0
|
1 /*! Shoestring - v2.0.1 - 2017-05-24
|
|
2 * http://github.com/filamentgroup/shoestring/
|
|
3 * Copyright (c) 2017 Scott Jehl, Filament Group, Inc; Licensed MIT & GPLv2 */
|
|
4 (function( factory ) {
|
|
5 if( typeof define === 'function' && define.amd ) {
|
|
6 // AMD. Register as an anonymous module.
|
|
7 define( [ 'shoestring' ], factory );
|
|
8 } else if (typeof module === 'object' && module.exports) {
|
|
9 // Node/CommonJS
|
|
10 module.exports = factory();
|
|
11 } else {
|
|
12 // Browser globals
|
|
13 factory();
|
|
14 }
|
|
15 }(function () {
|
|
16 var win = typeof window !== "undefined" ? window : this;
|
|
17 var doc = win.document;
|
|
18
|
|
19
|
|
20 /**
|
|
21 * The shoestring object constructor.
|
|
22 *
|
|
23 * @param {string,object} prim The selector to find or element to wrap.
|
|
24 * @param {object} sec The context in which to match the `prim` selector.
|
|
25 * @returns shoestring
|
|
26 * @this window
|
|
27 */
|
|
28 function shoestring( prim, sec ){
|
|
29 var pType = typeof( prim ),
|
|
30 ret = [],
|
|
31 sel;
|
|
32
|
|
33 // return an empty shoestring object
|
|
34 if( !prim ){
|
|
35 return new Shoestring( ret );
|
|
36 }
|
|
37
|
|
38 // ready calls
|
|
39 if( prim.call ){
|
|
40 return shoestring.ready( prim );
|
|
41 }
|
|
42
|
|
43 // handle re-wrapping shoestring objects
|
|
44 if( prim.constructor === Shoestring && !sec ){
|
|
45 return prim;
|
|
46 }
|
|
47
|
|
48 // if string starting with <, make html
|
|
49 if( pType === "string" && prim.indexOf( "<" ) === 0 ){
|
|
50 var dfrag = doc.createElement( "div" );
|
|
51
|
|
52 dfrag.innerHTML = prim;
|
|
53
|
|
54 // TODO depends on children (circular)
|
|
55 return shoestring( dfrag ).children().each(function(){
|
|
56 dfrag.removeChild( this );
|
|
57 });
|
|
58 }
|
|
59
|
|
60 // if string, it's a selector, use qsa
|
|
61 if( pType === "string" ){
|
|
62 if( sec ){
|
|
63 return shoestring( sec ).find( prim );
|
|
64 }
|
|
65
|
|
66 sel = doc.querySelectorAll( prim );
|
|
67
|
|
68 return new Shoestring( sel, prim );
|
|
69 }
|
|
70
|
|
71 // array like objects or node lists
|
|
72 if( Object.prototype.toString.call( pType ) === '[object Array]' ||
|
|
73 (win.NodeList && prim instanceof win.NodeList) ){
|
|
74
|
|
75 return new Shoestring( prim, prim );
|
|
76 }
|
|
77
|
|
78 // if it's an array, use all the elements
|
|
79 if( prim.constructor === Array ){
|
|
80 return new Shoestring( prim, prim );
|
|
81 }
|
|
82
|
|
83 // otherwise assume it's an object the we want at an index
|
|
84 return new Shoestring( [prim], prim );
|
|
85 }
|
|
86
|
|
87 var Shoestring = function( ret, prim ) {
|
|
88 this.length = 0;
|
|
89 this.selector = prim;
|
|
90 shoestring.merge(this, ret);
|
|
91 };
|
|
92
|
|
93 // TODO only required for tests
|
|
94 Shoestring.prototype.reverse = [].reverse;
|
|
95
|
|
96 // For adding element set methods
|
|
97 shoestring.fn = Shoestring.prototype;
|
|
98
|
|
99 shoestring.Shoestring = Shoestring;
|
|
100
|
|
101 // For extending objects
|
|
102 // TODO move to separate module when we use prototypes
|
|
103 shoestring.extend = function( first, second ){
|
|
104 for( var i in second ){
|
|
105 if( second.hasOwnProperty( i ) ){
|
|
106 first[ i ] = second[ i ];
|
|
107 }
|
|
108 }
|
|
109
|
|
110 return first;
|
|
111 };
|
|
112
|
|
113 // taken directly from jQuery
|
|
114 shoestring.merge = function( first, second ) {
|
|
115 var len, j, i;
|
|
116
|
|
117 len = +second.length,
|
|
118 j = 0,
|
|
119 i = first.length;
|
|
120
|
|
121 for ( ; j < len; j++ ) {
|
|
122 first[ i++ ] = second[ j ];
|
|
123 }
|
|
124
|
|
125 first.length = i;
|
|
126
|
|
127 return first;
|
|
128 };
|
|
129
|
|
130 // expose
|
|
131 win.shoestring = shoestring;
|
|
132
|
|
133
|
|
134
|
|
135 /**
|
|
136 * Make an HTTP request to a url.
|
|
137 *
|
|
138 * **NOTE** the following options are supported:
|
|
139 *
|
|
140 * - *method* - The HTTP method used with the request. Default: `GET`.
|
|
141 * - *data* - Raw object with keys and values to pass with request as query params. Default `null`.
|
|
142 * - *headers* - Set of request headers to add. Default `{}`.
|
|
143 * - *async* - Whether the opened request is asynchronouse. Default `true`.
|
|
144 * - *success* - Callback for successful request and response. Passed the response data.
|
|
145 * - *error* - Callback for failed request and response.
|
|
146 * - *cancel* - Callback for cancelled request and response.
|
|
147 *
|
|
148 * @param {string} url The url to request.
|
|
149 * @param {object} options The options object, see Notes.
|
|
150 * @return shoestring
|
|
151 * @this shoestring
|
|
152 */
|
|
153
|
|
154 shoestring.ajax = function( url, options ) {
|
|
155 var params = "", req = new XMLHttpRequest(), settings, key;
|
|
156
|
|
157 settings = shoestring.extend( {}, shoestring.ajax.settings );
|
|
158
|
|
159 if( options ){
|
|
160 shoestring.extend( settings, options );
|
|
161 }
|
|
162
|
|
163 if( !url ){
|
|
164 url = settings.url;
|
|
165 }
|
|
166
|
|
167 if( !req || !url ){
|
|
168 return;
|
|
169 }
|
|
170
|
|
171 // create parameter string from data object
|
|
172 if( settings.data ){
|
|
173 for( key in settings.data ){
|
|
174 if( settings.data.hasOwnProperty( key ) ){
|
|
175 if( params !== "" ){
|
|
176 params += "&";
|
|
177 }
|
|
178 params += encodeURIComponent( key ) + "=" +
|
|
179 encodeURIComponent( settings.data[key] );
|
|
180 }
|
|
181 }
|
|
182 }
|
|
183
|
|
184 // append params to url for GET requests
|
|
185 if( settings.method === "GET" && params ){
|
|
186
|
|
187 url += "?" + params;
|
|
188 }
|
|
189
|
|
190 req.open( settings.method, url, settings.async );
|
|
191
|
|
192 if( req.setRequestHeader ){
|
|
193 req.setRequestHeader( "X-Requested-With", "XMLHttpRequest" );
|
|
194
|
|
195 // Set 'Content-type' header for POST requests
|
|
196 if( settings.method === "POST" && params ){
|
|
197 req.setRequestHeader( "Content-type", "application/x-www-form-urlencoded" );
|
|
198 }
|
|
199
|
|
200 for( key in settings.headers ){
|
|
201 if( settings.headers.hasOwnProperty( key ) ){
|
|
202 req.setRequestHeader(key, settings.headers[ key ]);
|
|
203 }
|
|
204 }
|
|
205 }
|
|
206
|
|
207 req.onreadystatechange = function () {
|
|
208 if( req.readyState === 4 ){
|
|
209 // Trim the whitespace so shoestring('<div>') works
|
|
210 var res = (req.responseText || '').replace(/^\s+|\s+$/g, '');
|
|
211 if( req.status.toString().indexOf( "0" ) === 0 ){
|
|
212 return settings.cancel( res, req.status, req );
|
|
213 }
|
|
214 else if ( req.status.toString().match( /^(4|5)/ ) && RegExp.$1 ){
|
|
215 return settings.error( res, req.status, req );
|
|
216 }
|
|
217 else if (settings.success) {
|
|
218 return settings.success( res, req.status, req );
|
|
219 }
|
|
220 }
|
|
221 };
|
|
222
|
|
223 if( req.readyState === 4 ){
|
|
224 return req;
|
|
225 }
|
|
226
|
|
227 // Send request
|
|
228 if( settings.method === "POST" && params ){
|
|
229 req.send( params );
|
|
230 } else {
|
|
231 req.send();
|
|
232 }
|
|
233
|
|
234 return req;
|
|
235 };
|
|
236
|
|
237 shoestring.ajax.settings = {
|
|
238 success: function(){},
|
|
239 error: function(){},
|
|
240 cancel: function(){},
|
|
241 method: "GET",
|
|
242 async: true,
|
|
243 data: null,
|
|
244 headers: {}
|
|
245 };
|
|
246
|
|
247
|
|
248
|
|
249 /**
|
|
250 * Helper function wrapping a call to [ajax](ajax.js.html) using the `GET` method.
|
|
251 *
|
|
252 * @param {string} url The url to GET from.
|
|
253 * @param {function} callback Callback to invoke on success.
|
|
254 * @return shoestring
|
|
255 * @this shoestring
|
|
256 */
|
|
257 shoestring.get = function( url, callback ){
|
|
258 return shoestring.ajax( url, { success: callback } );
|
|
259 };
|
|
260
|
|
261
|
|
262
|
|
263 /**
|
|
264 * Load the HTML response from `url` into the current set of elements.
|
|
265 *
|
|
266 * @param {string} url The url to GET from.
|
|
267 * @param {function} callback Callback to invoke after HTML is inserted.
|
|
268 * @return shoestring
|
|
269 * @this shoestring
|
|
270 */
|
|
271 shoestring.fn.load = function( url, callback ){
|
|
272 var self = this,
|
|
273 args = arguments,
|
|
274 intCB = function( data ){
|
|
275 self.each(function(){
|
|
276 shoestring( this ).html( data );
|
|
277 });
|
|
278
|
|
279 if( callback ){
|
|
280 callback.apply( self, args );
|
|
281 }
|
|
282 };
|
|
283
|
|
284 shoestring.ajax( url, { success: intCB } );
|
|
285 return this;
|
|
286 };
|
|
287
|
|
288
|
|
289
|
|
290 /**
|
|
291 * Helper function wrapping a call to [ajax](ajax.js.html) using the `POST` method.
|
|
292 *
|
|
293 * @param {string} url The url to POST to.
|
|
294 * @param {object} data The data to send.
|
|
295 * @param {function} callback Callback to invoke on success.
|
|
296 * @return shoestring
|
|
297 * @this shoestring
|
|
298 */
|
|
299 shoestring.post = function( url, data, callback ){
|
|
300 return shoestring.ajax( url, { data: data, method: "POST", success: callback } );
|
|
301 };
|
|
302
|
|
303
|
|
304
|
|
305 /**
|
|
306 * Iterates over `shoestring` collections.
|
|
307 *
|
|
308 * @param {function} callback The callback to be invoked on each element and index
|
|
309 * @return shoestring
|
|
310 * @this shoestring
|
|
311 */
|
|
312 shoestring.fn.each = function( callback ){
|
|
313 return shoestring.each( this, callback );
|
|
314 };
|
|
315
|
|
316 shoestring.each = function( collection, callback ) {
|
|
317 var val;
|
|
318 for( var i = 0, il = collection.length; i < il; i++ ){
|
|
319 val = callback.call( collection[i], i, collection[i] );
|
|
320 if( val === false ){
|
|
321 break;
|
|
322 }
|
|
323 }
|
|
324
|
|
325 return collection;
|
|
326 };
|
|
327
|
|
328
|
|
329
|
|
330 /**
|
|
331 * Check for array membership.
|
|
332 *
|
|
333 * @param {object} needle The thing to find.
|
|
334 * @param {object} haystack The thing to find the needle in.
|
|
335 * @return {boolean}
|
|
336 * @this window
|
|
337 */
|
|
338 shoestring.inArray = function( needle, haystack ){
|
|
339 var isin = -1;
|
|
340 for( var i = 0, il = haystack.length; i < il; i++ ){
|
|
341 if( haystack.hasOwnProperty( i ) && haystack[ i ] === needle ){
|
|
342 isin = i;
|
|
343 }
|
|
344 }
|
|
345 return isin;
|
|
346 };
|
|
347
|
|
348
|
|
349
|
|
350 /**
|
|
351 * Bind callbacks to be run when the DOM is "ready".
|
|
352 *
|
|
353 * @param {function} fn The callback to be run
|
|
354 * @return shoestring
|
|
355 * @this shoestring
|
|
356 */
|
|
357 shoestring.ready = function( fn ){
|
|
358 if( ready && fn ){
|
|
359 fn.call( doc );
|
|
360 }
|
|
361 else if( fn ){
|
|
362 readyQueue.push( fn );
|
|
363 }
|
|
364 else {
|
|
365 runReady();
|
|
366 }
|
|
367
|
|
368 return [doc];
|
|
369 };
|
|
370
|
|
371 // TODO necessary?
|
|
372 shoestring.fn.ready = function( fn ){
|
|
373 shoestring.ready( fn );
|
|
374 return this;
|
|
375 };
|
|
376
|
|
377 // Empty and exec the ready queue
|
|
378 var ready = false,
|
|
379 readyQueue = [],
|
|
380 runReady = function(){
|
|
381 if( !ready ){
|
|
382 while( readyQueue.length ){
|
|
383 readyQueue.shift().call( doc );
|
|
384 }
|
|
385 ready = true;
|
|
386 }
|
|
387 };
|
|
388
|
|
389 // If DOM is already ready at exec time, depends on the browser.
|
|
390 // From: https://github.com/mobify/mobifyjs/blob/526841be5509e28fc949038021799e4223479f8d/src/capture.js#L128
|
|
391 if (doc.attachEvent ? doc.readyState === "complete" : doc.readyState !== "loading") {
|
|
392 runReady();
|
|
393 } else {
|
|
394 doc.addEventListener( "DOMContentLoaded", runReady, false );
|
|
395 doc.addEventListener( "readystatechange", runReady, false );
|
|
396 win.addEventListener( "load", runReady, false );
|
|
397 }
|
|
398
|
|
399
|
|
400
|
|
401 /**
|
|
402 * Checks the current set of elements against the selector, if one matches return `true`.
|
|
403 *
|
|
404 * @param {string} selector The selector to check.
|
|
405 * @return {boolean}
|
|
406 * @this {shoestring}
|
|
407 */
|
|
408 shoestring.fn.is = function( selector ){
|
|
409 var ret = false, self = this, parents, check;
|
|
410
|
|
411 // assume a dom element
|
|
412 if( typeof selector !== "string" ){
|
|
413 // array-like, ie shoestring objects or element arrays
|
|
414 if( selector.length && selector[0] ){
|
|
415 check = selector;
|
|
416 } else {
|
|
417 check = [selector];
|
|
418 }
|
|
419
|
|
420 return _checkElements(this, check);
|
|
421 }
|
|
422
|
|
423 parents = this.parent();
|
|
424
|
|
425 if( !parents.length ){
|
|
426 parents = shoestring( doc );
|
|
427 }
|
|
428
|
|
429 parents.each(function( i, e ) {
|
|
430 var children;
|
|
431
|
|
432 children = e.querySelectorAll( selector );
|
|
433
|
|
434 ret = _checkElements( self, children );
|
|
435 });
|
|
436
|
|
437 return ret;
|
|
438 };
|
|
439
|
|
440 function _checkElements(needles, haystack){
|
|
441 var ret = false;
|
|
442
|
|
443 needles.each(function() {
|
|
444 var j = 0;
|
|
445
|
|
446 while( j < haystack.length ){
|
|
447 if( this === haystack[j] ){
|
|
448 ret = true;
|
|
449 }
|
|
450
|
|
451 j++;
|
|
452 }
|
|
453 });
|
|
454
|
|
455 return ret;
|
|
456 }
|
|
457
|
|
458
|
|
459
|
|
460 /**
|
|
461 * Get data attached to the first element or set data values on all elements in the current set.
|
|
462 *
|
|
463 * @param {string} name The data attribute name.
|
|
464 * @param {any} value The value assigned to the data attribute.
|
|
465 * @return {any|shoestring}
|
|
466 * @this shoestring
|
|
467 */
|
|
468 shoestring.fn.data = function( name, value ){
|
|
469 if( name !== undefined ){
|
|
470 if( value !== undefined ){
|
|
471 return this.each(function(){
|
|
472 if( !this.shoestringData ){
|
|
473 this.shoestringData = {};
|
|
474 }
|
|
475
|
|
476 this.shoestringData[ name ] = value;
|
|
477 });
|
|
478 }
|
|
479 else {
|
|
480 if( this[ 0 ] ) {
|
|
481 if( this[ 0 ].shoestringData ) {
|
|
482 return this[ 0 ].shoestringData[ name ];
|
|
483 }
|
|
484 }
|
|
485 }
|
|
486 }
|
|
487 else {
|
|
488 return this[ 0 ] ? this[ 0 ].shoestringData || {} : undefined;
|
|
489 }
|
|
490 };
|
|
491
|
|
492
|
|
493 /**
|
|
494 * Remove data associated with `name` or all the data, for each element in the current set.
|
|
495 *
|
|
496 * @param {string} name The data attribute name.
|
|
497 * @return shoestring
|
|
498 * @this shoestring
|
|
499 */
|
|
500 shoestring.fn.removeData = function( name ){
|
|
501 return this.each(function(){
|
|
502 if( name !== undefined && this.shoestringData ){
|
|
503 this.shoestringData[ name ] = undefined;
|
|
504 delete this.shoestringData[ name ];
|
|
505 } else {
|
|
506 this[ 0 ].shoestringData = {};
|
|
507 }
|
|
508 });
|
|
509 };
|
|
510
|
|
511
|
|
512
|
|
513 /**
|
|
514 * An alias for the `shoestring` constructor.
|
|
515 */
|
|
516 win.$ = shoestring;
|
|
517
|
|
518
|
|
519
|
|
520 /**
|
|
521 * Add a class to each DOM element in the set of elements.
|
|
522 *
|
|
523 * @param {string} className The name of the class to be added.
|
|
524 * @return shoestring
|
|
525 * @this shoestring
|
|
526 */
|
|
527 shoestring.fn.addClass = function( className ){
|
|
528 var classes = className.replace(/^\s+|\s+$/g, '').split( " " );
|
|
529
|
|
530 return this.each(function(){
|
|
531 for( var i = 0, il = classes.length; i < il; i++ ){
|
|
532 if( this.className !== undefined &&
|
|
533 (this.className === "" ||
|
|
534 !this.className.match( new RegExp( "(^|\\s)" + classes[ i ] + "($|\\s)"))) ){
|
|
535 this.className += " " + classes[ i ];
|
|
536 }
|
|
537 }
|
|
538 });
|
|
539 };
|
|
540
|
|
541
|
|
542
|
|
543 /**
|
|
544 * Add elements matching the selector to the current set.
|
|
545 *
|
|
546 * @param {string} selector The selector for the elements to add from the DOM
|
|
547 * @return shoestring
|
|
548 * @this shoestring
|
|
549 */
|
|
550 shoestring.fn.add = function( selector ){
|
|
551 var ret = [];
|
|
552 this.each(function(){
|
|
553 ret.push( this );
|
|
554 });
|
|
555
|
|
556 shoestring( selector ).each(function(){
|
|
557 ret.push( this );
|
|
558 });
|
|
559
|
|
560 return shoestring( ret );
|
|
561 };
|
|
562
|
|
563
|
|
564
|
|
565 /**
|
|
566 * Insert an element or HTML string after each element in the current set.
|
|
567 *
|
|
568 * @param {string|HTMLElement} fragment The HTML or HTMLElement to insert.
|
|
569 * @return shoestring
|
|
570 * @this shoestring
|
|
571 */
|
|
572 shoestring.fn.after = function( fragment ){
|
|
573 if( typeof( fragment ) === "string" || fragment.nodeType !== undefined ){
|
|
574 fragment = shoestring( fragment );
|
|
575 }
|
|
576
|
|
577 if( fragment.length > 1 ){
|
|
578 fragment = fragment.reverse();
|
|
579 }
|
|
580 return this.each(function( i ){
|
|
581 for( var j = 0, jl = fragment.length; j < jl; j++ ){
|
|
582 var insertEl = i > 0 ? fragment[ j ].cloneNode( true ) : fragment[ j ];
|
|
583 this.parentNode.insertBefore( insertEl, this.nextSibling );
|
|
584 }
|
|
585 });
|
|
586 };
|
|
587
|
|
588
|
|
589
|
|
590 /**
|
|
591 * Insert an element or HTML string as the last child of each element in the set.
|
|
592 *
|
|
593 * @param {string|HTMLElement} fragment The HTML or HTMLElement to insert.
|
|
594 * @return shoestring
|
|
595 * @this shoestring
|
|
596 */
|
|
597 shoestring.fn.append = function( fragment ){
|
|
598 if( typeof( fragment ) === "string" || fragment.nodeType !== undefined ){
|
|
599 fragment = shoestring( fragment );
|
|
600 }
|
|
601
|
|
602 return this.each(function( i ){
|
|
603 for( var j = 0, jl = fragment.length; j < jl; j++ ){
|
|
604 this.appendChild( i > 0 ? fragment[ j ].cloneNode( true ) : fragment[ j ] );
|
|
605 }
|
|
606 });
|
|
607 };
|
|
608
|
|
609
|
|
610
|
|
611 /**
|
|
612 * Insert the current set as the last child of the elements matching the selector.
|
|
613 *
|
|
614 * @param {string} selector The selector after which to append the current set.
|
|
615 * @return shoestring
|
|
616 * @this shoestring
|
|
617 */
|
|
618 shoestring.fn.appendTo = function( selector ){
|
|
619 return this.each(function(){
|
|
620 shoestring( selector ).append( this );
|
|
621 });
|
|
622 };
|
|
623
|
|
624
|
|
625
|
|
626 /**
|
|
627 * Get the value of the first element of the set or set the value of all the elements in the set.
|
|
628 *
|
|
629 * @param {string} name The attribute name.
|
|
630 * @param {string} value The new value for the attribute.
|
|
631 * @return {shoestring|string|undefined}
|
|
632 * @this {shoestring}
|
|
633 */
|
|
634 shoestring.fn.attr = function( name, value ){
|
|
635 var nameStr = typeof( name ) === "string";
|
|
636
|
|
637 if( value !== undefined || !nameStr ){
|
|
638 return this.each(function(){
|
|
639 if( nameStr ){
|
|
640 this.setAttribute( name, value );
|
|
641 } else {
|
|
642 for( var i in name ){
|
|
643 if( name.hasOwnProperty( i ) ){
|
|
644 this.setAttribute( i, name[ i ] );
|
|
645 }
|
|
646 }
|
|
647 }
|
|
648 });
|
|
649 } else {
|
|
650 return this[ 0 ] ? this[ 0 ].getAttribute( name ) : undefined;
|
|
651 }
|
|
652 };
|
|
653
|
|
654
|
|
655
|
|
656 /**
|
|
657 * Insert an element or HTML string before each element in the current set.
|
|
658 *
|
|
659 * @param {string|HTMLElement} fragment The HTML or HTMLElement to insert.
|
|
660 * @return shoestring
|
|
661 * @this shoestring
|
|
662 */
|
|
663 shoestring.fn.before = function( fragment ){
|
|
664 if( typeof( fragment ) === "string" || fragment.nodeType !== undefined ){
|
|
665 fragment = shoestring( fragment );
|
|
666 }
|
|
667
|
|
668 return this.each(function( i ){
|
|
669 for( var j = 0, jl = fragment.length; j < jl; j++ ){
|
|
670 this.parentNode.insertBefore( i > 0 ? fragment[ j ].cloneNode( true ) : fragment[ j ], this );
|
|
671 }
|
|
672 });
|
|
673 };
|
|
674
|
|
675
|
|
676
|
|
677 /**
|
|
678 * Get the children of the current collection.
|
|
679 * @return shoestring
|
|
680 * @this shoestring
|
|
681 */
|
|
682 shoestring.fn.children = function(){
|
|
683 var ret = [],
|
|
684 childs,
|
|
685 j;
|
|
686 this.each(function(){
|
|
687 childs = this.children;
|
|
688 j = -1;
|
|
689
|
|
690 while( j++ < childs.length-1 ){
|
|
691 if( shoestring.inArray( childs[ j ], ret ) === -1 ){
|
|
692 ret.push( childs[ j ] );
|
|
693 }
|
|
694 }
|
|
695 });
|
|
696 return shoestring(ret);
|
|
697 };
|
|
698
|
|
699
|
|
700
|
|
701 /**
|
|
702 * Clone and return the current set of nodes into a new `shoestring` object.
|
|
703 *
|
|
704 * @return shoestring
|
|
705 * @this shoestring
|
|
706 */
|
|
707 shoestring.fn.clone = function() {
|
|
708 var ret = [];
|
|
709
|
|
710 this.each(function() {
|
|
711 ret.push( this.cloneNode( true ) );
|
|
712 });
|
|
713
|
|
714 return shoestring( ret );
|
|
715 };
|
|
716
|
|
717
|
|
718
|
|
719 /**
|
|
720 * Find an element matching the selector in the set of the current element and its parents.
|
|
721 *
|
|
722 * @param {string} selector The selector used to identify the target element.
|
|
723 * @return shoestring
|
|
724 * @this shoestring
|
|
725 */
|
|
726 shoestring.fn.closest = function( selector ){
|
|
727 var ret = [];
|
|
728
|
|
729 if( !selector ){
|
|
730 return shoestring( ret );
|
|
731 }
|
|
732
|
|
733 this.each(function(){
|
|
734 var element, $self = shoestring( element = this );
|
|
735
|
|
736 if( $self.is(selector) ){
|
|
737 ret.push( this );
|
|
738 return;
|
|
739 }
|
|
740
|
|
741 while( element.parentElement ) {
|
|
742 if( shoestring(element.parentElement).is(selector) ){
|
|
743 ret.push( element.parentElement );
|
|
744 break;
|
|
745 }
|
|
746
|
|
747 element = element.parentElement;
|
|
748 }
|
|
749 });
|
|
750
|
|
751 return shoestring( ret );
|
|
752 };
|
|
753
|
|
754
|
|
755
|
|
756 shoestring.cssExceptions = {
|
|
757 'float': [ 'cssFloat' ]
|
|
758 };
|
|
759
|
|
760
|
|
761
|
|
762 (function() {
|
|
763 var cssExceptions = shoestring.cssExceptions;
|
|
764
|
|
765 // marginRight instead of margin-right
|
|
766 function convertPropertyName( str ) {
|
|
767 return str.replace( /\-([A-Za-z])/g, function ( match, character ) {
|
|
768 return character.toUpperCase();
|
|
769 });
|
|
770 }
|
|
771
|
|
772 function _getStyle( element, property ) {
|
|
773 return win.getComputedStyle( element, null ).getPropertyValue( property );
|
|
774 }
|
|
775
|
|
776 var vendorPrefixes = [ '', '-webkit-', '-ms-', '-moz-', '-o-', '-khtml-' ];
|
|
777
|
|
778 /**
|
|
779 * Private function for getting the computed style of an element.
|
|
780 *
|
|
781 * **NOTE** Please use the [css](../css.js.html) method instead.
|
|
782 *
|
|
783 * @method _getStyle
|
|
784 * @param {HTMLElement} element The element we want the style property for.
|
|
785 * @param {string} property The css property we want the style for.
|
|
786 */
|
|
787 shoestring._getStyle = function( element, property ) {
|
|
788 var convert, value, j, k;
|
|
789
|
|
790 if( cssExceptions[ property ] ) {
|
|
791 for( j = 0, k = cssExceptions[ property ].length; j < k; j++ ) {
|
|
792 value = _getStyle( element, cssExceptions[ property ][ j ] );
|
|
793
|
|
794 if( value ) {
|
|
795 return value;
|
|
796 }
|
|
797 }
|
|
798 }
|
|
799
|
|
800 for( j = 0, k = vendorPrefixes.length; j < k; j++ ) {
|
|
801 convert = convertPropertyName( vendorPrefixes[ j ] + property );
|
|
802
|
|
803 // VendorprefixKeyName || key-name
|
|
804 value = _getStyle( element, convert );
|
|
805
|
|
806 if( convert !== property ) {
|
|
807 value = value || _getStyle( element, property );
|
|
808 }
|
|
809
|
|
810 if( vendorPrefixes[ j ] ) {
|
|
811 // -vendorprefix-key-name
|
|
812 value = value || _getStyle( element, vendorPrefixes[ j ] + property );
|
|
813 }
|
|
814
|
|
815 if( value ) {
|
|
816 return value;
|
|
817 }
|
|
818 }
|
|
819
|
|
820 return undefined;
|
|
821 };
|
|
822 })();
|
|
823
|
|
824
|
|
825
|
|
826 (function() {
|
|
827 var cssExceptions = shoestring.cssExceptions;
|
|
828
|
|
829 // marginRight instead of margin-right
|
|
830 function convertPropertyName( str ) {
|
|
831 return str.replace( /\-([A-Za-z])/g, function ( match, character ) {
|
|
832 return character.toUpperCase();
|
|
833 });
|
|
834 }
|
|
835
|
|
836 /**
|
|
837 * Private function for setting the style of an element.
|
|
838 *
|
|
839 * **NOTE** Please use the [css](../css.js.html) method instead.
|
|
840 *
|
|
841 * @method _setStyle
|
|
842 * @param {HTMLElement} element The element we want to style.
|
|
843 * @param {string} property The property being used to style the element.
|
|
844 * @param {string} value The css value for the style property.
|
|
845 */
|
|
846 shoestring._setStyle = function( element, property, value ) {
|
|
847 var convertedProperty = convertPropertyName(property);
|
|
848
|
|
849 element.style[ property ] = value;
|
|
850
|
|
851 if( convertedProperty !== property ) {
|
|
852 element.style[ convertedProperty ] = value;
|
|
853 }
|
|
854
|
|
855 if( cssExceptions[ property ] ) {
|
|
856 for( var j = 0, k = cssExceptions[ property ].length; j<k; j++ ) {
|
|
857 element.style[ cssExceptions[ property ][ j ] ] = value;
|
|
858 }
|
|
859 }
|
|
860 };
|
|
861 })();
|
|
862
|
|
863
|
|
864
|
|
865 /**
|
|
866 * Get the compute style property of the first element or set the value of a style property
|
|
867 * on all elements in the set.
|
|
868 *
|
|
869 * @method _setStyle
|
|
870 * @param {string} property The property being used to style the element.
|
|
871 * @param {string|undefined} value The css value for the style property.
|
|
872 * @return {string|shoestring}
|
|
873 * @this shoestring
|
|
874 */
|
|
875 shoestring.fn.css = function( property, value ){
|
|
876 if( !this[0] ){
|
|
877 return;
|
|
878 }
|
|
879
|
|
880 if( typeof property === "object" ) {
|
|
881 return this.each(function() {
|
|
882 for( var key in property ) {
|
|
883 if( property.hasOwnProperty( key ) ) {
|
|
884 shoestring._setStyle( this, key, property[key] );
|
|
885 }
|
|
886 }
|
|
887 });
|
|
888 } else {
|
|
889 // assignment else retrieve first
|
|
890 if( value !== undefined ){
|
|
891 return this.each(function(){
|
|
892 shoestring._setStyle( this, property, value );
|
|
893 });
|
|
894 }
|
|
895
|
|
896 return shoestring._getStyle( this[0], property );
|
|
897 }
|
|
898 };
|
|
899
|
|
900
|
|
901
|
|
902 /**
|
|
903 * Returns the indexed element wrapped in a new `shoestring` object.
|
|
904 *
|
|
905 * @param {integer} index The index of the element to wrap and return.
|
|
906 * @return shoestring
|
|
907 * @this shoestring
|
|
908 */
|
|
909 shoestring.fn.eq = function( index ){
|
|
910 if( this[index] ){
|
|
911 return shoestring( this[index] );
|
|
912 }
|
|
913
|
|
914 return shoestring([]);
|
|
915 };
|
|
916
|
|
917
|
|
918
|
|
919 /**
|
|
920 * Filter out the current set if they do *not* match the passed selector or
|
|
921 * the supplied callback returns false
|
|
922 *
|
|
923 * @param {string,function} selector The selector or boolean return value callback used to filter the elements.
|
|
924 * @return shoestring
|
|
925 * @this shoestring
|
|
926 */
|
|
927 shoestring.fn.filter = function( selector ){
|
|
928 var ret = [];
|
|
929
|
|
930 this.each(function( index ){
|
|
931 var wsel;
|
|
932
|
|
933 if( typeof selector === 'function' ) {
|
|
934 if( selector.call( this, index ) !== false ) {
|
|
935 ret.push( this );
|
|
936 }
|
|
937 // document node
|
|
938 } else if( this.nodeType === 9 ){
|
|
939 if( this === selector ) {
|
|
940 ret.push( this );
|
|
941 }
|
|
942 } else {
|
|
943 if( !this.parentNode ){
|
|
944 var context = shoestring( doc.createDocumentFragment() );
|
|
945
|
|
946 context[ 0 ].appendChild( this );
|
|
947 wsel = shoestring( selector, context );
|
|
948 } else {
|
|
949 wsel = shoestring( selector, this.parentNode );
|
|
950 }
|
|
951
|
|
952 if( shoestring.inArray( this, wsel ) > -1 ){
|
|
953 ret.push( this );
|
|
954 }
|
|
955 }
|
|
956 });
|
|
957
|
|
958 return shoestring( ret );
|
|
959 };
|
|
960
|
|
961
|
|
962
|
|
963 /**
|
|
964 * Find descendant elements of the current collection.
|
|
965 *
|
|
966 * @param {string} selector The selector used to find the children
|
|
967 * @return shoestring
|
|
968 * @this shoestring
|
|
969 */
|
|
970 shoestring.fn.find = function( selector ){
|
|
971 var ret = [],
|
|
972 finds;
|
|
973 this.each(function(){
|
|
974 finds = this.querySelectorAll( selector );
|
|
975
|
|
976 for( var i = 0, il = finds.length; i < il; i++ ){
|
|
977 ret = ret.concat( finds[i] );
|
|
978 }
|
|
979 });
|
|
980 return shoestring( ret );
|
|
981 };
|
|
982
|
|
983
|
|
984
|
|
985 /**
|
|
986 * Returns the first element of the set wrapped in a new `shoestring` object.
|
|
987 *
|
|
988 * @return shoestring
|
|
989 * @this shoestring
|
|
990 */
|
|
991 shoestring.fn.first = function(){
|
|
992 return this.eq( 0 );
|
|
993 };
|
|
994
|
|
995
|
|
996
|
|
997 /**
|
|
998 * Returns the raw DOM node at the passed index.
|
|
999 *
|
|
1000 * @param {integer} index The index of the element to wrap and return.
|
|
1001 * @return {HTMLElement|undefined|array}
|
|
1002 * @this shoestring
|
|
1003 */
|
|
1004 shoestring.fn.get = function( index ){
|
|
1005
|
|
1006 // return an array of elements if index is undefined
|
|
1007 if( index === undefined ){
|
|
1008 var elements = [];
|
|
1009
|
|
1010 for( var i = 0; i < this.length; i++ ){
|
|
1011 elements.push( this[ i ] );
|
|
1012 }
|
|
1013
|
|
1014 return elements;
|
|
1015 } else {
|
|
1016 return this[ index ];
|
|
1017 }
|
|
1018 };
|
|
1019
|
|
1020
|
|
1021
|
|
1022 /**
|
|
1023 * Private function for setting/getting the offset property for height/width.
|
|
1024 *
|
|
1025 * **NOTE** Please use the [width](width.js.html) or [height](height.js.html) methods instead.
|
|
1026 *
|
|
1027 * @param {shoestring} set The set of elements.
|
|
1028 * @param {string} name The string "height" or "width".
|
|
1029 * @param {float|undefined} value The value to assign.
|
|
1030 * @return shoestring
|
|
1031 * @this window
|
|
1032 */
|
|
1033 shoestring._dimension = function( set, name, value ){
|
|
1034 var offsetName;
|
|
1035
|
|
1036 if( value === undefined ){
|
|
1037 offsetName = name.replace(/^[a-z]/, function( letter ) {
|
|
1038 return letter.toUpperCase();
|
|
1039 });
|
|
1040
|
|
1041 return set[ 0 ][ "offset" + offsetName ];
|
|
1042 } else {
|
|
1043 // support integer values as pixels
|
|
1044 value = typeof value === "string" ? value : value + "px";
|
|
1045
|
|
1046 return set.each(function(){
|
|
1047 this.style[ name ] = value;
|
|
1048 });
|
|
1049 }
|
|
1050 };
|
|
1051
|
|
1052
|
|
1053
|
|
1054 /**
|
|
1055 * Gets the height value of the first element or sets the height for the whole set.
|
|
1056 *
|
|
1057 * @param {float|undefined} value The value to assign.
|
|
1058 * @return shoestring
|
|
1059 * @this shoestring
|
|
1060 */
|
|
1061 shoestring.fn.height = function( value ){
|
|
1062 return shoestring._dimension( this, "height", value );
|
|
1063 };
|
|
1064
|
|
1065
|
|
1066
|
|
1067 var set = function( html ){
|
|
1068 if( typeof html === "string" || typeof html === "number" ){
|
|
1069 return this.each(function(){
|
|
1070 this.innerHTML = "" + html;
|
|
1071 });
|
|
1072 } else {
|
|
1073 var h = "";
|
|
1074 if( typeof html.length !== "undefined" ){
|
|
1075 for( var i = 0, l = html.length; i < l; i++ ){
|
|
1076 h += html[i].outerHTML;
|
|
1077 }
|
|
1078 } else {
|
|
1079 h = html.outerHTML;
|
|
1080 }
|
|
1081 return this.each(function(){
|
|
1082 this.innerHTML = h;
|
|
1083 });
|
|
1084 }
|
|
1085 };
|
|
1086 /**
|
|
1087 * Gets or sets the `innerHTML` from all the elements in the set.
|
|
1088 *
|
|
1089 * @param {string|undefined} html The html to assign
|
|
1090 * @return {string|shoestring}
|
|
1091 * @this shoestring
|
|
1092 */
|
|
1093 shoestring.fn.html = function( html ){
|
|
1094 if( typeof html !== "undefined" ){
|
|
1095 return set.call( this, html );
|
|
1096 } else { // get
|
|
1097 var pile = "";
|
|
1098
|
|
1099 this.each(function(){
|
|
1100 pile += this.innerHTML;
|
|
1101 });
|
|
1102
|
|
1103 return pile;
|
|
1104 }
|
|
1105 };
|
|
1106
|
|
1107
|
|
1108
|
|
1109 (function() {
|
|
1110 function _getIndex( set, test ) {
|
|
1111 var i, result, element;
|
|
1112
|
|
1113 for( i = result = 0; i < set.length; i++ ) {
|
|
1114 element = set.item ? set.item(i) : set[i];
|
|
1115
|
|
1116 if( test(element) ){
|
|
1117 return result;
|
|
1118 }
|
|
1119
|
|
1120 // ignore text nodes, etc
|
|
1121 // NOTE may need to be more permissive
|
|
1122 if( element.nodeType === 1 ){
|
|
1123 result++;
|
|
1124 }
|
|
1125 }
|
|
1126
|
|
1127 return -1;
|
|
1128 }
|
|
1129
|
|
1130 /**
|
|
1131 * Find the index in the current set for the passed selector.
|
|
1132 * Without a selector it returns the index of the first node within the array of its siblings.
|
|
1133 *
|
|
1134 * @param {string|undefined} selector The selector used to search for the index.
|
|
1135 * @return {integer}
|
|
1136 * @this {shoestring}
|
|
1137 */
|
|
1138 shoestring.fn.index = function( selector ){
|
|
1139 var self, children;
|
|
1140
|
|
1141 self = this;
|
|
1142
|
|
1143 // no arg? check the children, otherwise check each element that matches
|
|
1144 if( selector === undefined ){
|
|
1145 children = ( ( this[ 0 ] && this[0].parentNode ) || doc.documentElement).childNodes;
|
|
1146
|
|
1147 // check if the element matches the first of the set
|
|
1148 return _getIndex(children, function( element ) {
|
|
1149 return self[0] === element;
|
|
1150 });
|
|
1151 } else {
|
|
1152
|
|
1153 // check if the element matches the first selected node from the parent
|
|
1154 return _getIndex(self, function( element ) {
|
|
1155 return element === (shoestring( selector, element.parentNode )[ 0 ]);
|
|
1156 });
|
|
1157 }
|
|
1158 };
|
|
1159 })();
|
|
1160
|
|
1161
|
|
1162
|
|
1163 /**
|
|
1164 * Insert the current set after the elements matching the selector.
|
|
1165 *
|
|
1166 * @param {string} selector The selector after which to insert the current set.
|
|
1167 * @return shoestring
|
|
1168 * @this shoestring
|
|
1169 */
|
|
1170 shoestring.fn.insertAfter = function( selector ){
|
|
1171 return this.each(function(){
|
|
1172 shoestring( selector ).after( this );
|
|
1173 });
|
|
1174 };
|
|
1175
|
|
1176
|
|
1177
|
|
1178 /**
|
|
1179 * Insert the current set before the elements matching the selector.
|
|
1180 *
|
|
1181 * @param {string} selector The selector before which to insert the current set.
|
|
1182 * @return shoestring
|
|
1183 * @this shoestring
|
|
1184 */
|
|
1185 shoestring.fn.insertBefore = function( selector ){
|
|
1186 return this.each(function(){
|
|
1187 shoestring( selector ).before( this );
|
|
1188 });
|
|
1189 };
|
|
1190
|
|
1191
|
|
1192
|
|
1193 /**
|
|
1194 * Returns the last element of the set wrapped in a new `shoestring` object.
|
|
1195 *
|
|
1196 * @return shoestring
|
|
1197 * @this shoestring
|
|
1198 */
|
|
1199 shoestring.fn.last = function(){
|
|
1200 return this.eq( this.length - 1 );
|
|
1201 };
|
|
1202
|
|
1203
|
|
1204
|
|
1205 /**
|
|
1206 * Returns a `shoestring` object with the set of siblings of each element in the original set.
|
|
1207 *
|
|
1208 * @return shoestring
|
|
1209 * @this shoestring
|
|
1210 */
|
|
1211 shoestring.fn.next = function(){
|
|
1212
|
|
1213 var result = [];
|
|
1214
|
|
1215 // TODO need to implement map
|
|
1216 this.each(function() {
|
|
1217 var children, item, found;
|
|
1218
|
|
1219 // get the child nodes for this member of the set
|
|
1220 children = shoestring( this.parentNode )[0].childNodes;
|
|
1221
|
|
1222 for( var i = 0; i < children.length; i++ ){
|
|
1223 item = children.item( i );
|
|
1224
|
|
1225 // found the item we needed (found) which means current item value is
|
|
1226 // the next node in the list, as long as it's viable grab it
|
|
1227 // NOTE may need to be more permissive
|
|
1228 if( found && item.nodeType === 1 ){
|
|
1229 result.push( item );
|
|
1230 break;
|
|
1231 }
|
|
1232
|
|
1233 // find the current item and mark it as found
|
|
1234 if( item === this ){
|
|
1235 found = true;
|
|
1236 }
|
|
1237 }
|
|
1238 });
|
|
1239
|
|
1240 return shoestring( result );
|
|
1241 };
|
|
1242
|
|
1243
|
|
1244
|
|
1245 /**
|
|
1246 * Removes elements from the current set.
|
|
1247 *
|
|
1248 * @param {string} selector The selector to use when removing the elements.
|
|
1249 * @return shoestring
|
|
1250 * @this shoestring
|
|
1251 */
|
|
1252 shoestring.fn.not = function( selector ){
|
|
1253 var ret = [];
|
|
1254
|
|
1255 this.each(function(){
|
|
1256 var found = shoestring( selector, this.parentNode );
|
|
1257
|
|
1258 if( shoestring.inArray(this, found) === -1 ){
|
|
1259 ret.push( this );
|
|
1260 }
|
|
1261 });
|
|
1262
|
|
1263 return shoestring( ret );
|
|
1264 };
|
|
1265
|
|
1266
|
|
1267
|
|
1268 /**
|
|
1269 * Returns an object with the `top` and `left` properties corresponging to the first elements offsets.
|
|
1270 *
|
|
1271 * @return object
|
|
1272 * @this shoestring
|
|
1273 */
|
|
1274 shoestring.fn.offset = function(){
|
|
1275 return {
|
|
1276 top: this[ 0 ].offsetTop,
|
|
1277 left: this[ 0 ].offsetLeft
|
|
1278 };
|
|
1279 };
|
|
1280
|
|
1281
|
|
1282
|
|
1283 /**
|
|
1284 * Returns the set of first parents for each element in the current set.
|
|
1285 *
|
|
1286 * @return shoestring
|
|
1287 * @this shoestring
|
|
1288 */
|
|
1289 shoestring.fn.parent = function(){
|
|
1290 var ret = [],
|
|
1291 parent;
|
|
1292
|
|
1293 this.each(function(){
|
|
1294 // no parent node, assume top level
|
|
1295 // jQuery parent: return the document object for <html> or the parent node if it exists
|
|
1296 parent = (this === doc.documentElement ? doc : this.parentNode);
|
|
1297
|
|
1298 // if there is a parent and it's not a document fragment
|
|
1299 if( parent && parent.nodeType !== 11 ){
|
|
1300 ret.push( parent );
|
|
1301 }
|
|
1302 });
|
|
1303
|
|
1304 return shoestring(ret);
|
|
1305 };
|
|
1306
|
|
1307
|
|
1308
|
|
1309 /**
|
|
1310 * Returns the set of all parents matching the selector if provided for each element in the current set.
|
|
1311 *
|
|
1312 * @param {string} selector The selector to check the parents with.
|
|
1313 * @return shoestring
|
|
1314 * @this shoestring
|
|
1315 */
|
|
1316 shoestring.fn.parents = function( selector ){
|
|
1317 var ret = [];
|
|
1318
|
|
1319 this.each(function(){
|
|
1320 var curr = this, match;
|
|
1321
|
|
1322 while( curr.parentElement && !match ){
|
|
1323 curr = curr.parentElement;
|
|
1324
|
|
1325 if( selector ){
|
|
1326 if( curr === shoestring( selector )[0] ){
|
|
1327 match = true;
|
|
1328
|
|
1329 if( shoestring.inArray( curr, ret ) === -1 ){
|
|
1330 ret.push( curr );
|
|
1331 }
|
|
1332 }
|
|
1333 } else {
|
|
1334 if( shoestring.inArray( curr, ret ) === -1 ){
|
|
1335 ret.push( curr );
|
|
1336 }
|
|
1337 }
|
|
1338 }
|
|
1339 });
|
|
1340
|
|
1341 return shoestring(ret);
|
|
1342 };
|
|
1343
|
|
1344
|
|
1345
|
|
1346 /**
|
|
1347 * Add an HTML string or element before the children of each element in the current set.
|
|
1348 *
|
|
1349 * @param {string|HTMLElement} fragment The HTML string or element to add.
|
|
1350 * @return shoestring
|
|
1351 * @this shoestring
|
|
1352 */
|
|
1353 shoestring.fn.prepend = function( fragment ){
|
|
1354 if( typeof( fragment ) === "string" || fragment.nodeType !== undefined ){
|
|
1355 fragment = shoestring( fragment );
|
|
1356 }
|
|
1357
|
|
1358 return this.each(function( i ){
|
|
1359
|
|
1360 for( var j = 0, jl = fragment.length; j < jl; j++ ){
|
|
1361 var insertEl = i > 0 ? fragment[ j ].cloneNode( true ) : fragment[ j ];
|
|
1362 if ( this.firstChild ){
|
|
1363 this.insertBefore( insertEl, this.firstChild );
|
|
1364 } else {
|
|
1365 this.appendChild( insertEl );
|
|
1366 }
|
|
1367 }
|
|
1368 });
|
|
1369 };
|
|
1370
|
|
1371
|
|
1372
|
|
1373 /**
|
|
1374 * Add each element of the current set before the children of the selected elements.
|
|
1375 *
|
|
1376 * @param {string} selector The selector for the elements to add the current set to..
|
|
1377 * @return shoestring
|
|
1378 * @this shoestring
|
|
1379 */
|
|
1380 shoestring.fn.prependTo = function( selector ){
|
|
1381 return this.each(function(){
|
|
1382 shoestring( selector ).prepend( this );
|
|
1383 });
|
|
1384 };
|
|
1385
|
|
1386
|
|
1387
|
|
1388 /**
|
|
1389 * Returns a `shoestring` object with the set of *one* siblingx before each element in the original set.
|
|
1390 *
|
|
1391 * @return shoestring
|
|
1392 * @this shoestring
|
|
1393 */
|
|
1394 shoestring.fn.prev = function(){
|
|
1395
|
|
1396 var result = [];
|
|
1397
|
|
1398 // TODO need to implement map
|
|
1399 this.each(function() {
|
|
1400 var children, item, found;
|
|
1401
|
|
1402 // get the child nodes for this member of the set
|
|
1403 children = shoestring( this.parentNode )[0].childNodes;
|
|
1404
|
|
1405 for( var i = children.length -1; i >= 0; i-- ){
|
|
1406 item = children.item( i );
|
|
1407
|
|
1408 // found the item we needed (found) which means current item value is
|
|
1409 // the next node in the list, as long as it's viable grab it
|
|
1410 // NOTE may need to be more permissive
|
|
1411 if( found && item.nodeType === 1 ){
|
|
1412 result.push( item );
|
|
1413 break;
|
|
1414 }
|
|
1415
|
|
1416 // find the current item and mark it as found
|
|
1417 if( item === this ){
|
|
1418 found = true;
|
|
1419 }
|
|
1420 }
|
|
1421 });
|
|
1422
|
|
1423 return shoestring( result );
|
|
1424 };
|
|
1425
|
|
1426
|
|
1427
|
|
1428 /**
|
|
1429 * Returns a `shoestring` object with the set of *all* siblings before each element in the original set.
|
|
1430 *
|
|
1431 * @return shoestring
|
|
1432 * @this shoestring
|
|
1433 */
|
|
1434 shoestring.fn.prevAll = function(){
|
|
1435
|
|
1436 var result = [];
|
|
1437
|
|
1438 this.each(function() {
|
|
1439 var $previous = shoestring( this ).prev();
|
|
1440
|
|
1441 while( $previous.length ){
|
|
1442 result.push( $previous[0] );
|
|
1443 $previous = $previous.prev();
|
|
1444 }
|
|
1445 });
|
|
1446
|
|
1447 return shoestring( result );
|
|
1448 };
|
|
1449
|
|
1450
|
|
1451
|
|
1452 // Property normalization, a subset taken from jQuery src
|
|
1453 shoestring.propFix = {
|
|
1454 "class": "className",
|
|
1455 contenteditable: "contentEditable",
|
|
1456 "for": "htmlFor",
|
|
1457 readonly: "readOnly",
|
|
1458 tabindex: "tabIndex"
|
|
1459 };
|
|
1460
|
|
1461
|
|
1462
|
|
1463 /**
|
|
1464 * Gets the property value from the first element or sets the property value on all elements of the currrent set.
|
|
1465 *
|
|
1466 * @param {string} name The property name.
|
|
1467 * @param {any} value The property value.
|
|
1468 * @return {any|shoestring}
|
|
1469 * @this shoestring
|
|
1470 */
|
|
1471 shoestring.fn.prop = function( name, value ){
|
|
1472 if( !this[0] ){
|
|
1473 return;
|
|
1474 }
|
|
1475
|
|
1476 name = shoestring.propFix[ name ] || name;
|
|
1477
|
|
1478 if( value !== undefined ){
|
|
1479 return this.each(function(){
|
|
1480 this[ name ] = value;
|
|
1481 });
|
|
1482 } else {
|
|
1483 return this[ 0 ][ name ];
|
|
1484 }
|
|
1485 };
|
|
1486
|
|
1487
|
|
1488
|
|
1489 /**
|
|
1490 * Remove an attribute from each element in the current set.
|
|
1491 *
|
|
1492 * @param {string} name The name of the attribute.
|
|
1493 * @return shoestring
|
|
1494 * @this shoestring
|
|
1495 */
|
|
1496 shoestring.fn.removeAttr = function( name ){
|
|
1497 return this.each(function(){
|
|
1498 this.removeAttribute( name );
|
|
1499 });
|
|
1500 };
|
|
1501
|
|
1502
|
|
1503
|
|
1504 /**
|
|
1505 * Remove a class from each DOM element in the set of elements.
|
|
1506 *
|
|
1507 * @param {string} className The name of the class to be removed.
|
|
1508 * @return shoestring
|
|
1509 * @this shoestring
|
|
1510 */
|
|
1511 shoestring.fn.removeClass = function( cname ){
|
|
1512 var classes = cname.replace(/^\s+|\s+$/g, '').split( " " );
|
|
1513
|
|
1514 return this.each(function(){
|
|
1515 var newClassName, regex;
|
|
1516
|
|
1517 for( var i = 0, il = classes.length; i < il; i++ ){
|
|
1518 if( this.className !== undefined ){
|
|
1519 regex = new RegExp( "(^|\\s)" + classes[ i ] + "($|\\s)", "gmi" );
|
|
1520 newClassName = this.className.replace( regex, " " );
|
|
1521
|
|
1522 this.className = newClassName.replace(/^\s+|\s+$/g, '');
|
|
1523 }
|
|
1524 }
|
|
1525 });
|
|
1526 };
|
|
1527
|
|
1528
|
|
1529
|
|
1530 /**
|
|
1531 * Remove the current set of elements from the DOM.
|
|
1532 *
|
|
1533 * @return shoestring
|
|
1534 * @this shoestring
|
|
1535 */
|
|
1536 shoestring.fn.remove = function(){
|
|
1537 return this.each(function(){
|
|
1538 if( this.parentNode ) {
|
|
1539 this.parentNode.removeChild( this );
|
|
1540 }
|
|
1541 });
|
|
1542 };
|
|
1543
|
|
1544
|
|
1545
|
|
1546 /**
|
|
1547 * Remove a proprety from each element in the current set.
|
|
1548 *
|
|
1549 * @param {string} name The name of the property.
|
|
1550 * @return shoestring
|
|
1551 * @this shoestring
|
|
1552 */
|
|
1553 shoestring.fn.removeProp = function( property ){
|
|
1554 var name = shoestring.propFix[ property ] || property;
|
|
1555
|
|
1556 return this.each(function(){
|
|
1557 this[ name ] = undefined;
|
|
1558 delete this[ name ];
|
|
1559 });
|
|
1560 };
|
|
1561
|
|
1562
|
|
1563
|
|
1564 /**
|
|
1565 * Replace each element in the current set with that argument HTML string or HTMLElement.
|
|
1566 *
|
|
1567 * @param {string|HTMLElement} fragment The value to assign.
|
|
1568 * @return shoestring
|
|
1569 * @this shoestring
|
|
1570 */
|
|
1571 shoestring.fn.replaceWith = function( fragment ){
|
|
1572 if( typeof( fragment ) === "string" ){
|
|
1573 fragment = shoestring( fragment );
|
|
1574 }
|
|
1575
|
|
1576 var ret = [];
|
|
1577
|
|
1578 if( fragment.length > 1 ){
|
|
1579 fragment = fragment.reverse();
|
|
1580 }
|
|
1581 this.each(function( i ){
|
|
1582 var clone = this.cloneNode( true ),
|
|
1583 insertEl;
|
|
1584 ret.push( clone );
|
|
1585
|
|
1586 // If there is no parentNode, this is pointless, drop it.
|
|
1587 if( !this.parentNode ){ return; }
|
|
1588
|
|
1589 if( fragment.length === 1 ){
|
|
1590 insertEl = i > 0 ? fragment[ 0 ].cloneNode( true ) : fragment[ 0 ];
|
|
1591 this.parentNode.replaceChild( insertEl, this );
|
|
1592 } else {
|
|
1593 for( var j = 0, jl = fragment.length; j < jl; j++ ){
|
|
1594 insertEl = i > 0 ? fragment[ j ].cloneNode( true ) : fragment[ j ];
|
|
1595 this.parentNode.insertBefore( insertEl, this.nextSibling );
|
|
1596 }
|
|
1597 this.parentNode.removeChild( this );
|
|
1598 }
|
|
1599 });
|
|
1600
|
|
1601 return shoestring( ret );
|
|
1602 };
|
|
1603
|
|
1604
|
|
1605
|
|
1606 shoestring.inputTypes = [
|
|
1607 "text",
|
|
1608 "hidden",
|
|
1609 "password",
|
|
1610 "color",
|
|
1611 "date",
|
|
1612 "datetime",
|
|
1613 // "datetime\-local" matched by datetime
|
|
1614 "email",
|
|
1615 "month",
|
|
1616 "number",
|
|
1617 "range",
|
|
1618 "search",
|
|
1619 "tel",
|
|
1620 "time",
|
|
1621 "url",
|
|
1622 "week"
|
|
1623 ];
|
|
1624
|
|
1625 shoestring.inputTypeTest = new RegExp( shoestring.inputTypes.join( "|" ) );
|
|
1626
|
|
1627
|
|
1628 /**
|
|
1629 * Serialize child input element values into an object.
|
|
1630 *
|
|
1631 * @return shoestring
|
|
1632 * @this shoestring
|
|
1633 */
|
|
1634 shoestring.fn.serialize = function(){
|
|
1635 var data = {};
|
|
1636
|
|
1637 shoestring( "input, select", this ).each(function(){
|
|
1638 var type = this.type, name = this.name, value = this.value;
|
|
1639
|
|
1640 if( shoestring.inputTypeTest.test( type ) ||
|
|
1641 ( type === "checkbox" || type === "radio" ) &&
|
|
1642 this.checked ){
|
|
1643
|
|
1644 data[ name ] = value;
|
|
1645 } else if( this.nodeName === "SELECT" ){
|
|
1646 data[ name ] = this.options[ this.selectedIndex ].nodeValue;
|
|
1647 }
|
|
1648 });
|
|
1649
|
|
1650 return data;
|
|
1651 };
|
|
1652
|
|
1653
|
|
1654
|
|
1655 /**
|
|
1656 * Get all of the sibling elements for each element in the current set.
|
|
1657 *
|
|
1658 * @return shoestring
|
|
1659 * @this shoestring
|
|
1660 */
|
|
1661 shoestring.fn.siblings = function(){
|
|
1662
|
|
1663 if( !this.length ) {
|
|
1664 return shoestring( [] );
|
|
1665 }
|
|
1666
|
|
1667 var sibs = [], el = this[ 0 ].parentNode.firstChild;
|
|
1668
|
|
1669 do {
|
|
1670 if( el.nodeType === 1 && el !== this[ 0 ] ) {
|
|
1671 sibs.push( el );
|
|
1672 }
|
|
1673
|
|
1674 el = el.nextSibling;
|
|
1675 } while( el );
|
|
1676
|
|
1677 return shoestring( sibs );
|
|
1678 };
|
|
1679
|
|
1680
|
|
1681
|
|
1682 var getText = function( elem ){
|
|
1683 var node,
|
|
1684 ret = "",
|
|
1685 i = 0,
|
|
1686 nodeType = elem.nodeType;
|
|
1687
|
|
1688 if ( !nodeType ) {
|
|
1689 // If no nodeType, this is expected to be an array
|
|
1690 while ( (node = elem[i++]) ) {
|
|
1691 // Do not traverse comment nodes
|
|
1692 ret += getText( node );
|
|
1693 }
|
|
1694 } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
|
|
1695 // Use textContent for elements
|
|
1696 // innerText usage removed for consistency of new lines (jQuery #11153)
|
|
1697 if ( typeof elem.textContent === "string" ) {
|
|
1698 return elem.textContent;
|
|
1699 } else {
|
|
1700 // Traverse its children
|
|
1701 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
|
|
1702 ret += getText( elem );
|
|
1703 }
|
|
1704 }
|
|
1705 } else if ( nodeType === 3 || nodeType === 4 ) {
|
|
1706 return elem.nodeValue;
|
|
1707 }
|
|
1708 // Do not include comment or processing instruction nodes
|
|
1709
|
|
1710 return ret;
|
|
1711 };
|
|
1712
|
|
1713 /**
|
|
1714 * Recursively retrieve the text content of the each element in the current set.
|
|
1715 *
|
|
1716 * @return shoestring
|
|
1717 * @this shoestring
|
|
1718 */
|
|
1719 shoestring.fn.text = function() {
|
|
1720
|
|
1721 return getText( this );
|
|
1722 };
|
|
1723
|
|
1724
|
|
1725
|
|
1726
|
|
1727 /**
|
|
1728 * Get the value of the first element or set the value of all elements in the current set.
|
|
1729 *
|
|
1730 * @param {string} value The value to set.
|
|
1731 * @return shoestring
|
|
1732 * @this shoestring
|
|
1733 */
|
|
1734 shoestring.fn.val = function( value ){
|
|
1735 var el;
|
|
1736 if( value !== undefined ){
|
|
1737 return this.each(function(){
|
|
1738 if( this.tagName === "SELECT" ){
|
|
1739 var optionSet, option,
|
|
1740 options = this.options,
|
|
1741 values = [],
|
|
1742 i = options.length,
|
|
1743 newIndex;
|
|
1744
|
|
1745 values[0] = value;
|
|
1746 while ( i-- ) {
|
|
1747 option = options[ i ];
|
|
1748 if ( (option.selected = shoestring.inArray( option.value, values ) >= 0) ) {
|
|
1749 optionSet = true;
|
|
1750 newIndex = i;
|
|
1751 }
|
|
1752 }
|
|
1753 // force browsers to behave consistently when non-matching value is set
|
|
1754 if ( !optionSet ) {
|
|
1755 this.selectedIndex = -1;
|
|
1756 } else {
|
|
1757 this.selectedIndex = newIndex;
|
|
1758 }
|
|
1759 } else {
|
|
1760 this.value = value;
|
|
1761 }
|
|
1762 });
|
|
1763 } else {
|
|
1764 el = this[0];
|
|
1765
|
|
1766 if( el.tagName === "SELECT" ){
|
|
1767 if( el.selectedIndex < 0 ){ return ""; }
|
|
1768 return el.options[ el.selectedIndex ].value;
|
|
1769 } else {
|
|
1770 return el.value;
|
|
1771 }
|
|
1772 }
|
|
1773 };
|
|
1774
|
|
1775
|
|
1776
|
|
1777 /**
|
|
1778 * Gets the width value of the first element or sets the width for the whole set.
|
|
1779 *
|
|
1780 * @param {float|undefined} value The value to assign.
|
|
1781 * @return shoestring
|
|
1782 * @this shoestring
|
|
1783 */
|
|
1784 shoestring.fn.width = function( value ){
|
|
1785 return shoestring._dimension( this, "width", value );
|
|
1786 };
|
|
1787
|
|
1788
|
|
1789
|
|
1790 /**
|
|
1791 * Wraps the child elements in the provided HTML.
|
|
1792 *
|
|
1793 * @param {string} html The wrapping HTML.
|
|
1794 * @return shoestring
|
|
1795 * @this shoestring
|
|
1796 */
|
|
1797 shoestring.fn.wrapInner = function( html ){
|
|
1798 return this.each(function(){
|
|
1799 var inH = this.innerHTML;
|
|
1800
|
|
1801 this.innerHTML = "";
|
|
1802 shoestring( this ).append( shoestring( html ).html( inH ) );
|
|
1803 });
|
|
1804 };
|
|
1805
|
|
1806
|
|
1807
|
|
1808 function initEventCache( el, evt ) {
|
|
1809 if ( !el.shoestringData ) {
|
|
1810 el.shoestringData = {};
|
|
1811 }
|
|
1812 if ( !el.shoestringData.events ) {
|
|
1813 el.shoestringData.events = {};
|
|
1814 }
|
|
1815 if ( !el.shoestringData.loop ) {
|
|
1816 el.shoestringData.loop = {};
|
|
1817 }
|
|
1818 if ( !el.shoestringData.events[ evt ] ) {
|
|
1819 el.shoestringData.events[ evt ] = [];
|
|
1820 }
|
|
1821 }
|
|
1822
|
|
1823 function addToEventCache( el, evt, eventInfo ) {
|
|
1824 var obj = {};
|
|
1825 obj.isCustomEvent = eventInfo.isCustomEvent;
|
|
1826 obj.callback = eventInfo.callfunc;
|
|
1827 obj.originalCallback = eventInfo.originalCallback;
|
|
1828 obj.namespace = eventInfo.namespace;
|
|
1829
|
|
1830 el.shoestringData.events[ evt ].push( obj );
|
|
1831
|
|
1832 if( eventInfo.customEventLoop ) {
|
|
1833 el.shoestringData.loop[ evt ] = eventInfo.customEventLoop;
|
|
1834 }
|
|
1835 }
|
|
1836
|
|
1837 /**
|
|
1838 * Bind a callback to an event for the currrent set of elements.
|
|
1839 *
|
|
1840 * @param {string} evt The event(s) to watch for.
|
|
1841 * @param {object,function} data Data to be included with each event or the callback.
|
|
1842 * @param {function} originalCallback Callback to be invoked when data is define.d.
|
|
1843 * @return shoestring
|
|
1844 * @this shoestring
|
|
1845 */
|
|
1846 shoestring.fn.bind = function( evt, data, originalCallback ){
|
|
1847
|
|
1848 if( typeof data === "function" ){
|
|
1849 originalCallback = data;
|
|
1850 data = null;
|
|
1851 }
|
|
1852
|
|
1853 var evts = evt.split( " " );
|
|
1854
|
|
1855 // NOTE the `triggeredElement` is purely for custom events from IE
|
|
1856 function encasedCallback( e, namespace, triggeredElement ){
|
|
1857 var result;
|
|
1858
|
|
1859 if( e._namespace && e._namespace !== namespace ) {
|
|
1860 return;
|
|
1861 }
|
|
1862
|
|
1863 e.data = data;
|
|
1864 e.namespace = e._namespace;
|
|
1865
|
|
1866 var returnTrue = function(){
|
|
1867 return true;
|
|
1868 };
|
|
1869
|
|
1870 e.isDefaultPrevented = function(){
|
|
1871 return false;
|
|
1872 };
|
|
1873
|
|
1874 var originalPreventDefault = e.preventDefault;
|
|
1875 var preventDefaultConstructor = function(){
|
|
1876 if( originalPreventDefault ) {
|
|
1877 return function(){
|
|
1878 e.isDefaultPrevented = returnTrue;
|
|
1879 originalPreventDefault.call(e);
|
|
1880 };
|
|
1881 } else {
|
|
1882 return function(){
|
|
1883 e.isDefaultPrevented = returnTrue;
|
|
1884 e.returnValue = false;
|
|
1885 };
|
|
1886 }
|
|
1887 };
|
|
1888
|
|
1889 // thanks https://github.com/jonathantneal/EventListener
|
|
1890 e.target = triggeredElement || e.target || e.srcElement;
|
|
1891 e.preventDefault = preventDefaultConstructor();
|
|
1892 e.stopPropagation = e.stopPropagation || function () {
|
|
1893 e.cancelBubble = true;
|
|
1894 };
|
|
1895
|
|
1896 result = originalCallback.apply(this, [ e ].concat( e._args ) );
|
|
1897
|
|
1898 if( result === false ){
|
|
1899 e.preventDefault();
|
|
1900 e.stopPropagation();
|
|
1901 }
|
|
1902
|
|
1903 return result;
|
|
1904 }
|
|
1905
|
|
1906 return this.each(function(){
|
|
1907 var domEventCallback,
|
|
1908 customEventCallback,
|
|
1909 customEventLoop,
|
|
1910 oEl = this;
|
|
1911
|
|
1912 for( var i = 0, il = evts.length; i < il; i++ ){
|
|
1913 var split = evts[ i ].split( "." ),
|
|
1914 evt = split[ 0 ],
|
|
1915 namespace = split.length > 0 ? split[ 1 ] : null;
|
|
1916
|
|
1917 domEventCallback = function( originalEvent ) {
|
|
1918 if( oEl.ssEventTrigger ) {
|
|
1919 originalEvent._namespace = oEl.ssEventTrigger._namespace;
|
|
1920 originalEvent._args = oEl.ssEventTrigger._args;
|
|
1921
|
|
1922 oEl.ssEventTrigger = null;
|
|
1923 }
|
|
1924 return encasedCallback.call( oEl, originalEvent, namespace );
|
|
1925 };
|
|
1926 customEventCallback = null;
|
|
1927 customEventLoop = null;
|
|
1928
|
|
1929 initEventCache( this, evt );
|
|
1930
|
|
1931 this.addEventListener( evt, domEventCallback, false );
|
|
1932
|
|
1933 addToEventCache( this, evt, {
|
|
1934 callfunc: customEventCallback || domEventCallback,
|
|
1935 isCustomEvent: !!customEventCallback,
|
|
1936 customEventLoop: customEventLoop,
|
|
1937 originalCallback: originalCallback,
|
|
1938 namespace: namespace
|
|
1939 });
|
|
1940 }
|
|
1941 });
|
|
1942 };
|
|
1943
|
|
1944 shoestring.fn.on = shoestring.fn.bind;
|
|
1945
|
|
1946
|
|
1947
|
|
1948
|
|
1949 /**
|
|
1950 * Unbind a previous bound callback for an event.
|
|
1951 *
|
|
1952 * @param {string} event The event(s) the callback was bound to..
|
|
1953 * @param {function} callback Callback to unbind.
|
|
1954 * @return shoestring
|
|
1955 * @this shoestring
|
|
1956 */
|
|
1957 shoestring.fn.unbind = function( event, callback ){
|
|
1958
|
|
1959
|
|
1960 var evts = event ? event.split( " " ) : [];
|
|
1961
|
|
1962 return this.each(function(){
|
|
1963 if( !this.shoestringData || !this.shoestringData.events ) {
|
|
1964 return;
|
|
1965 }
|
|
1966
|
|
1967 if( !evts.length ) {
|
|
1968 unbindAll.call( this );
|
|
1969 } else {
|
|
1970 var split, evt, namespace;
|
|
1971 for( var i = 0, il = evts.length; i < il; i++ ){
|
|
1972 split = evts[ i ].split( "." ),
|
|
1973 evt = split[ 0 ],
|
|
1974 namespace = split.length > 0 ? split[ 1 ] : null;
|
|
1975
|
|
1976 if( evt ) {
|
|
1977 unbind.call( this, evt, namespace, callback );
|
|
1978 } else {
|
|
1979 unbindAll.call( this, namespace, callback );
|
|
1980 }
|
|
1981 }
|
|
1982 }
|
|
1983 });
|
|
1984 };
|
|
1985
|
|
1986 function unbind( evt, namespace, callback ) {
|
|
1987 var bound = this.shoestringData.events[ evt ];
|
|
1988 if( !(bound && bound.length) ) {
|
|
1989 return;
|
|
1990 }
|
|
1991
|
|
1992 var matched = [], j, jl;
|
|
1993 for( j = 0, jl = bound.length; j < jl; j++ ) {
|
|
1994 if( !namespace || namespace === bound[ j ].namespace ) {
|
|
1995 if( callback === undefined || callback === bound[ j ].originalCallback ) {
|
|
1996 this.removeEventListener( evt, bound[ j ].callback, false );
|
|
1997 matched.push( j );
|
|
1998 }
|
|
1999 }
|
|
2000 }
|
|
2001
|
|
2002 for( j = 0, jl = matched.length; j < jl; j++ ) {
|
|
2003 this.shoestringData.events[ evt ].splice( j, 1 );
|
|
2004 }
|
|
2005 }
|
|
2006
|
|
2007 function unbindAll( namespace, callback ) {
|
|
2008 for( var evtKey in this.shoestringData.events ) {
|
|
2009 unbind.call( this, evtKey, namespace, callback );
|
|
2010 }
|
|
2011 }
|
|
2012
|
|
2013 shoestring.fn.off = shoestring.fn.unbind;
|
|
2014
|
|
2015
|
|
2016 /**
|
|
2017 * Bind a callback to an event for the currrent set of elements, unbind after one occurence.
|
|
2018 *
|
|
2019 * @param {string} event The event(s) to watch for.
|
|
2020 * @param {function} callback Callback to invoke on the event.
|
|
2021 * @return shoestring
|
|
2022 * @this shoestring
|
|
2023 */
|
|
2024 shoestring.fn.one = function( event, callback ){
|
|
2025 var evts = event.split( " " );
|
|
2026
|
|
2027 return this.each(function(){
|
|
2028 var thisevt, cbs = {}, $t = shoestring( this );
|
|
2029
|
|
2030 for( var i = 0, il = evts.length; i < il; i++ ){
|
|
2031 thisevt = evts[ i ];
|
|
2032
|
|
2033 cbs[ thisevt ] = function( e ){
|
|
2034 var $t = shoestring( this );
|
|
2035
|
|
2036 for( var j in cbs ) {
|
|
2037 $t.unbind( j, cbs[ j ] );
|
|
2038 }
|
|
2039
|
|
2040 return callback.apply( this, [ e ].concat( e._args ) );
|
|
2041 };
|
|
2042
|
|
2043 $t.bind( thisevt, cbs[ thisevt ] );
|
|
2044 }
|
|
2045 });
|
|
2046 };
|
|
2047
|
|
2048
|
|
2049
|
|
2050 /**
|
|
2051 * Trigger an event on the first element in the set, no bubbling, no defaults.
|
|
2052 *
|
|
2053 * @param {string} event The event(s) to trigger.
|
|
2054 * @param {object} args Arguments to append to callback invocations.
|
|
2055 * @return shoestring
|
|
2056 * @this shoestring
|
|
2057 */
|
|
2058 shoestring.fn.triggerHandler = function( event, args ){
|
|
2059 var e = event.split( " " )[ 0 ],
|
|
2060 el = this[ 0 ],
|
|
2061 ret;
|
|
2062
|
|
2063 // See this.fireEvent( 'on' + evts[ i ], document.createEventObject() ); instead of click() etc in trigger.
|
|
2064 if( doc.createEvent && el.shoestringData && el.shoestringData.events && el.shoestringData.events[ e ] ){
|
|
2065 var bindings = el.shoestringData.events[ e ];
|
|
2066 for (var i in bindings ){
|
|
2067 if( bindings.hasOwnProperty( i ) ){
|
|
2068 event = doc.createEvent( "Event" );
|
|
2069 event.initEvent( e, true, true );
|
|
2070 event._args = args;
|
|
2071 args.unshift( event );
|
|
2072
|
|
2073 ret = bindings[ i ].originalCallback.apply( event.target, args );
|
|
2074 }
|
|
2075 }
|
|
2076 }
|
|
2077
|
|
2078 return ret;
|
|
2079 };
|
|
2080
|
|
2081
|
|
2082
|
|
2083 /**
|
|
2084 * Trigger an event on each of the DOM elements in the current set.
|
|
2085 *
|
|
2086 * @param {string} event The event(s) to trigger.
|
|
2087 * @param {object} args Arguments to append to callback invocations.
|
|
2088 * @return shoestring
|
|
2089 * @this shoestring
|
|
2090 */
|
|
2091 shoestring.fn.trigger = function( event, args ){
|
|
2092 var evts = event.split( " " );
|
|
2093
|
|
2094 return this.each(function(){
|
|
2095 var split, evt, namespace;
|
|
2096 for( var i = 0, il = evts.length; i < il; i++ ){
|
|
2097 split = evts[ i ].split( "." ),
|
|
2098 evt = split[ 0 ],
|
|
2099 namespace = split.length > 0 ? split[ 1 ] : null;
|
|
2100
|
|
2101 if( evt === "click" ){
|
|
2102 if( this.tagName === "INPUT" && this.type === "checkbox" && this.click ){
|
|
2103 this.click();
|
|
2104 return false;
|
|
2105 }
|
|
2106 }
|
|
2107
|
|
2108 if( doc.createEvent ){
|
|
2109 var event = doc.createEvent( "Event" );
|
|
2110 event.initEvent( evt, true, true );
|
|
2111 event._args = args;
|
|
2112 event._namespace = namespace;
|
|
2113
|
|
2114 this.dispatchEvent( event );
|
|
2115 }
|
|
2116 }
|
|
2117 });
|
|
2118 };
|
|
2119
|
|
2120
|
|
2121
|
|
2122 return shoestring;
|
|
2123 }));
|