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