web-dev-qa-db-fra.com

jQuery quand l'élément devient visible

En gros, je me demande s’il existe un moyen d’exécuter automatiquement une fonction lorsqu’un élément devient masqué ou visible, non pas lorsque l'utilisateur clique, mais automatiquement dans un autre script.

Je ne veux pas que cela ne soit exécuté qu'une seule fois, car les éléments (comme un curseur) changent constamment de visible à caché.

Est-ce que jQuery peut faire quelque chose avec bind? Telle que lier la visibilité de l'élément à une fonction (je ne sais pas comment l'écrire)

Si vous avez besoin que je vous explique plus en détail ce que j'essaie de faire, faites-le-moi savoir. Merci

Pseudocode: 

$('#element').bind('display:none', function);
function(){
    //do something when element is display:none
}

$('#element').bind('display:block', function2);
function2(){
    //do opposite of function
}
43
sl133

JQuery ne contient aucun événement permettant de détecter les modifications CSS.
Reportez-vous ici: événement de type onHide () dans jQuery

C'est possible:

Le module DOM L2 Events définit les événements de mutation; L'un d'entre eux - DOMAttrModified est celui qu'il vous faut. Certes, ils ne sont pas largement implémentés, mais sont pris en charge dans au moins les navigateurs Gecko et Opera.
Source: Détection d’événement lorsque la propriété css a été modifiée à l’aide de Jquery

Sans événements, vous pouvez utiliser la fonction setInterval, comme ceci:

var maxTime = 5000, // 5 seconds
    startTime = Date.now();

var interval = setInterval(function () {
        if ($('#element').is(':visible')) {
            // visible, do something
            clearInterval(interval);
        } else {
            // still hidden
            if (Date.now() - startTime > maxTime) {
                // hidden even after 'maxTime'. stop checking.
                clearInterval(interval);
            }
        }
    },
    100 // 0.1 second (wait time between checks)
);

Notez que l'utilisation de setInterval de cette manière, pour garder un œil sur vous, peut affecter les performances de votre page.

7 juillet 2018:
Étant donné que cette réponse obtient de la visibilité et que plus de votes ont été votés récemment, voici une mise à jour supplémentaire sur la détection des modifications css: 

Les événements de mutation ont maintenant été remplacés par Mutation Observer, plus performant.

L'interface MutationObserver permet de surveiller les modifications apportées à l'arborescence DOM. Il est conçu pour remplacer l'ancienne fonctionnalité d'événements de mutation qui faisait partie de la spécification DOM3 Events. 

Voir: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver

26
P5Coder
(function() {
    var ev = new $.Event('display'),
        orig = $.fn.css;
    $.fn.css = function() {
        orig.apply(this, arguments);
        $(this).trigger(ev);
    }
})();

$('#element').bind('display', function(e) {
    alert("display has changed to :" + $(this).attr('style') );
});

$('#element').css("display", "none")// i change the style in this line !!
$('#element').css("display", "block")// i change the style in this line !!

http://fiddle.jshell.net/prollygeek/gM8J2/3/

les changements seront alertés.

17
ProllyGeek

J'ai essayé cela sur firefox, fonctionne http://jsfiddle.net/Tm26Q/1/

$(function(){
 /** Just to mimic a blinking box on the page**/
  setInterval(function(){$("div#box").hide();},2001);
  setInterval(function(){$("div#box").show();},1000);
 /**/
});

$("div#box").on("DOMAttrModified",
function(){if($(this).is(":visible"))console.log("visible");});

METTRE À JOUR

Actuellement, les événements de mutation (comme DOMAttrModified utilisés dans la solution ) Sont remplacés par MutationObserver , vous pouvez l'utiliser pour. détecter les changements de nœud DOM comme dans le cas ci-dessus.

4
user2587132

Je viens d'améliorer ProllyGeek `s 

Quelqu'un peut trouver cela utile… vous pouvez accéder à l'événement displayChanged(event, state) lorsque .show(), .hide() ou .toggle() est appelé sur l'élément

(function() {
  var eventDisplay = new $.Event('displayChanged'),
    origShow = $.fn.show,
    origHide = $.fn.hide;
  //
  $.fn.show = function() {
    origShow.apply(this, arguments);
    $(this).trigger(eventDisplay,['show']);
  };
  //
  $.fn.hide = function() {
    origHide.apply(this, arguments);
    $(this).trigger(eventDisplay,['hide']);
  };
  //
})();

$('#header').on('displayChanged', function(e,state) {
      console.log(state);
});

$('#header').toggle(); // .show() .hide() supported
2
django

Un événement personnalisé catch-all jQuery basé sur une extension de ses méthodes principales comme proposé par différentes personnes dans ce fil de discussion:

(function() {
    var ev = new $.Event('event.css.jquery'),
        css = $.fn.css,
        show = $.fn.show,
        hide = $.fn.hide;

    // extends css()
    $.fn.css = function() {
        css.apply(this, arguments);
        $(this).trigger(ev);
    };

    // extends show()
    $.fn.show = function() {
        show.apply(this, arguments);
        $(this).trigger(ev);
    };

    // extends hide()
    $.fn.hide = function() {
        hide.apply(this, arguments);
        $(this).trigger(ev);
    };
})();

Une bibliothèque externe utilise alors sth comme $('selector').css('property', value).

Comme nous ne voulons pas modifier le code de la bibliothèque mais que FAISONS voulons étendre son comportement, nous le faisons comme:

$('#element').on('event.css.jquery', function(e) {
    // ...more code here...
});

Exemple: l'utilisateur clique sur un panneau construit par une bibliothèque. La bibliothèque affiche/masque les éléments en fonction de l’interaction de l’utilisateur. Nous voulons ajouter un capteur qui montre que qc a été masqué/affiché à cause de cette interaction et qui devrait être appelé après la fonction de la bibliothèque.

Un autre exemple: jsfiddle .

0
centurian

J'aime le plugin https://github.com/hazzik/livequery Cela fonctionne sans timers!

Utilisation simple

$('.some:visible').livequery( function(){ ... } );

Mais vous devez réparer une erreur. Remplacer la ligne

$jQlq.registerPlugin('append', 'prepend', 'after', 'before', 'wrap', 'attr', 'removeAttr', 'addClass', 'removeClass', 'toggleClass', 'empty', 'remove', 'html', 'prop', 'removeProp');

à

$jQlq.registerPlugin('show', 'append', 'prepend', 'after', 'before', 'wrap', 'attr', 'removeAttr', 'addClass', 'removeClass', 'toggleClass', 'empty', 'remove', 'html', 'prop', 'removeProp');
0
Rabotyahoff