我在我的网站中使用 jQuery,我想在某个 div 可见时触发某些操作。
是否可以将某种“不可见”事件处理程序附加到任意 div 并在 div 可见时运行某些代码?
我想要类似下面的伪代码:
$(function() {
$('#contentDiv').isvisible(function() {
alert("do something");
});
});
在 contentDiv 实际可见之前,不应触发 alert("do something") 代码。
谢谢。
您始终可以添加到原始 .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() 方法的正常行为的同时执行一些 beforeShow 和 afterShow 。
您还可以创建另一个方法,这样您就不必覆盖原始的 .show() 方法。
DOM mutation observers 正在解决此问题。它们允许您将观察者(一个函数)绑定到更改 dom 元素的内容、文本或属性的事件。
随着 IE11 的发布,所有主流浏览器都支持此功能,请查看 http://caniuse.com/mutationobserver
示例代码如下:
$(function() { $('#show').click(function() { $('#testdiv').show(); }); var observer = new MutationObserver(function(mutations) { alert('Attributes改变了!'); }); var target = document.querySelector('#testdiv');observer.observe(target, { attributes: true }); });
没有可以为此挂钩的本机事件,但是在使用 .trigger 函数使 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');
});
show()
怎么办?
onIsVisible
,因为“isVisible”的使用现在有点模棱两可。
您可以使用 jQuery 的 Live Query plugin。并编写代码如下:
$('#contentDiv:visible').livequery(function() {
alert("do something");
});
然后每次 contentDiv 可见时,都会提醒“做某事”!
redsquare's solution 是正确答案。
但作为 IN-THEORY 解决方案,您可以编写一个函数来选择按 .visibilityCheck
分类的元素(并非所有可见元素)并检查它们的 visibility
属性值;如果 true
然后做一些事情。
之后,应使用 setInterval()
函数定期执行该函数。您可以在成功调用后使用 clearInterval()
停止计时器。
这是一个例子:
function foo() {
$('.visibilityCheck').each(function() {
if ($(this).is(':visible')){
// do something
}
});
}
window.setInterval(foo, 100);
您还可以对其进行一些性能改进,但是,在实际中使用该解决方案基本上是荒谬的。所以...
display:none
?
以下代码(取自 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);
el.apply(this, arguments)
前添加一个返回来解决此问题。
如果您想通过 $.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”)
基于 Glenns ideea 的隐藏/显示事件触发器:删除切换,因为它会触发显示/隐藏并且我们不希望一个事件发生 2 次触发
$(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;
}
});
});
我遇到了同样的问题并创建了一个 jQuery 插件来为我们的网站解决它。
https://github.com/shaunbowe/jquery.visibilityChanged
以下是根据您的示例使用它的方法:
$('#contentDiv').visibilityChanged(function(element, visible) {
alert("do something");
});
只需将触发器与选择器绑定并将代码放入触发器事件中:
jQuery(function() {
jQuery("#contentDiv:hidden").show().trigger('show');
jQuery('#contentDiv').on('show', function() {
console.log('#contentDiv is now visible');
// your code here
});
});
在这里帮助我的是最近的ResizeObserver spec polyfill:
const divEl = $('#section60');
const ro = new ResizeObserver(() => {
if (divEl.is(':visible')) {
console.log("it's visible now!");
}
});
ro.observe(divEl[0]);
请注意,它是跨浏览器和高性能的(无轮询)。
使用 jQuery 航点:
$('#contentDiv').waypoint(function() {
alert('do something');
});
the site of jQuery Waypoints 上的其他示例。
我做了一个简单的 setinterval 函数来实现这一点。如果具有类 div1 的元素可见,则将 div2 设置为可见。我知道不是一个好方法,而是一个简单的解决方法。
setInterval(function(){
if($('.div1').is(':visible')){
$('.div2').show();
}
else {
$('.div2').hide();
}
}, 100);
这支持动画完成后的缓动和触发事件! [在 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
});
希望这将以最简单的方式完成工作:
$("#myID").on('show').trigger('displayShow');
$('#myID').off('displayShow').on('displayShow', function(e) {
console.log('This event will be triggered when myID will be visible');
});
我根据 Glenns 的想法更改了 Catalint 的隐藏/显示事件触发器。我的问题是我有一个模块化应用程序。我在显示和隐藏 div 父级的模块之间切换。然后,当我隐藏一个模块并显示另一个模块时,使用他的方法在模块之间切换时会出现明显的延迟。我只需要偶尔点亮这个事件,并在一些特殊的孩子身上。所以我决定只通知“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;
}
});
然后当一个孩子想听“显示”或“隐藏”事件时,我必须为他添加“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");
});
});
$(function() { $(document).click(function (){ if ($('#contentDiv').is(':visible')) { alert("Visible"); } else { alert("Hidden "); } }); });
<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';
}">
此代码自动控制不需要查询可见或不可见控件
fadeTo
功能在实现这个功能后不能正常工作