Événement jQuery pour déclencher une action lorsqu'un div est rendu visible

J'utilise jQuery dans mon site et j'aimerais déclencher certaines actions lorsqu'une certaine div est rendue visible.

Est-il possible d'attacher une sorte de gestionnaire d'événements "invisible" à des divs arbitraires et de certains codes s'exécutent lorsque les div sont rendus visibles?

J'aimerais quelque chose comme le pseudocode suivant:

$(function() { $('#contentDiv').isvisible(function() { alert("do something"); }); }); 

Le code d'alerte ("faire quelque chose") ne doit pas déclencher jusqu'à ce que le contenuDiv soit rendu visible.

Merci.

Vous pouvez toujours ajouter à la méthode originale .show () afin de ne pas déclencher d'événements chaque fois que vous montrez quelque chose ou si vous en avez besoin pour travailler avec le code hérité:

Extension Jquery:

 jQuery(function($) { var _oldShow = $.fn.show; $.fn.show = function(speed, oldCallback) { return $(this).each(function() { var obj = $(this), newCallback = function() { if ($.isFunction(oldCallback)) { oldCallback.apply(obj); } obj.trigger('afterShow'); }; // you can trigger a before show if you want obj.trigger('beforeShow'); // now use the old function to show the element passing the new callback _oldShow.apply(obj, [speed, newCallback]); }); } }); 

Exemple d'utilisation:

 jQuery(function($) { $('#test') .bind('beforeShow', function() { alert('beforeShow'); }) .bind('afterShow', function() { alert('afterShow'); }) .show(1000, function() { alert('in show callback'); }) .show(); }); 

Cela vous permet effectivement de faire quelque chose avant & afficher et afficher après tout en exécutant le comportement normal de la méthode originale .show ().

Vous pouvez également créer une autre méthode, de sorte que vous ne devez pas remplacer la méthode originale .show ().

Il n'y a pas d'événement natif auquel vous pouvez vous connecter, mais vous pouvez déclencher un événement à partir de votre script après avoir rendu le div visible en utilisant le. Fonction de déclenchement

par exemple

 //declare event to run when div is visible function isVisible(){ //do something } //hookup the event $('#someDivId').bind('isVisible', isVisible); //show div and trigger custom event in callback when div is visible $('#someDivId').show('slow', function(){ $(this).trigger('isVisible'); }); 

Le problème est traité par les observateurs de mutations DOM . Ils vous permettent de lier un observateur (une fonction) à des événements de changement de contenu, de texte ou d'attributs d'éléments dom.

Avec la sortie d'IE11, tous les principaux navigateurs prennent en charge cette fonctionnalité, consultez http://caniuse.com/mutationobserver

Le code d'exemple est le suivant:

 $(function() { $('#show').click(function() { $('#testdiv').show(); }); var observer = new MutationObserver(function(mutations) { alert('Attributes changed!'); }); var target = document.querySelector('#testdiv'); observer.observe(target, { attributes: true }); }); 
 <div id="testdiv" style="display:none;">hidden</div> <button id="show">Show hidden div</button> <script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js"></script> 

Vous pouvez utiliser le plugin de connexion en direct de jQuery. Et écrivez le code comme suit:

 $('#contentDiv:visible').livequery(function() { alert("do something"); }); 

Ensuite, chaque fois que le contenuDiv est visible, "faire quelque chose" sera alerté!

La solution redsquare est la bonne réponse logique.

Mais en tant que solution IN THEORY, vous pouvez coder une fonction qui sélectionne les éléments classés par la classe .visibilityCheck ( pas tous les éléments visibles ) et vérifie leur valeur de propriété de visibility ; Si true alors, faites quelque chose. D'accord?
Ensuite, la fonction doit être effectuée périodiquement à l'aide de la fonction setInterval() . Comme vous le savez, vous pouvez arrêter la minuterie en utilisant clearInterval() et l'ID de la minuterie lors de l'appel réussi de la fonction.

 function foo(){ $('.visibilityCheck').each(function(){ if($(this).is(':visible')){ //do something } }); } //foo() window.setInterval(foo, 100); 

De plus, vous pouvez faire des améliorations de performance à ce sujet, mais la solution est essentiellement ignorée pour être utilisée en action, je pense.

Si vous souhaitez déclencher l'événement sur tous les éléments (et éléments enfants) réalisés visiblement par $ .show, basculer, toggleClass, addClass ou removeClass:

 $.each(["show", "toggle", "toggleClass", "addClass", "removeClass"], function(){ var _oldFn = $.fn[this]; $.fn[this] = function(){ var hidden = this.find(":hidden").add(this.filter(":hidden")); var result = _oldFn.apply(this, arguments); hidden.filter(":visible").each(function(){ $(this).triggerHandler("show"); //No bubbling }); return result; } }); 

Et maintenant, votre élément:

 $("#myLazyUl").bind("show", function(){ alert(this); }); 

Vous pouvez ajouter des remplacements à des fonctions jQuery supplémentaires en les ajoutant au tableau en haut (comme "attr")

Un déclencheur de l'événement hide / show basé sur Glena ideea: supprimé le bascule parce qu'il déclenche show / hide et nous ne voulons pas 2 incendies pour un événement

 $(function(){ $.each(["show","hide", "toggleClass", "addClass", "removeClass"], function(){ var _oldFn = $.fn[this]; $.fn[this] = function(){ var hidden = this.find(":hidden").add(this.filter(":hidden")); var visible = this.find(":visible").add(this.filter(":visible")); var result = _oldFn.apply(this, arguments); hidden.filter(":visible").each(function(){ $(this).triggerHandler("show"); }); visible.filter(":hidden").each(function(){ $(this).triggerHandler("hide"); }); return result; } }); }); 

Le code suivant (tiré de http://maximeparmentier.com/2012/11/06/bind-show-hide-events-with-jquery/ ) vous permettra d'utiliser $('#someDiv').on('show', someFunc); .

 (function ($) { $.each(['show', 'hide'], function (i, ev) { var el = $.fn[ev]; $.fn[ev] = function () { this.trigger(ev); return el.apply(this, arguments); }; }); })(jQuery); 

J'ai eu ce même problème et j'ai créé un plugin jQuery pour le résoudre pour notre site.

https://github.com/shaunbowe/jquery.visibilityChanged

Voici comment vous l'utiliserez en fonction de votre exemple:

 $('#contentDiv').visibilityChanged(function(element, visible) { alert("do something"); }); 

Utilisez jQuery Waypoints:

 $('#contentDiv').waypoint(function() { alert('do something'); }); 

D'autres exemples sur le site de jQuery Waypoints .

Vous pouvez également essayer jQuery apparaître un plugin comme mentionné dans le thread parallèle https://stackoverflow.com/a/3535028/741782

Ce support facilite et déclenche l'événement après l'animation effectuée! [Testé sur jQuery 2.2.4]

 (function ($) { $.each(['show', 'hide', 'fadeOut', 'fadeIn'], function (i, ev) { var el = $.fn[ev]; $.fn[ev] = function () { var result = el.apply(this, arguments); var _self=this; result.promise().done(function () { _self.triggerHandler(ev, [result]); //console.log(_self); }); return result; }; }); })(jQuery); 

Inspiré par http://viralpatel.net/blogs/jquery-trigger-custom-event-show-hide-element/

Il existe un plugin jQuery disponible pour regarder la modification des attributs DOM,

https://github.com/darcyclarke/jQuery-Watch-Plugin

Le plugin enveloppe Tout ce qu'il faut faire est bind MutationObserver

Vous pouvez ensuite l'utiliser pour regarder le div en utilisant:

 $("#selector").watch('css', function() { console.log("Visibility: " + this.style.display == 'none'?'hidden':'shown')); //or any random events }); 

J'ai changé le déclencheur d'événement hide / show de Catalint basé sur l'idée de Glenns. Mon problème était que j'ai une application modulaire. Je change entre les modules qui montrent et cachent les parents divs. Ensuite, lorsque je cache un module et en montre un autre, avec sa méthode, j'ai un délai visible lorsque je change entre les modules. J'ai seulement besoin de liten cet événement, et dans certains enfants spéciaux. J'ai donc décidé de ne notifier que les enfants avec la classe "displayObserver"

 $.each(["show", "hide", "toggleClass", "addClass", "removeClass"], function () { var _oldFn = $.fn[this]; $.fn[this] = function () { var hidden = this.find(".displayObserver:hidden").add(this.filter(":hidden")); var visible = this.find(".displayObserver:visible").add(this.filter(":visible")); var result = _oldFn.apply(this, arguments); hidden.filter(":visible").each(function () { $(this).triggerHandler("show"); }); visible.filter(":hidden").each(function () { $(this).triggerHandler("hide"); }); return result; } }); 

Ensuite, quand un enfant veut écouter l'événement "show" ou "hide", je dois l'ajouter à la classe "displayObserver", et quand il ne veut pas continuer à l'écouter, je l'enlève le cours

 bindDisplayEvent: function () { $("#child1").addClass("displayObserver"); $("#child1").off("show", this.onParentShow); $("#child1").on("show", this.onParentShow); }, bindDisplayEvent: function () { $("#child1").removeClass("displayObserver"); $("#child1").off("show", this.onParentShow); }, 

Je souhaite de l'aide

Une façon de le faire.
Fonctionne uniquement sur les changements de visibilité effectués par le changement de classe css, mais peuvent être étendus pour surveiller les changements d'attribut aussi.

 var observer = new MutationObserver(function(mutations) { var clone = $(mutations[0].target).clone(); clone.removeClass(); for(var i = 0; i < mutations.length; i++){ clone.addClass(mutations[i].oldValue); } $(document.body).append(clone); var cloneVisibility = $(clone).is(":visible"); $(clone).remove(); if (cloneVisibility != $(mutations[0].target).is(":visible")){ var visibilityChangedEvent = document.createEvent('Event'); visibilityChangedEvent.initEvent('visibilityChanged', true, true); mutations[0].target.dispatchEvent(visibilityChangedEvent); } }); var targets = $('.ui-collapsible-content'); $.each(targets, function(i,target){ target.addEventListener('visibilityChanged',VisbilityChanedEventHandler}); target.addEventListener('DOMNodeRemovedFromDocument',VisbilityChanedEventHandler }); observer.observe(target, { attributes: true, attributeFilter : ['class'], childList: false, attributeOldValue: true }); }); function VisbilityChanedEventHandler(e){console.log('Kaboom babe'); console.log(e.target); } 

Ma solution:

 ; (function ($) { $.each([ "toggle", "show", "hide" ], function( i, name ) { var cssFn = $.fn[ name ]; $.fn[ name ] = function( speed, easing, callback ) { if(speed == null || typeof speed === "boolean"){ var ret=cssFn.apply( this, arguments ) $.fn.triggerVisibleEvent.apply(this,arguments) return ret }else{ var that=this var new_callback=function(){ callback.call(this) $.fn.triggerVisibleEvent.apply(that,arguments) } var ret=this.animate( genFx( name, true ), speed, easing, new_callback ) return ret } }; }); $.fn.triggerVisibleEvent=function(){ this.each(function(){ if($(this).is(':visible')){ $(this).trigger('visible') $(this).find('[data-trigger-visible-event]').triggerVisibleEvent() } }) } })(jQuery); 

Utilisation d'exemple:

 if(!$info_center.is(':visible')){ $info_center.attr('data-trigger-visible-event','true').one('visible',processMoreLessButton) }else{ processMoreLessButton() } function processMoreLessButton(){ //some logic } 
 $( window ).scroll(function(e,i) { win_top = $( window ).scrollTop(); win_bottom = $( window ).height() + win_top; //console.log( win_top,win_bottom ); $('.onvisible').each(function() { t = $(this).offset().top; b = t + $(this).height(); if( t > win_top && b < win_bottom ) alert("do something"); }); }); 

J'espère que cela fera le travail de la manière la plus simple:

 $("#myID").on('show').trigger('displayShow'); $('#myID').off('displayShow').on('displayShow', function(e) { console.log('This event will be triggered when myID will be visible'); }); 

Ce qui m'a aidé ici est le dernier Polyfill de spécifications ResizeObserver :

 const divEl = $('#section60'); const ro = new ResizeObserver(() => { if (divEl.is(':visible')) { console.log("it's visible now!"); } }); ro.observe(divEl[0]); 

Notez que c'est crossbrowser et performant (pas de sondage).

 <div id="welcometo">Özhan</div> <input type="button" name="ooo" onclick="JavaScript: if(document.all.welcometo.style.display=='none') { document.all.welcometo.style.display=''; } else { document.all.welcometo.style.display='none'; }"> 

Ce contrôle automatique de code ne nécessite pas une requête visible ou un contrôle invisible