javascript - Ako zakázať HTML odkazy
Mám tlačidlo s odkazom vo vnútri <td>, ktoré musím zakázať. Toto funguje v IE, ale nefunguje vo Firefoxe a Chrome.
Vyskúšal som všetko nasledovné, ale na Firefoxe to nefunguje (používam js 1.4.2):
$(".myLink").attr('disabled', 'disabled');
$(".myLink").attr('disabled', true);
$(".myLink").attr('disabled', 'true');
Poznámka - Nemôžem odregistrovať klikaciu funkciu pre značku anchor, pretože je registrovaná dynamicky. A MUSÍM ZOBRAZIŤ ODKAZ V NEAKTÍVNOM REŽIME.
Odpoveď č. 1
Nemôžete zakázať odkaz (prenosným spôsobom). Môžete použiť jednu z týchto techník (každá s vlastnými výhodami a nevýhodami).
Spôsob CSS
Toto by mala byť správna cesta (ale pozri neskôr), ako to urobiť, keď väčšina prehliadačov to bude podporovať:
a.disabled {
pointer-events: none;
}
To je to, čo napríklad robí Bootstrap 3.x. V súčasnosti (2016) je to dobre podporované iba v prehliadačoch Chrome, Firefox a Opera (19+). Internet Explorer začal toto podporovať od verzie 11, ale nie pre odkazy, avšak je to dostupné v vonkajšom prvku, ako je:
span.disable-links {
pointer-events: none;
}
S :
<span class="disable-links"><a href="#">...</a></span>
Obchádzka
Pravdepodobne budeme musieť definovať CSS triedu pre pointer-events: none, ale čo ak namiesto CSS triedy znovu použijeme atribút disabled? Striktne vzaté, disabled nie je podporovaný pre <a>, ale prehliadače sa nebudú sťažovať na neznáme atribúty. Použitím atribútu disabled IE ignoruje pointer-events, ale rešpektuje špecifický IE atribút disabled; ostatné CSS kompatibilné prehliadače ignorujú neznámy atribút disabled a rešpektujú pointer-events. Ľahšie sa to píše než vysvetľuje:
a[disabled] {
pointer-events: none;
}
Ďalšou možnosťou pre IE 11 je nastaviť display prvkov odkazov na block alebo inline-block:
<a style="pointer-events: none; display: inline-block;" href="#">...</a>
Všimnite si, že toto môže byť prenosné riešenie, ak potrebujete podporovať IE (a môžete zmeniť svoj HTML), ale...
Všetko vyššie uvedené berte na vedomie, prosím, že pointer-events vypína iba... události ukazovateľa. Odkazy budú stále dostupné cez klávesnicu, potom je tiež potrebné aplikovať jednu z ďalších techník popísaných tu.
Zamerať sa
V spojení s vyššie popísanou technikou CSS môžete použiť tabindex neštandardným spôsobom, aby sa zabránilo zaostreniu na prvok:
<a href="#" disabled tabindex="-1">...</a>
Nikdy som neoveroval jeho kompatibilitu s viacerými prehliadačmi, takže ho možno budete chcieť vyskúšať sami pred jeho použitím. Má výhodu, že funguje bez JavaScriptu. Bohužiaľ (ale očividne) sa tabindex nedá meniť cez CSS.
Zachytiť kliknutia
Použite href na JavaScriptovú funkciu, skontrolujte podmienku (alebo samotný atribút disabled) a v prípade potreby nerobte nič.
$("td > a").on("click", function(event){
if ($(this).is("[disabled]")) {
event.preventDefault();
}
});
Ak chcete zakázať odkazy, urobte toto:
$("td > a").attr("disabled", "disabled");
Ak ich chcete znova povoliť:
$("td > a").removeAttr("disabled");
Ak chcete namiesto .is("[disabled]") použiť .attr("disabled") != undefined (jQuery 1.6+ vždy vráti undefined, keď atribút nie je nastavený), ale is() je oveľa jasnejšie (ďakujeme Daveovi Stewartovi za tento tip). Upozorňujem, že tu používam atribút disabled neštandardným spôsobom, ak vám na tom záleží, nahraďte atribút triedou a nahraďte .is("[disabled]") pomocou .hasClass("disabled") (pridávanie a odstraňovanie pomocou addClass() a removeClass()).
Zoltán Tamási poznamenal v komentári, že "v niektorých prípadoch je udalosť kliknutia už viazaná na nejakú "skutočnú" funkciu (napríklad pri použití knockoutjs). V takom prípade môže poradie spracovania udalostí spôsobiť určité problémy. Preto som implementoval nefunkčné odkazy tak, že som na udalosti touchstart, mousedown a keydown odkazu priradil obslužnú funkciu, ktorá vracia false. Má to určité nevýhody (zabránia posúvaniu dotykom, ktoré začalo na odkaze)", ale spracovanie udalostí klávesnice má aj výhodu, že zabraňuje navigácii pomocou klávesnice.
Všimnite si, že ak href nie je vymazané, je možné, aby používateľ manuálne navštívil túto stránku.
Vymazať odkaz
Vymažte atribút href. S týmto kódom nepridávate obslužnú funkciu udalosti, ale meníte samotný odkaz. Použite tento kód na deaktiváciu odkazov:
$("td > a").each(function() {
this.data("href", this.attr("href"))
.attr("href", "javascript:void(0)")
.attr("disabled", "disabled");
});
A tento na ich opätovné povolenie:
$("td > a").each(function() {
this.attr("href", this.data("href")).removeAttr("disabled");
});
Osobne sa mi toto riešenie veľmi nepáči (ak nemusíte robiť viac s nefunkčnými odkazmi), ale môže byť kompatibilnejšie kvôli rôznym spôsobom, ako sledovať odkaz.
Falošný obsluhovač kliknutí
Pridajte/odstráňte funkciu onclick, kde return false, odkaz nebude nasledovaný. Na deaktiváciu odkazov:
$("td > a").attr("disabled", "disabled").on("click", function() {
return false;
});
Ak ich chcete znovu povoliť:
$("td > a").removeAttr("disabled").off("click");
Nemyslím si, že by existoval dôvod uprednostniť toto riešenie namiesto toho prvého.
Štylizovanie
Štýlovanie je ešte jednoduchšie, bez ohľadu na riešenie, ktoré používate na deaktiváciu odkazu, pridali sme atribút disabled, takže môžete použiť nasledujúce pravidlo CSS:
a[disabled] {
color: gray;
}
Ak používate triedu namiesto atribútu:
a.disabled {
color: gray;
}
Ak používate UI rámec, môžete si všimnúť, že deaktivované odkazy nie sú správne štýlované. Bootstrap 3.x napríklad rieši tento scenár a tlačidlo je správne štýlované ako s atribútom disabled, tak aj s triedou .disabled. Ak však odkaz vymažete (alebo použijete jednu z ostatných techník JavaScriptu), musíte sa tiež postarať o štýlovanie, pretože <a> bez href sa stále zobrazuje ako povolený.
Prístupné bohaté internetové aplikácie (ARIA)
Nezabudnite tiež pridať atribút aria-disabled="true" spolu s atribútom/triedou disabled.
Odpoveď č. 2
Dostal som opravu v CSS.
td.disabledAnchor a{
pointer-events: none !important;
cursor: default;
color:Gray;
}
Uvedený CSS kód, keď sa aplikuje na značku anchor, deaktivuje udalosť kliknutia.
Pre podrobnosti si pozrite tento odkaz
Odpoveď č. 3
Vďaka všetkým, ktorí zverejnili riešenia (najmä @AdrianoRepetti), kombinoval som niekoľko prístupov, aby som poskytol trochu pokročilejšiu funkcionalitu disabled (a funguje naprieč prehliadačmi). Kód je nižšie (ako ES2015, tak aj coffeescript podľa vašej preferencie).
Toto zabezpečuje viacero úrovní obrany, takže kotvy označené ako zakázané sa skutočne správajú týmto spôsobom. Použitím tohto prístupu získate kotvu, ktorú nemôžete:
- klik
- tab a stlač return
- Tabulátorovaním naň sa presunie fokus na ďalší prvok, ktorý môže získať fokus
- je si vedomý, či je kotva následne povolená
Ako
Zahrňte tento CSS, pretože je to prvá línia obrany. Predpokladá sa, že selektor, ktorý používate, je
a.disableda.disabled { pointer-events: none; cursor: default; }Ďalej, na inicializáciu tejto triedy pri pripravenosti (s voliteľným selektorom):
new AnchorDisabler()
Trieda ES2015
npm install -S key.jsimport {Key, Keycodes} from 'key.js'
export default class AnchorDisabler {
constructor (config = { selector: 'a.disabled' }) {
this.config = config
$(this.config.selector)
.click((ev) => this.onClick(ev))
.keyup((ev) => this.onKeyup(ev))
.focus((ev) => this.onFocus(ev))
}
isStillDisabled (ev) {
// since disabled can be a class or an attribute, and it can be dynamically removed, always recheck on a watched event
let target = $(ev.target)
if (target.hasClass('disabled') || target.prop('disabled') == 'disabled') {
return true
}
else {
return false
}
}
onFocus (ev) {
// if an attempt is made to focus on a disabled element, just move it along to the next focusable one.
if (!this.isStillDisabled(ev)) {
return
}
let focusables = $(':focusable')
if (!focusables) {
return
}
let current = focusables.index(ev.target)
let next = null
if (focusables.eq(current + 1).length) {
next = focusables.eq(current + 1)
} else {
next = focusables.eq(0)
}
if (next) {
next.focus()
}
}
onClick (ev) {
// disabled could be dynamically removed
if (!this.isStillDisabled(ev)) {
return
}
ev.preventDefault()
return false
}
onKeyup (ev) {
// We are only interested in disabling Enter so get out fast
if (Key.isNot(ev, Keycodes.ENTER)) {
return
}
// disabled could be dynamically removed
if (!this.isStillDisabled(ev)) {
return
}
ev.preventDefault()
return false
}
}
Trieda Coffeescript:
class AnchorDisabler
constructor: (selector = 'a.disabled') ->
$(selector).click(@onClick).keyup(@onKeyup).focus(@onFocus)
isStillDisabled: (ev) =>
### since disabled can be a class or an attribute, and it can be dynamically removed, always recheck on a watched event ###
target = $(ev.target)
return true if target.hasClass('disabled')
return true if target.attr('disabled') is 'disabled'
return false
onFocus: (ev) =>
### if an attempt is made to focus on a disabled element, just move it along to the next focusable one. ###
return unless @isStillDisabled(ev)
focusables = $(':focusable')
return unless focusables
current = focusables.index(ev.target)
next = (if focusables.eq(current + 1).length then focusables.eq(current + 1) else focusables.eq(0))
next.focus() if next
onClick: (ev) =>
# disabled could be dynamically removed
return unless @isStillDisabled(ev)
ev.preventDefault()
return false
onKeyup: (ev) =>
# 13 is the js key code for Enter, we are only interested in disabling that so get out fast
code = ev.keyCode or ev.which
return unless code is 13
# disabled could be dynamically removed
return unless @isStillDisabled(ev)
ev.preventDefault()
return false
