jQuery事件触发行动时,div是可见的
我在我的网站中使用jQuery,我想触发某些特定的行动时,可见。
是否有可能附加某种“不可见的”事件处理程序到任意的div,并有一定的代码运行时,他们的div是可见的?
我想像下面的伪代码:
$(function() { $('#contentDiv').isvisible(function() { alert("do something"); }); });
警报(“做某事”)代码不应该触发,直到contentDiv实际上可见。
谢谢。
您始终可以添加到原始的.show()方法,因此您不必在每次显示内容时触发事件,也不必在遗留代码中使用它。
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]); }); } });
用法示例:
jQuery(function($) { $('#test') .bind('beforeShow', function() { alert('beforeShow'); }) .bind('afterShow', function() { alert('afterShow'); }) .show(1000, function() { alert('in show callback'); }) .show(); });
这可以让你在执行原始的.show()方法的正常行为的同时,在ShowShow和AfterShow之前做一些事情。
你也可以创建另一个方法,所以你不必重写原始的.show()方法。
没有本身的事件,你可以为此插入,但是你可以从你的脚本触发一个事件后,你可以使用。 触发功能
例如
//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'); });
DOM突变观察者正在解决这个问题。 它们允许你将观察者(一个函数)绑定到改变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>
你可以使用jQuery的livequery插件。 并编写代码如下:
$('#contentDiv:visible').livequery(function() { alert("do something"); });
然后,每当contentDiv可见时,“做某事”将会被提醒!
redsquare的解决方案是正确的/逻辑的答案。
但作为IN-THEORY解决方案,您可以编写一个功能,选择由.visibilityCheck
类( 不是所有可见元素 )分类的元素并检查其visibility
属性值; 如果true
那么做点什么。 好?
之后,应该使用setInterval()
函数定期执行函数。 如您所知,可以使用clearInterval()
和函数成功调出时的计时器ID来停止计时器。
function foo(){ $('.visibilityCheck').each(function(){ if($(this).is(':visible')){ //do something } }); } //foo() window.setInterval(foo, 100);
你也可以在这方面做一些性能上的改进,但是我想这个解决方案基本上被忽略了。
如果您想触发实际可见的所有元素(和子元素)上的事件,请按$ .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); });
您可以通过将其添加到顶部数组(如“attr”)来将其他jQuery函数的覆盖
基于Glenns ideea的隐藏/显示事件触发器:删除切换,因为它触发显示/隐藏,并且我们不希望双事件发生在一个事件
$(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; } }); });
下面的代码(来自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);
我有同样的问题,并创建了一个jQuery插件来解决我们的网站。
https://github.com/shaunbowe/jquery.visibilityChanged
下面是你将如何使用它的基础上你的例子:
$('#contentDiv').visibilityChanged(function(element, visible) { alert("do something"); });
使用jQuery Waypoints:
$('#contentDiv').waypoint(function() { alert('do something'); });
jQuery Waypoint网站上的其他例子。
您也可以尝试jQuery出现插件提到的并行线程https://stackoverflow.com/a/3535028/741782
这个动画完成后支持缓动和触发事件! [在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/
有一个jQuery插件可用于观看DOM属性的变化,
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 });
基于Glenns的想法,我改变了Catalint的hide / show事件触发器。 我的问题是,我有一个模块化的应用程序。 我改变模块显示和隐藏divs父母。 然后,当我隐藏一个模块,并显示另一个,用他的方法,我有一个明显的延迟,当我改变模块之间。 我只是有时候需要把这个事件和一些特殊的孩子扔掉。 所以我决定只通知班级“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; } });
那么当一个孩子想要听“show”或“hide”事件时,我不得不为他添加“displayObserver”类,而当它不想继续听时,我把他移除
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); },
我希望能帮到你
一种方法来做到这一点。
仅适用于由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); }
我的解决方案
; (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 }
$( 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"); }); });
希望这会以最简单的方式完成工作:
$("#myID").on('show').trigger('displayShow'); $('#myID').off('displayShow').on('displayShow', function(e) { console.log('This event will be triggered when myID will be visible'); });
这里帮助我的是最近的ResizeObserver spec polyfill :
const divEl = $('#section60'); const ro = new ResizeObserver(() => { if (divEl.is(':visible')) { console.log("it's visible now!"); } }); ro.observe(divEl[0]);
请注意,它是交叉浏览器和高性能(无轮询)。
<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'; }">
这个代码自动控制不需要查询可见或不可见的控制