-
-
Save ashmind/2403709aedfadfa0f326 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! | |
* jquery.visiblechange.js 0.7 // 2014.05.06 // tested with jQuery 1.11 | |
* | |
* Copyright 2014 Andrey Shchekin for AffinityID | |
* Licensed under the terms of the MIT license. | |
*/ | |
/* | |
* This plugin provides a new event 'visiblechange' that is raised when the | |
* visibility of the element changes. This includes direct change to visibility, | |
* or changes to parent visibility. However that sdoes not include element | |
* being "out-of-sight" due to the scrolling or other offsets. | |
* | |
* // basic usage: | |
* $(element).on('visiblechange', handler); | |
* | |
* // shortcut: | |
* $(element).visiblechange(handler); | |
* | |
* // unsubscribing: | |
* $(element).off('visiblechange'); | |
* | |
* // handling: | |
* function handler(e) { | |
* console.log("visible:", e.visible); | |
* } | |
* | |
* Known limitations: | |
* 1. DOM changes are not handled -- movement of the element or its parents | |
* in the DOM tree can lead to unpredicatable results. | |
* 2. In the browsers that do not have MutationObservers, the poll interval | |
* is not configurable. | |
*/ | |
(function($) { | |
var eventName = 'visiblechange'; // improves minification | |
$.event.special[eventName] = (function() { | |
var visibleDataKey = '__.' + eventName +'.data'; | |
function setup() { | |
var $element = $(this); | |
var visible = $element.is(':visible'); | |
var unobserve = window.MutationObserver | |
? observeWithMutationObserver($element) | |
: observeWithSetInterval($element); | |
$element.data(visibleDataKey, { | |
unobserve: unobserve, | |
oldVisible: visible | |
}); | |
} | |
function observeWithMutationObserver($element) { | |
var observer = new MutationObserver(function() { | |
checkVisible($element); | |
}); | |
$element.parents().addBack().each(function() { | |
observer.observe(this, { | |
attributes: true, | |
attributeFilter: ['style', 'class'] | |
}); | |
}); | |
return function() { | |
return observer.disconnect(); | |
}; | |
} | |
function observeWithSetInterval($element) { | |
var timer = setInterval(function() { | |
checkVisible($element); | |
}, 500); | |
return function() { resetInterval(timer); }; | |
} | |
function checkVisible($element) { | |
var data = $element.data(visibleDataKey); | |
var newVisible = $element.is(':visible'); | |
if (newVisible === data.oldVisible) | |
return; | |
data.oldVisible = newVisible; | |
var event = $.Event(eventName); | |
event.visible = newVisible; | |
$element.trigger(event); | |
} | |
function teardown() { | |
var $element = $(this); | |
var data = $element.data(visibleDataKey); | |
data.unobserve(); | |
$element.data(visibleDataKey, null); | |
} | |
return { | |
noBubble: true, | |
setup: setup, | |
teardown: teardown | |
}; | |
})(); | |
$.fn[eventName] = function(callback) { | |
this.on(eventName, callback); | |
}; | |
})(window.jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment