Czy mogę wyłączyć efekt CSS: najechanie kursorem za pomocą JavaScript?

99

Próbuję uniemożliwić przeglądarce korzystanie z :hoverefektu CSS za pomocą JavaScript.

Po ustawieniu ai a:hoverstyle w moim CSS, ponieważ chcę skutek najechania, jeśli JS nie jest dostępna. Ale jeśli JS jest dostępny, chcę nadpisać mój efekt najechania kursorem CSS na płynniejszy (na przykład używając wtyczki kolorów jQuery).

Próbowałem tego:

$("ul#mainFilter a").hover(
     function(e){ e.preventDefault(); ...do my stuff... }, 
     function(e){ e.preventDefault(); ...do my stuff... });

Próbowałem też z tym return false;, ale to nie działa.

Oto przykład mojego problemu: http://jsfiddle.net/4rEzz/ . Łącze powinno po prostu zniknąć bez szarzenia.

Jak wspomniał Fudgey, obejściem byłoby zresetowanie stylów aktywowania przy użyciu, .css()ale musiałbym nadpisać każdą pojedynczą właściwość określoną w CSS (patrz tutaj: http://jsfiddle.net/raPeX/1/ ). Szukam generycznego rozwiązania.

Czy ktoś wie, jak to zrobić?

PS: Nie chcę nadpisywać każdego stylu, który ustawiłem dla najechania.

meo
źródło

Odpowiedzi:

136

Obawiam się, że nie ma czystego ogólnego rozwiązania JavaScript. JavaScript nie jest w stanie wyłączyć :hoversamego stanu CSS .

Możesz jednak wypróbować następujące alternatywne obejście. Jeśli nie masz nic przeciwko odrobinie grzebania w HTML i CSS, oszczędza to konieczności ręcznego resetowania każdej właściwości CSS za pomocą JavaScript.

HTML

<body class="nojQuery">

CSS

/* Limit the hover styles in your CSS so that they only apply when the nojQuery 
class is present */

body.nojQuery ul#mainFilter a:hover {
    /* CSS-only hover styles go here */
}

JavaScript

// When jQuery kicks in, remove the nojQuery class from the <body> element, thus
// making the CSS hover styles disappear.

$(function(){}
    $('body').removeClass('nojQuery');
)
Paul D. Waite
źródło
5
To rozwiązanie podoba mi się bardziej niż rozwiązania noscript, ponieważ działa, gdy CSS jest całkowicie zawarty w plikach zewnętrznych, a także działa podczas ładowania strony, jeśli CSS ładuje się najpierw, ale JS nie ładuje się później. Używanie jQuery do „stopniowego ulepszania” rzeczy często skutkuje stronami, które nie działają dobrze, jeśli klikniesz na coś przed zakończeniem ładowania. Nawet z szybką przeglądarką i szybkim łączem widzę to często.
Mr. Shiny and New 安 宇
@Pan. Błyszczące i nowe: zgadzam się, podoba mi się to również bardziej niż moje rozwiązanie! Nie jestem pewien, dlaczego wcześniej nie zauważyłem elegancji tego ...
Josh
3
„Podoba mi się to rozwiązanie bardziej niż rozwiązania noscript, ponieważ działa, gdy CSS jest całkowicie zawarty w plikach zewnętrznych” - tak samo działa <noscript>rozwiązanie. Po prostu umieszczasz <link>tagi w swoim <noscript>, zamiast <style>tagów. Moje rozwiązanie pozwala jednak zachować wszystko w jednym pliku arkusza stylów, a nie w wielu plikach.
Paul D. Waite
to nie jest dokładnie to, czego szukałem, ale myślę, że to rozwiązanie jest najlepszym kompromisem! Dziękuję wam wszystkim
meo
możesz również skopiować ten sam styl z inną nazwą i za pomocą jquery zaznaczyć wszystkie elementy z tą klasą, usunąć klasę i zastąpić ją klasą copy.
chepe263
14

Użyj drugiej klasy, do której przypisano tylko dymek:

HTML

 <a class="myclass myclass_hover" href="#">My anchor</a>

CSS

 .myclass { 
   /* all anchor styles */
 }
 .myclass_hover:hover {
   /* example color */
   color:#00A;
 }

Teraz możesz użyć Jquery do usunięcia klasy, na przykład jeśli element został kliknięty:

JQUERY

 $('.myclass').click( function(e) {
    e.preventDefault();
    $(this).removeClass('myclass_hover');
 });

Mam nadzieję, że ta odpowiedź jest pomocna.

Kai Noack
źródło
3
plus 1. nie jest ortodoksyjny, ale rozwiązuje problem w dość wzniosły sposób.
Jim Tollan
11

Możesz samodzielnie manipulować arkuszami stylów i regułami arkuszy stylów za pomocą javascript

var sheetCount = document.styleSheets.length;
var lastSheet = document.styleSheets[sheetCount-1];
var ruleCount;
if (lastSheet.cssRules) { // Firefox uses 'cssRules'
    ruleCount = lastSheet.cssRules.length;
}
else if (lastSheet.rules) { / /IE uses 'rules'
    ruleCount = lastSheet.rules.length;
}
var newRule = "a:hover { text-decoration: none !important; color: #000 !important; }";
// insert as the last rule in the last sheet so it
// overrides (not overwrites) previous definitions
lastSheet.insertRule(newRule, ruleCount);

Uczynienie atrybutów! Ważnymi i uczynienie ich ostatnią definicją CSS powinno nadpisać wszelkie poprzednie definicje, chyba że jest to bardziej szczegółowe. W takim przypadku może być konieczne wstawienie większej liczby reguł.

Stephen P.
źródło
1
Możesz też umieścić wszystkie reguły noscript w jednym arkuszu stylów, a następnie wyłączyć arkusz stylów z poziomu javascript.
Sean Hogan
2
Albo umieścić <link>tag arkusza stylów noscript wewnątrz <noscript>elementu? To zadziałałoby, prawda?
Paul D. Waite
1
Lub usuń „naruszającą” regułę: developer.mozilla.org/en/DOM/stylesheet.deleteRule
RoToRa
1
Nawet IE5 to potrafi. Jego metoda nazywa się inaczej, ale powinna działać: msdn.microsoft.com/en-us/library/ms531195%28v=vs.85%29.aspx . Nie sprawdzałem innych przeglądarek, ale domyślam się, że wszystkie współczesne przeglądarki implementują ten standard.
RoToRa
W przeglądarce Firefox dostajęError: The operation is insecure.
Alex W
11

Jest to podobne do odpowiedzi aSeptik, ale co z tym podejściem? Owiń kod CSS, który chcesz wyłączyć, używając JavaScript w <noscript>tagach. W ten sposób, jeśli javaScript jest wyłączony, :hoverzostanie użyty CSS , w przeciwnym razie zostanie użyty efekt JavaScript.

Przykład:

<noscript>
<style type="text/css">
ul#mainFilter a:hover {
  /* some CSS attributes here */
}
</style>
</noscript>
<script type="text/javascript">
$("ul#mainFilter a").hover(
     function(o){ /* ...do your stuff... */ }, 
     function(o){ /* ...do your stuff... */ });
</script>
Josh
źródło
4

Użyłem not()operatora CSS i addClass()funkcji jQuery . Oto przykład, kiedy klikniesz element listy, nie będzie on już najeżdżać:

Na przykład:

HTML

<ul class="vegies">
    <li>Onion</li>
    <li>Potato</li>
    <li>Lettuce</li>
<ul>

CSS

.vegies li:not(.no-hover):hover { color: blue; }

jQuery

$('.vegies li').click( function(){
    $(this).addClass('no-hover');
});
ColdTuna
źródło
3

Użyłbym CSS, aby zapobiec zmianie wyglądu linku przez zdarzenie: hover.

a{
  font:normal 12px/15px arial,verdana,sans-serif;
  color:#000;
  text-decoration:none;
}

Ten prosty CSS oznacza, że ​​linki zawsze będą czarne i nie będą podkreślone. Nie potrafię powiedzieć na podstawie pytania, czy jedyną rzeczą, którą chcesz kontrolować, jest zmiana wyglądu.

Christophera Altmana
źródło
dobrze, że występuje efekt: hover, jeśli JS nie jest dostępny na kliencie. Ale jeśli tak, muszę go nadpisać. Ustawiłem klasę: hover w moim css, po prostu chcę ją wyłączyć.
meo
@meo: Nie możesz wyłączyć klas CSS psuedo, ale możesz je zastąpić, ustawiając wszystkie style linków tak, aby miały ten sam wygląd / parametry. Zarówno ta odpowiedź, jak i moja odpowiedź robią to, tylko na różne sposoby.
Mottie
3

Polecam zastąpić wszystkie :hoverwłaściwości, :activegdy wykryjesz, że urządzenie obsługuje dotyk. Po prostu wywołaj tę funkcję, gdy zrobisz to jako touch().

function touch() {
  if ('ontouchstart' in document.documentElement) {
    for (var sheetI = document.styleSheets.length - 1; sheetI >= 0; sheetI--) {
      var sheet = document.styleSheets[sheetI];
      if (sheet.cssRules) {
        for (var ruleI = sheet.cssRules.length - 1; ruleI >= 0; ruleI--) {
          var rule = sheet.cssRules[ruleI];

          if (rule.selectorText) {
            rule.selectorText = rule.selectorText.replace(':hover', ':active');
          }
        }
      }
    }
  }
}
Shobhit Sharma
źródło
U mnie działa świetnie. Dzięki!
Inversion
1

Spróbuj po prostu ustawić kolor linku:

$("ul#mainFilter a").css('color','#000');

Edytuj: lub jeszcze lepiej, użyj CSS, jak zasugerował Christopher

Mottie
źródło
jsfiddle.net/raPeX Zrobiłem przykład. Działa, ale to trochę głupie. musiałbym pobrać każdą wartość CSS i dodać je jako styl? Musi być lepszy sposób. Nie chcę tego robić. ale +1 za podpowiedź
meo
Cześć Meo, nie, nie, mój powyższy kod był skierowany na konkretny link, ponieważ myślałem, że właśnie tego chcesz. Możesz uogólnić to bardziej, używając azamiast tego, ul#mainFilter aczy to masz na myśli, czy też mówisz, że każdy link na stronie ma inny kolor?
Mottie
Zaktualizowałem Twoje demo z komentarzami, aby pokazać, o co mi chodzi: jsfiddle.net/raPeX/2
Mottie
Już to rozumiem, dziękuję. Ale problem polega na tym, że po najechaniu kursorem zmienia się nie tylko kolor, czasami jest to tło, granica, a czasem nawet wysokość linii. Dlatego łatwiej byłoby mi po prostu zapobiec zawisaniu, aby nadpisać każdy pojedynczy efekt najechania.
meo
Częściowa poprawka do tego pomysłu: można utworzyć regułę css, która wybiera dla a.jsOverride:hoverniej wszystkie cechy css, więc js musiałby po prostu dodać tę jsOverrideklasę do wszystkich linków, gdy strona się wczyta ...
grossvogel
1

Właściwie innym sposobem rozwiązania tego problemu może być nadpisanie CSS z insertRule.

Daje możliwość wstrzykiwania reguł CSS do istniejącego / nowego arkusza stylów. W moim konkretnym przykładzie wyglądałoby to tak:

//creates a new `style` element in the document
var sheet = (function(){
  var style = document.createElement("style");
  // WebKit hack :(
  style.appendChild(document.createTextNode(""));
  // Add the <style> element to the page
  document.head.appendChild(style);
  return style.sheet;
})();

//add the actual rules to it
sheet.insertRule(
 "ul#mainFilter a:hover { color: #0000EE }" , 0
);

Demo z moim oryginalnym przykładem sprzed 4 lat: http://jsfiddle.net/raPeX/21/

meo
źródło