जब एक div दिखाई दे, तो कार्रवाई को ट्रिगर करने के लिए jQuery की घटना


312

मैं अपनी साइट में jQuery का उपयोग कर रहा हूं और मैं कुछ क्रियाओं को ट्रिगर करना चाहूंगा जब एक निश्चित div दिखाई दे।

क्या किसी प्रकार के "इस्विसिबल" ईवेंट हैंडलर को मनमाने ढंग से divs से जोड़ना संभव है और जब वे डिव को दृश्यमान बनाते हैं तो निश्चित कोड रन होते हैं?

मैं निम्नलिखित छद्मकोड जैसा कुछ चाहूंगा:

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

चेतावनी ("कुछ करें") कोड तब तक फायर नहीं करना चाहिए जब तक कि कंटेंटडिव वास्तव में दिखाई न दे।

धन्यवाद।


जवाबों:


190

आप हमेशा मूल .show () विधि में जोड़ सकते हैं ताकि आपको हर बार कुछ दिखाने के लिए घटनाओं को ट्रिगर न करना पड़े या यदि आपको विरासत कोड के साथ काम करने की आवश्यकता हो:

जेकरी विस्तार:

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]);
    });
  }
});

उपयोग उदाहरण:

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

यह प्रभावी रूप से आपको मूल .show () विधि के सामान्य व्यवहार को निष्पादित करते हुए भीShow और afterShow से पहले कुछ करने देता है।

आप एक और विधि भी बना सकते हैं ताकि आपको मूल .show () विधि को ओवरराइड न करना पड़े।


7
EDIT: इस विधि के साथ केवल एक नकारात्मक पहलू है: आपको सभी तरीकों के लिए समान "विस्तार" को दोहराना होगा जो तत्व को प्रकट करते हैं: शो (), स्लाइडडाउन () आदि। एक बार और इस समस्या को हल करने के लिए कुछ और सार्वभौमिक की आवश्यकता होती है सभी के बाद से, प्रतिनिधि () या लाइव () के लिए "तैयार" घटना होना असंभव है।
शाहरियार इमानोव

1
अच्छा, एकमात्र समस्या यह है कि fadeToइस कार्य को लागू करने के बाद फ़ंक्शन ठीक से काम नहीं करता है
ओमिड

9
आपका कोड नवीनतम jQuery के साथ काम नहीं करता है (इस टिप्पणी की तारीख में 1.7.1)। मैंने इस समाधान को नवीनतम jQuery के साथ काम करने के लिए थोड़ा हल किया है: stackoverflow.com/a/9422207/135968
mkmurray

1
एक अजाक्स प्रतिक्रिया द्वारा ट्रिगर दिव्य दृश्यता के साथ काम करने के लिए उस कोड को प्राप्त नहीं कर सकते।
जैकइन्फाइनी

यहाँ नौसिखिया। मुझे समझ में नहीं आता है कि obj (और newCallback) को फ़ंक्शन () घोषणा से बाहर क्यों संदर्भित किया जा सकता है जैसा कि आवेदन () में देखा जा सकता है। मुझे सिखाया गया था कि var के साथ घोषित करने से वैरिएबल लोकल हो जाते हैं, लेकिन "var" को हटाने से वे अपने आप ग्लोबल हो जाते हैं।
युता 73३

85

समस्या को DOM उत्परिवर्तन पर्यवेक्षकों द्वारा संबोधित किया जा रहा है । वे आपको बदलते तत्वों की सामग्री, पाठ या प्रमुख तत्वों की विशेषताओं की घटनाओं के लिए एक पर्यवेक्षक (एक फ़ंक्शन) को बांधने की अनुमति देते हैं।

IE11 की रिलीज़ के साथ, सभी प्रमुख ब्राउज़र इस सुविधा का समर्थन करते हैं, http://caniuse.com/mutationobserver की जाँच करें

उदाहरण कोड इस प्रकार है:

$(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>


3
यह एक दया है कि IE अभी तक इसका समर्थन नहीं करता है। caniuse.com/mutationobserver -> उन ब्राउज़र को देखने के लिए जो इसका समर्थन करते हैं।
ccsakuweb

2
यह वास्तव में काम करता है, और मुझे विरासत ब्राउज़रों का समर्थन करने की आवश्यकता नहीं है, इसलिए यह सही है! I'br ने उत्तर के JSFiddle प्रमाण को यहां जोड़ा: jsfiddle.net/DanAtkinson/26URF
Dan Atkinson

क्रोम में अच्छी तरह से काम करता है, लेकिन ब्लैकबेरी 10 कैस्केड वेबव्यू (अगर किसी और की परवाह करता है?) में काम नहीं करता है
गिआल्यूम जेंडर

1
यदि दृश्यता परिवर्तन की निगरानी के पूर्वज में विशेषता परिवर्तन के कारण होता है तो यह काम नहीं करता है।
माइकल

4
यह Chrome 51 में काम नहीं करता है, निश्चित रूप से क्यों नहीं। उपरोक्त कोड चलाना और बटन दबाना, कोई अलर्ट नहीं।
क्रिश

76

ऐसी कोई भी मूल घटना नहीं है जिसे आप इसके लिए हुक कर सकते हैं, हालांकि आप अपनी स्क्रिप्ट से एक घटना को ट्रिगर कर सकते हैं, जब आपने div का उपयोग करके दृश्यमान बना दिया हो। ट्रिगर समारोह

जैसे

//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');
});

45
यहाँ मेरी सीमा यह है कि मेरे पास उस कोड का उपयोग करने की आवश्यकता नहीं है जो शो () है। इसलिए मैं वास्तव में ट्रिगर () विधि को कॉल करने में सक्षम नहीं होगा।
फ्रैंकडेलिक

11
जेएस को मेरे संगठन के बाहर एक विकास दल द्वारा प्रदान किया गया था। यह "ब्लैक बॉक्स" का भी कुछ है, इसलिए यदि संभव हो तो हम उस कोड को संशोधित नहीं करना चाहते हैं। हालांकि यह हमारी एकमात्र पसंद हो सकती है।
फ्रैंकडेलिक

आप हमेशा अपने स्वयं के कार्यान्वयन के साथ उनके जेएस कार्यों पर मुहर लगा सकते हैं। हालांकि गंभीर लगता है!
redsquare

11
@redsquare: show()ऊपर चर्चा की गई कोड ब्लॉक के अलावा कई जगहों से क्या कहा जाता है?
रॉबिन माबेन

1
इस उदाहरण के लिए, आपको फ़ंक्शन का नाम बदल देना चाहिए onIsVisibleक्योंकि "विवेगम" का उपयोग अभी थोड़ा अस्पष्ट है।
ब्रैड जॉनसन

27

आप jQuery के लाइव क्वेरी प्लगइन का उपयोग कर सकते हैं । और निम्नानुसार कोड लिखें:

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

तब हर बार कंटेंटडिव दिखाई देता है, "कुछ करें" अलर्ट हो जाएगा!


खैर, यह काम करता है। मैंने इसके बारे में सोचा था और इसे बिना काम किए ही इसे अस्वीकार कर दिया था। कोशिश करनी चाहिए थी। :)
नेमिनेम

1
मेरे लिए काम नहीं किया। मुझे त्रुटि मिली "livequery एक फ़ंक्शन नहीं है"। दोनों "jquery-1.12.4.min.js" और "jquery-3.1.1.min.js"
पॉल गोर्बस

2
@Paul: यह एक प्लगइन है
क्रिश्चियन

यह आपकी वेबसाइट को काफी धीमा कर सकता है! लाइव म्यूटरी प्लगइन डोम म्यूटेशन ऑब्जर्वर जैसे आधुनिक कुशल तरीकों का उपयोग करने के बजाय विशेषताओं पर तेजी से मतदान करता है। इसलिए मैं @hegemon का समाधान पसंद करूंगा: stackoverflow.com/a/16462443/19163 (और पुराने IE संस्करणों के लिए केवल एक वापसी के रूप में मतदान का उपयोग करें) - vog 1 घंटा पहले
vog

20

redsquare का समाधान सही उत्तर है।

लेकिन एक इन-थ्योरी समाधान के रूप में आप एक फ़ंक्शन लिख सकते हैं जो कि सभी तत्वों.visibilityCheck ( न कि सभी दृश्य तत्वों ) द्वारा वर्गीकृत तत्वों का चयन कर रहा है और उनकी visibilityसंपत्ति मूल्य की जांच कर सकता है; अगर trueकुछ है तो करो।

बाद में, फ़ंक्शन का उपयोग करके setInterval()फ़ंक्शन को समय-समय पर प्रदर्शन किया जाना चाहिए । आप टाइमर का उपयोग करके रोक सकते हैंclearInterval() सफल कॉल-आउट हैं।

यहाँ एक उदाहरण है:

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

window.setInterval(foo, 100);

आप इस पर कुछ प्रदर्शन सुधार भी कर सकते हैं, हालांकि, समाधान मूल रूप से कार्रवाई में उपयोग करने के लिए बेतुका है। इसलिए...


5
setTimeout / setInterval के अंदर एक निहित फंक का उपयोग करने के लिए अच्छा रूप नहीं है। सेटटाइमआउट (फू, 100)
redsquare

1
मुझे आपको इसे सौंपना है, यह रचनात्मक है, यद्यपि बुरा। और यह मेरे लिए एक IE8-अनुरूप तरीके से चाल करने के लिए बस त्वरित और गंदा था। धन्यवाद!
JD स्मिथ

या display:none?
माइकल

12

निम्नलिखित कोड ( http://maximeparmentier.com/2012/11/06/bind-show-hide-events-with-jquery/ ) आपको उपयोग करने में सक्षम करेगा $('#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);

8
यह मेरे लिए पूरी तरह से काम करता है, लेकिन यह ध्यान रखना महत्वपूर्ण है कि फ़ंक्शन शो पर चेनिंग को तोड़ता है और फ़ंक्शन को छिपाता है, जो बहुत सारे प्लगइन्स को तोड़ता है। el.apply(this, arguments)इसे ठीक करने के लिए सामने एक रिटर्न जोड़ें ।
जयमेरप

यह वही है जिसे मैं देख रहा था! रिटर्न को @jaimerump
Brainfeeder

9

यदि आप सभी तत्वों (और बाल तत्वों) पर घटना को ट्रिगर करना चाहते हैं जो वास्तव में $ .show, toggle, toggleClass, addClass, या 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;
    }
});

और अब आपका तत्व:

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

आप शीर्ष पर सरणी में जोड़कर अतिरिक्त jQuery कार्यों को ओवरराइड कर सकते हैं (जैसे "attr")


9

ग्लेनस आइडिया पर आधारित एक छुपा / शो इवेंट ट्रिगर: टॉगल को हटा दिया गया क्योंकि यह शो को छुपाता है / छुपाता है और हम एक इवेंट के लिए 2fires नहीं चाहते हैं

$(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;
        }
    });
});

2
आप भी attr की जाँच करें और भी हटाएं?
एंड्रियाजा

5

मुझे यही समस्या थी और हमारी साइट के लिए इसे हल करने के लिए एक jQuery प्लगइन बनाया।

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

यहां बताया गया है कि आप इसका उपयोग अपने उदाहरण के आधार पर कैसे करेंगे:

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

1
मतदान बहुत कुशल नहीं है, और अगर यह कई तत्वों के लिए उपयोग किया जाता है, तो ब्राउज़र को काफी धीमा कर देगा।
सेरिन

4

JQuery के तरीके का उपयोग करें:

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

JQuery के रास्ते की साइट पर अन्य उदाहरण ।


1
यह केवल तब काम करता है जब स्क्रॉलिंग के कारण आइटम दिखाई देता है और अन्य व्यावहारिक परिवर्तनों के कारण नहीं।
एडमजोन

@AdamJones जब मैं कीबोर्ड का उपयोग कर रहा हूं, यह अपेक्षा के अनुरूप काम करता है। Ex .: imakewebthings.com/jquery-waypoints/shortcuts/infinite-scroll
फेडिर RYKHTIK

4

हाल ही में ResizeObserver कल्पना पॉलीफ़िल ने मुझे यहाँ क्या मदद की :

const divEl = $('#section60');

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

ध्यान दें कि यह क्रॉसब्रोसर और परफॉर्मेंट (कोई मतदान नहीं) है।


हर बार यह पता लगाने के लिए अच्छी तरह से काम किया जाता है कि एक तालिका पंक्ति दूसरों के विपरीत / छिपी हुई थी, एक प्लस भी आवश्यक प्लगइन नहीं था!
16

3

मैंने इसे प्राप्त करने के लिए एक सरल सेटर्नल फंक्शन किया। यदि कक्षा div1 वाला तत्व दिखाई देता है, तो यह दृश्यमान होने के लिए div2 सेट करता है। मुझे पता है कि एक अच्छी विधि नहीं है, लेकिन एक सरल तरीका है।

setInterval(function(){
  if($('.div1').is(':visible')){
    $('.div2').show();
  }
  else {
    $('.div2').hide();
  }      
}, 100);


2

एनीमेशन के बाद यह सहजता और ट्रिगर घटना का समर्थन करता है! [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);

से प्रेरित http://viralpatel.net/blogs/jquery-trigger-custom-event-show-hide-element/


2

बस चयनकर्ता के साथ एक ट्रिगर बांधें और ट्रिगर इवेंट में कोड डालें:

jQuery(function() {
  jQuery("#contentDiv:hidden").show().trigger('show');

  jQuery('#contentDiv').on('show', function() {
    console.log('#contentDiv is now visible');
    // your code here
  });
});

मुझे लगता है कि यह काफी सुरुचिपूर्ण समाधान है। इसने मेरे लिए काम किया।
KIKO सॉफ्टवेयर

1

DOM विशेषताओं में परिवर्तन देखने के लिए jQuery प्लगइन उपलब्ध है,

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

प्लगइन आप सभी की जरूरत है लपेटता है MutationObserver बाँध है

तब आप इसका उपयोग करके div देखने के लिए कर सकते हैं:

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

1

आशा है कि यह काम सबसे सरल तरीके से करेगा:

$("#myID").on('show').trigger('displayShow');

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

0

मैंने ग्लेन के विचार के आधार पर कैटलिन से छिपाने / शो इवेंट ट्रिगर को बदल दिया। मेरी समस्या यह थी कि मेरे पास एक मॉड्यूलर आवेदन है। मैं divs माता-पिता को दिखाने और छुपाने वाले मॉड्यूल के बीच बदलता हूं। फिर जब मैं एक मॉड्यूल छिपाता हूं और दूसरा दिखाता हूं, तो उसकी विधि के साथ जब मैं मॉड्यूल के बीच बदलाव करता हूं तो मुझे एक देरी दिखाई देती है। मुझे केवल कभी-कभी इस घटना को जगाने की जरूरत है, और कुछ विशेष चिल्ड में। तो मैंने कक्षा "प्रदर्शनकारक" के साथ केवल बच्चों को सूचित करने का फैसला किया

$.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;
    }
});

फिर जब कोई बच्चा "शो" या "छुपाना" घटना के लिए सुनना चाहता है तो मुझे उसे "प्रदर्शनकारक" वर्ग जोड़ना होगा, और जब वह इसे जारी रखना नहीं चाहेगा, तो मैं उसे कक्षा से हटा दूंगा

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);
},

मैं मदद की कामना करता हूं


0

ऐसा करने का एक तरीका।
केवल दृश्यता परिवर्तनों पर काम करता है जो css वर्ग परिवर्तन द्वारा किए जाते हैं, लेकिन विशेषता परिवर्तनों के लिए भी इसे देखने के लिए बढ़ाया जा सकता है।

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); }

0

मेरा समाधान:

; (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);

उदाहरण का उपयोग:

if(!$info_center.is(':visible')){
    $info_center.attr('data-trigger-visible-event','true').one('visible',processMoreLessButton)
}else{
    processMoreLessButton()
}

function processMoreLessButton(){
//some logic
}

0
$( 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");
    });
});

-2
<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';
                    }">

यह कोड ऑटो नियंत्रण क्वेरी दृश्यमान या अदृश्य नियंत्रण की आवश्यकता नहीं है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.