-
Notifications
You must be signed in to change notification settings - Fork 2
/
thin.js
153 lines (135 loc) · 4 KB
/
thin.js
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Thin JS. (C) 2009 Dominic Baggott. Released under MIT license
(function() {
// help the minifier crush the code
var doc = document,
addEventListener = "addEventListener",
querySelectorAll = "querySelectorAll",
w3c = !!doc[ addEventListener ],
// get the target of an event
getTarget = function( event ) {
event = event || window.event;
return event.target || event.srcElement;
},
// add an event handler to an element
addEvent = function( element, event, fn ) {
if ( w3c ) {
element[ addEventListener ]( event, fn, false );
}
else {
element.attachEvent( 'on' + event, function( e ) {
fn.call( getTarget( e ), e );
} );
}
},
/**
* $( selector )
* - selector (String|Node|NodeList): selector to use to find elements
*
* Browsers which don't support document.querySelectorAll will always
* return an empty list.
**/
Thin = function( selector ) {
// use an empty array to fail silently in unsupported browsers
var elements = [];
// a string is a selector
if ( typeof selector === "string" ) {
if ( doc[ querySelectorAll ] ) {
elements = doc[ querySelectorAll ]( selector );
}
}
// allows wrapping of single nodes
else if ( selector.nodeType ) {
elements = [ selector ];
}
// allows wrapping of NodeLists (including those returned by Thin)
else if ( selector.length ) {
elements = selector;
}
/**
* each( fn )
* - fn (Function): the function to call for each element
**/
elements.each = function( fn ) {
for ( var i = 0; i < elements.length; i++ ) {
fn.call( elements[ i ], i );
}
// return elements to allow chaining
return elements;
};
/**
* bind( event, fn )
* - event (String): the name of the event, e.g. click, hover
* - fn (Function): the function to call when the event triggers
**/
elements.bind = function( event, fn ) {
return elements.each( function() {
addEvent( this, event, fn );
} );
};
/**
* live( event, fn )
* - event (String): the name of the event, e.g. click, hover
* - fn (Function): the function to call when the event triggers
**/
elements.live = function( event, fn ) {
addEvent( doc, event, function( e ) {
var target = getTarget( e ),
matches = target.parentNode[ querySelectorAll ]( selector ),
length = matches.length,
i = 0;
for ( ; i < length; i++ ) {
if ( matches[ i ] === target ) {
fn.call( target, e );
return;
}
}
} );
// return elements to allow chaining
return elements;
};
return elements;
},
// holds references to all the functions to call on DOMReady
readyFunctions = [],
// this is fired on DOMReady to call all the queued functions
doReady = function() {
while ( readyFunctions.length ) {
// we use shift to make sure the functions only get called once
readyFunctions.shift()();
}
};
/**
* $.ready( fn )
* - fn (Function): the function to call on DOMReady
**/
Thin.ready = function( fn ) {
if ( doc.readyState === "complete" ) {
fn();
}
else {
readyFunctions.push( fn );
}
};
// set up doReady to fire on DOMReady the "official" way
if ( w3c ) {
addEvent( doc, "DOMContentLoaded", doReady );
}
// IE doesn't support DOMContentLoaded so we use this which fires earlier
// than window.onload: http://javascript.nwbox.com/IEContentLoaded/
if ( doc.documentElement.doScroll ) {
// anonymous self-executing repeater which stops after calling doReady
( function() {
try {
doc.documentElement.doScroll( "left" );
doReady();
}
catch ( e ) {
setTimeout( arguments.callee, 0 );
}
} )();
}
// fire doReady on window load, just as a backup
addEvent( window, "load", doReady );
// expose the library
window.$ = Thin;
})();