(function ($) { var selectors = []; var checkbinded = false; var checklock = false; var defaults = { interval: 250, force_process: false }; var $window = $(window); var $priorappeared = []; function isappeared() { return $(this).is(':appeared'); } function isnottriggered() { return !$(this).data('_appear_triggered'); } function process() { checklock = false; for (var index = 0, selectorslength = selectors.length; index < selectorslength; index++) { var $appeared = $(selectors[index]).filter(isappeared); $appeared .filter(isnottriggered) .data('_appear_triggered', true) .trigger('appear', [$appeared]); if ($priorappeared[index]) { var $disappeared = $priorappeared[index].not($appeared); $disappeared .data('_appear_triggered', false) .trigger('disappear', [$disappeared]); } $priorappeared[index] = $appeared; } } function addselector(selector) { selectors.push(selector); $priorappeared.push(); } // ":appeared" custom filter $.expr.pseudos.appeared = $.expr.createpseudo(function (_arg) { return function (element) { var $element = $(element); if (!$element.is(':visible')) { return false; } var windowleft = $window.scrollleft(); var windowtop = $window.scrolltop(); var offset = $element.offset(); var left = offset.left; var top = offset.top; if (top + $element.height() >= windowtop && top - ($element.data('appear-top-offset') || 0) <= windowtop + $window.height() && left + $element.width() >= windowleft && left - ($element.data('appear-left-offset') || 0) <= windowleft + $window.width()) { return true; } return false; }; }); $.fn.extend({ // watching for element's appearance in browser viewport appear: function (selector, options) { $.appear(this, options); return this; } }); $.extend({ appear: function (selector, options) { var opts = $.extend({}, defaults, options || {}); if (!checkbinded) { var oncheck = function () { if (checklock) { return; } checklock = true; settimeout(process, opts.interval); }; $(window).scroll(oncheck).resize(oncheck); checkbinded = true; } if (opts.force_process) { settimeout(process, opts.interval); } addselector(selector); }, // force elements's appearance check force_appear: function () { if (checkbinded) { process(); return true; } return false; } }); }(function () { if (typeof module !== 'undefined') { // node return require('jquery'); } return jquery; }()));