UNPKG

4.65 kBJavaScriptView Raw
1/*
2 * jQuery.appear
3 * https://github.com/bas2k/jquery.appear/
4 * http://code.google.com/p/jquery-appear/
5 * http://bas2k.ru/
6 *
7 * Copyright (c) 2009 Michael Hixson
8 * Copyright (c) 2012-2014 Alexander Brovikov
9 * Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
10 */
11(function (root, factory) {
12 if (typeof define === 'function' && define.amd) {
13 define(['jquery'], factory);
14 } else if (typeof module === 'object' && module.exports) {
15 factory(require('jquery'));
16 } else {
17 factory(root.jQuery);
18 }
19}(this, function ($) {
20 $.fn.appear = function(fn, options) {
21
22 var settings = $.extend({
23
24 //arbitrary data to pass to fn
25 data: undefined,
26
27 //call fn only on the first appear?
28 one: true,
29
30 // X & Y accuracy
31 accX: 0,
32 accY: 0
33
34 }, options);
35
36 return this.each(function() {
37
38 var t = $(this);
39
40 //whether the element is currently visible
41 t.appeared = false;
42
43 if (!fn) {
44
45 //trigger the custom event
46 t.trigger('appear', settings.data);
47 return;
48 }
49
50 var w = $(window);
51
52 //fires the appear event when appropriate
53 var check = function() {
54
55 //is the element hidden?
56 if (!t.is(':visible')) {
57
58 //it became hidden
59 t.appeared = false;
60 return;
61 }
62
63 //is the element inside the visible window?
64 var a = w.scrollLeft();
65 var b = w.scrollTop();
66 var o = t.offset();
67 var x = o.left;
68 var y = o.top;
69
70 var ax = settings.accX;
71 var ay = settings.accY;
72 var th = t.height();
73 var wh = w.height();
74 var tw = t.width();
75 var ww = w.width();
76
77 if (y + th + ay >= b &&
78 y <= b + wh + ay &&
79 x + tw + ax >= a &&
80 x <= a + ww + ax) {
81
82 //trigger the custom event
83 if (!t.appeared) t.trigger('appear', settings.data);
84
85 } else {
86
87 //it scrolled out of view
88 t.appeared = false;
89 }
90 };
91
92 //create a modified fn with some additional logic
93 var modifiedFn = function() {
94
95 //mark the element as visible
96 t.appeared = true;
97
98 //is this supposed to happen only once?
99 if (settings.one) {
100
101 //remove the check
102 w.unbind('scroll', check);
103 var i = $.inArray(check, $.fn.appear.checks);
104 if (i >= 0) $.fn.appear.checks.splice(i, 1);
105 }
106
107 //trigger the original fn
108 fn.apply(this, arguments);
109 };
110
111 //bind the modified fn to the element
112 if (settings.one) t.one('appear', settings.data, modifiedFn);
113 else t.bind('appear', settings.data, modifiedFn);
114
115 //check whenever the window scrolls
116 w.scroll(check);
117
118 //check whenever the dom changes
119 $.fn.appear.checks.push(check);
120
121 //check now
122 (check)();
123 });
124 };
125
126 //keep a queue of appearance checks
127 $.extend($.fn.appear, {
128
129 checks: [],
130 timeout: null,
131
132 //process the queue
133 checkAll: function() {
134 var length = $.fn.appear.checks.length;
135 if (length > 0) while (length--) ($.fn.appear.checks[length])();
136 },
137
138 //check the queue asynchronously
139 run: function() {
140 if ($.fn.appear.timeout) clearTimeout($.fn.appear.timeout);
141 $.fn.appear.timeout = setTimeout($.fn.appear.checkAll, 20);
142 }
143 });
144
145 //run checks when these methods are called
146 $.each(['append', 'prepend', 'after', 'before', 'attr',
147 'removeAttr', 'addClass', 'removeClass', 'toggleClass',
148 'remove', 'css', 'show', 'hide'], function(i, n) {
149 var old = $.fn[n];
150 if (old) {
151 $.fn[n] = function() {
152 var r = old.apply(this, arguments);
153 $.fn.appear.run();
154 return r;
155 }
156 }
157 });
158}));