Событие jQuery для запуска действия, когда div становится видимым
Я использую jQuery на своем сайте, и я хотел бы вызвать определенные действия, когда определенный div становится видимым.
Можно ли прикрепить какой-либо "видимый" обработчик событий к произвольным divs и запустить определенный код, когда они становятся видимыми?
Мне бы хотелось что-то вроде следующего псевдокода:
$(function() {
$('#contentDiv').isvisible(function() {
alert("do something");
});
});
Предупреждение ( "сделать что-то" ) код не должен срабатывать, пока контентDDD не станет видимым.
Спасибо.
Ответы
Ответ 1
Вы всегда можете добавить к оригинальному . 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();
});
Это эффективно позволяет вам что-то делать beforeShow и afterShow при выполнении обычного поведения исходного метода .show().
Вы также можете создать другой метод, поэтому вам не нужно переопределять оригинальный метод .show().
Ответ 2
Нет никакого родного события, к которому вы можете подключиться, но вы можете инициировать событие из вашего script после того, как вы сделали div видимым с помощью. trigger функция
например
//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');
});
Ответ 3
Проблема решается наблюдателями мутации 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>
Ответ 4
Вы можете использовать плагин jQuery livequery.
И напишите код следующим образом:
$('#contentDiv:visible').livequery(function() {
alert("do something");
});
Затем каждый раз, когда отображается contentDiv, "делать что-то" будет предупрежден!
Ответ 5
решение redsquare - это правильный/логический ответ.
но как решение IN-THEORY вы можете закодировать функцию, которая выбирает элементы, классифицированные классом .visibilityCheck
(не все видимые элементы), и проверяют их значение свойства visibility
; если true
, тогда сделайте что-нибудь. ок?
Затем функция должна выполняться периодически с помощью функции setInterval()
. Как вы знаете, вы можете остановить таймер с помощью clearInterval()
и идентификатора таймера при успешном вызове функции.
function foo(){
$('.visibilityCheck').each(function(){
if($(this).is(':visible')){
//do something
}
});
} //foo()
window.setInterval(foo, 100);
Кроме того, вы можете сделать некоторые улучшения производительности, но решение в основном проигнорировано для использования в действии, я думаю.
Ответ 6
Если вы хотите вызвать событие на всех элементах (и дочерних элементах), которые фактически становятся видимыми, с помощью $.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)
Ответ 7
скрыть/показать событие триггер на основе Glenns ideea:
удаленный переключатель, потому что он запускает show/hide, и мы не хотим, чтобы 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;
}
});
});
Ответ 8
Следующий код (вытащенный из 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);
Ответ 9
У меня была эта же проблема и я создал плагин jQuery для его решения для нашего сайта.
https://github.com/shaunbowe/jquery.visibilityChanged
Вот как вы могли бы использовать его на основе вашего примера:
$('#contentDiv').visibilityChanged(function(element, visible) {
alert("do something");
});
Ответ 10
Использовать путевые точки jQuery:
$('#contentDiv').waypoint(function() {
alert('do something');
});
Другие примеры на сайте путевых точек jQuery.
Ответ 11
Вы также можете попробовать jQuery появится плагин, как указано в параллельном потоке fooobar.com/questions/10584/...
Ответ 12
Эта поддержка облегчает и запускает событие после анимации! [проверено на 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/
Ответ 13
Существует плагин jQuery для просмотра изменений в атрибутах DOM,
https://github.com/darcyclarke/jQuery-Watch-Plugin
Плагины для плагинов Все, что вам нужно, это bind MutationObserver
Затем вы можете использовать его для просмотра div с помощью:
$("#selector").watch('css', function() {
console.log("Visibility: " + this.style.display == 'none'?'hidden':'shown'));
//or any random events
});
Ответ 14
Я изменил триггер show/show из Catalint на основе идеи Glenns.
Моя проблема заключалась в том, что у меня модульное приложение. Я переключаюсь между модулями, показывающими и скрывающими родителей 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);
},
Я хочу помочь
Ответ 15
Один из способов сделать это.
Работает только с изменениями видимости, которые производятся с помощью изменения класса 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); }
Ответ 16
мое решение:
; (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
}
Ответ 17
$( 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");
});
});
Ответ 18
Надеюсь, что это сделает работу простейшим образом:
$("#myID").on('show').trigger('displayShow');
$('#myID').off('displayShow').on('displayShow', function(e) {
console.log('This event will be triggered when myID will be visible');
});
Ответ 19
Что мне помогло, это недавний ResizeObserver spec polyfill:
const divEl = $('#section60');
const ro = new ResizeObserver(() => {
if (divEl.is(':visible')) {
console.log("it visible now!");
}
});
ro.observe(divEl[0]);
Обратите внимание, что это crossbrowser и performant (без опроса).
Ответ 20
<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';
}">
Этот автоматический контроль кода не требует видимого или невидимого запроса