minifiedjs-rails 0.0.1.beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 TM Lee
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,44 @@
1
+ # minifiedjs-rails
2
+
3
+ MinifiedJS (http://minifiedjs.com/), A Truly Lightweight JavaScript Library for Rails via Assets Pipeline
4
+ The Javascript library that replaces jQuery or MooTools with a <4kB Library.
5
+
6
+ ## Installation with Rails 3.1+
7
+
8
+ Add this to your `Gemfile` as part of the `assets` group:
9
+
10
+ group :assets do
11
+ gem 'minifiedjs-rails'
12
+ end
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Require `minified_web` in your JavaScript manifest, for example in `application.js` if you are using Rails 3.1+:
19
+
20
+ //= require minified_web
21
+
22
+ Your other options include a minified version and also with IE6-8 support removed (more information at http://minifiedjs.com/download/). You should only pick one of the following to be included in your app.
23
+
24
+ //= require minified_web
25
+ //= require minified_web.min
26
+ //= require minified_web_noie
27
+ //= require minified_web_noie.min
28
+
29
+ ## Usage
30
+
31
+ Quick start guide can be found at http://minifiedjs.com/docs/quickstart.html
32
+
33
+ For more documentations, visit http://minifiedjs.com/docs/
34
+
35
+ For the complete API, check out http://minifiedjs.com/api/
36
+
37
+
38
+ ## Contributing
39
+
40
+ 1. Fork it
41
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
42
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
43
+ 4. Push to the branch (`git push origin my-new-feature`)
44
+ 5. Create new Pull Request
@@ -0,0 +1,8 @@
1
+ require "minifiedjs/rails/version"
2
+
3
+ module Minifiedjs
4
+ module Rails
5
+ class Engine < ::Rails::Engine
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ module Minifiedjs
2
+ module Rails
3
+ VERSION = "0.0.1.beta"
4
+ end
5
+ end
@@ -0,0 +1,3086 @@
1
+ /*
2
+ * Minified-web.js - Complete library for JavaScript interaction in less than 4kb
3
+ *
4
+ * Public Domain. Use, modify and distribute it any way you like. No attribution required.
5
+ *
6
+ * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
7
+ *
8
+ * Contains code based on https://github.com/douglascrockford/JSON-js (also Public Domain).
9
+ *
10
+ * https://github.com/timjansen/minified.js
11
+ */
12
+
13
+ /*
14
+ * When you read this code, please keep in mind that it is optimized to produce small and gzip'able code
15
+ * after being minimized with Closure (http://closure-compiler.appspot.com). Run-time performance and readability
16
+ * should be acceptable, but are not a primary concern.
17
+ *
18
+ *
19
+ * Various comment annotations control the builder in parser-src.js / builder-src.js. This file should always work without the builder,
20
+ * but only the builder allows you to remove functions.
21
+ *
22
+ * Here's a short summary of that the non-documenting tags mean.
23
+ *
24
+ * Multi-Line Comments:
25
+ * - @id marks the beginning of an optional block. It ends with the next @id block, or the next @stop comment.
26
+ * - @requires defines the ids that the current block depends on. They will always be available.
27
+ * - @configurable the block can be selected in the GUI. If the value is 'default', it is a enabled by default. If it is 'optional', it is not.
28
+ * - @dependency if set, the block is only used as a dependency and won't show up in builder or documentation
29
+ * - @name a name for builder and reference docs
30
+ * - @doc if 'no', the section will not be displayed in reference docs, only in builder
31
+ * - @module the module(s), comma-separated. Can be WEB, UTIL or APP
32
+ *
33
+ * Single-Line Comments
34
+ * - @cond id defines that the code following after the id will be included if the block id is enabled
35
+ * - @cond !id include the following line only if the block id is disabled
36
+ * - @condblock id will include all following lines if id is enabled until the next @condend. @condblocks can be nested.
37
+ * - @condend ends a @condblock
38
+ */
39
+
40
+ // ==ClosureCompiler==
41
+ // @output_file_name minified.js
42
+ // @compilation_level ADVANCED_OPTIMIZATIONS
43
+ // ==/ClosureCompiler==
44
+
45
+ /*$
46
+ * @id require
47
+ * @name require()
48
+ * @syntax require(name)
49
+ * @group OPTIONS
50
+ * @module WEB, UTIL, APP
51
+ * Returns a reference to a module. If you do not use an AMD loader to load Minified, just call <var>require()</var> with the
52
+ * argument 'minified' to get a reference to Minified.
53
+ * If you do use an AMD loader, Minified will not define this function and you can use the AMD loader to obtain the
54
+ * reference to Minified.
55
+ * Minified's version of <var>require</var> is very simple and will only support Minified, but <strong>no other libraries</strong>. You can not
56
+ * use it to load other modules, and it will be incompatible with all non-AMD libraries that also define a function
57
+ * of the same name. If you need to work with several libraries, you need a real AMD loader.
58
+ *
59
+ * @param name the name of the module to request. In Minified's implementation, only 'minified' is supported.
60
+ * @return the reference to Minified if 'minified' had been used as name. <var>undefined</var> otherwise.
61
+ */
62
+
63
+ /*$
64
+ * @id amdsupport
65
+ * @name AMD support
66
+ * @configurable default
67
+ * @group OPTIONS
68
+ * @doc no
69
+ * @module WEB, UTIL
70
+ * If enabled, Minified will work correctly with AMD frameworks. If not, it will just provide a global
71
+ * function ##require(), which can be used only to load 'minified'.
72
+ */
73
+ if (/^u/.test(typeof define)) { // no AMD support available ? define a minimal version
74
+ var def = {};
75
+ this['define'] = function(name, f) {def[name] = f();};
76
+ this['require'] = function(name) { return def[name]; };
77
+ }
78
+
79
+
80
+ define('minified', function() {
81
+ /*$
82
+ * @stop
83
+ */
84
+ // @cond !amdsupport (function() {
85
+
86
+
87
+ //// GLOBAL VARIABLES ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
88
+
89
+ /**
90
+ * @const
91
+ */
92
+ var _window = this;
93
+
94
+ /**
95
+ * @const
96
+ */
97
+ var _document = document;
98
+
99
+ /**
100
+ * @const
101
+ * @type {!string}
102
+ */
103
+ var BACKSLASHB = '\\b';
104
+ /** @const */
105
+ var undef;
106
+
107
+ var PUSH = [].push;
108
+
109
+ /*$
110
+ * @id ready_vars
111
+ * @dependency
112
+ */
113
+ /** @type {!Array.<function()>} */
114
+ var DOMREADY_HANDLER = [];
115
+
116
+ /*$
117
+ * @id animation_vars
118
+ * @dependency
119
+ */
120
+ /** @type {!Array.<{c:!function(), t:!number, s:!function()}>} */
121
+ var ANIMATION_HANDLERS = []; // global list of {c: <callback function>, t: <timestamp>, s:<stop function>} currently active
122
+
123
+ /** @type {!function()} */
124
+ var REQUEST_ANIMATION_FRAME = _window['requestAnimationFrame'] || function(callback) {
125
+ delay(callback, 33); // 30 fps as fallback
126
+ };
127
+
128
+
129
+ /*$
130
+ * @id ie8compatibility
131
+ * @group OPTIONS
132
+ * @configurable default
133
+ * @doc no
134
+ * @name Backward-Compatibility for IE8 and similar browsers
135
+ * The only difference for Minified between IE8 and IE9 is the lack of support for the CSS opacity attribute in IE8,
136
+ * and the existence of cssText (which is used instead of the style attribute).
137
+ */
138
+ /**
139
+ * @const
140
+ * @type {boolean}
141
+ */
142
+ // @condblock ready_vars
143
+ var IS_PRE_IE9 = !!_document.all && !DOMREADY_HANDLER.map;
144
+ // @condend
145
+ // @cond !ready_vars var IS_PRE_IE9 = !!_document.all && ![].map;
146
+ /*$
147
+ * @id ie7compatibility
148
+ * @requires ie8compatibility
149
+ * @group OPTIONS
150
+ * @configurable default
151
+ * @doc no
152
+ * @name Backward-Compatibility for IE7 and similar browsers
153
+ * The difference between IE7 and IE8 compatibility that IE7 provides neither native selector support (querySelectorAll) nor native JSON.
154
+ * Disabling IE6 and IE7 will not only make Minified smaller, but give you full CSS selectors and complete JSON support.
155
+ */
156
+ // @condblock ucode
157
+ /**
158
+ * @const
159
+ * @type {Object.<string, string>}
160
+ */
161
+ var STRING_SUBSTITUTIONS = { // table of character substitutions
162
+ '\t': '\\t',
163
+ '\r': '\\r',
164
+ '\n': '\\n',
165
+ '"' : '\\"',
166
+ '\\': '\\\\'
167
+ };
168
+ // @condend
169
+
170
+ /*$
171
+ * @id ie6compatibility
172
+ * @requires ie7compatibility
173
+ * @group OPTIONS
174
+ * @configurable default
175
+ * @doc no
176
+ * @name Backward-Compatibility for IE6 and similar browsers
177
+ * The only difference for Minified between IE6 and IE7 is the lack of a native XmlHttpRequest in IE6 which makes the library a tiny
178
+ * little bit larger.
179
+ */
180
+
181
+ /*$
182
+ * @id fadeslide
183
+ * @requires animate set
184
+ * @group ANIMATION
185
+ * @configurable default
186
+ * @doc no
187
+ * @name Support for $$fade and $$slide
188
+ */
189
+ /*$
190
+ * @stop
191
+ */
192
+
193
+ //// GLOBAL FUNCTIONS ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
194
+
195
+ /** @param s {?} */
196
+ function toString(s) { // wrapper for Closure optimization
197
+ return s!=null ? ''+s : '';
198
+ }
199
+ /**
200
+ * @param s {?}
201
+ * @param o {string}
202
+ */
203
+ function isType(s,o) {
204
+ return typeof s == o;
205
+ }
206
+ /** @param s {?} */
207
+ function isString(s) {
208
+ return isType(s, 'string');
209
+ }
210
+ function isFunction(f) {
211
+ return isType(f, 'function') && !f['item']; // item check as work-around webkit bug 14547
212
+ }
213
+ function isObject(f) {
214
+ return isType(f, 'object');
215
+ }
216
+ function isNode(n) {
217
+ return n && n['nodeType'];
218
+ }
219
+ function isList(v) {
220
+ return v && v.length != null && !isString(v) && !isNode(v) && !isFunction(v);
221
+ }
222
+ function eachObj(obj, cb) {
223
+ for (var n in obj)
224
+ if (obj.hasOwnProperty(n))
225
+ cb(n, obj[n]);
226
+ return obj;
227
+ }
228
+ function each(list, cb) {
229
+ for (var i = 0; list && i < list.length; i++)
230
+ cb(list[i], i);
231
+ return list;
232
+ }
233
+ function filter(list, filterFunc) {
234
+ var r = [];
235
+ each(list, function(node,index) {
236
+ if (filterFunc(node,index))
237
+ r.push(node);
238
+ });
239
+ return r;
240
+ }
241
+ function collect(obj, collectFunc) {
242
+ var result = [];
243
+ each(obj, function (a, b) {
244
+ if (isList(a = collectFunc(a, b))) // caution: extreme variable re-using of 'a'
245
+ each(a, function(rr) { result.push(rr); });
246
+ else if (a != null)
247
+ result.push(a);
248
+ });
249
+ return result;
250
+ }
251
+ function collectObj(obj, collectFunc) { // warning: 1:1 copy of collect(), with one diff... good for gzip..
252
+ var result = [];
253
+ eachObj(obj, function (a, b) {
254
+ if (isList(a = collectFunc(a, b))) // caution: extreme variable re-using of 'a'
255
+ each(a, function(rr) { result.push(rr); });
256
+ else if (a != null)
257
+ result.push(a);
258
+ });
259
+ return result;
260
+ }
261
+ function replace(s, regexp, sub) {
262
+ return toString(s).replace(regexp, sub||'');
263
+ }
264
+ function delay(f, delayMs) {
265
+ _window.setTimeout(f, delayMs||0);
266
+ }
267
+ function extractNumber(v) {
268
+ return parseFloat(replace(v, /^[^\d-]+/));
269
+ }
270
+
271
+ function getNaturalHeight(elementList) {
272
+ var q = {'$position': 'absolute', '$visibility': 'hidden', '$display': 'block', '$height': null};
273
+ var oldStyles = elementList['get'](q);
274
+ elementList['set'](q);
275
+ var h = elementList['get']('$height', true);
276
+ elementList['set'](oldStyles);
277
+ return h;
278
+ }
279
+
280
+ function now() {
281
+ return new Date().getTime();
282
+ }
283
+
284
+ function callArg(f) {f();}
285
+
286
+ // for ready()
287
+ function triggerDomReady() {
288
+ each(DOMREADY_HANDLER, callArg);
289
+ DOMREADY_HANDLER = null;
290
+ }
291
+
292
+ function ready(handler) {
293
+ // @cond debug if (typeof handler != 'function') error("First argument must be a function");
294
+ if (DOMREADY_HANDLER)
295
+ DOMREADY_HANDLER.push(handler);
296
+ else
297
+ delay(handler);
298
+ }
299
+
300
+ function $$(selector) {
301
+ return dollarRaw(selector)[0];
302
+ }
303
+
304
+ function EE(elementName, attributes, children, onCreate) {
305
+ // @cond debug if (!elementName) error("EE() requires the element name.");
306
+ // @cond debug if (/:/.test(elementName)) error("The element name can not create a colon (':').");
307
+
308
+ return function() {
309
+ var list = $(_document.createElement(elementName));
310
+ (isList(attributes) || !isObject(attributes)) ? list['add'](attributes) : list['set'](attributes)['add'](children);
311
+ if (onCreate)
312
+ onCreate(list);
313
+ return list;
314
+ };
315
+ }
316
+
317
+ function promise() {
318
+ var state; // undefined/null = pending, true = fulfilled, false = rejected
319
+ var values = []; // an array of values as arguments for the then() handlers
320
+ var deferred = []; // functions to call when set() is invoked
321
+
322
+ var set = function (newState, newValues) {
323
+ if (state == null) {
324
+ state = newState;
325
+ values = newValues;
326
+ delay(function() {
327
+ each(deferred, callArg);
328
+ });
329
+ }
330
+ };
331
+ /*$
332
+ * @id then
333
+ * @group REQUEST
334
+ * @name promise.then()
335
+ * @syntax promise.then()
336
+ * @syntax promise.then(onSuccess)
337
+ * @syntax promise.then(onSuccess, onError)
338
+ *
339
+ * @module WEB, UTIL
340
+ * Registers two callbacks that will be invoked when the ##promise#Promise##'s asynchronous operation finished
341
+ * successfully (<var>onSuccess</var>) or an error occurred (<var>onError</var>). The callbacks will be called after
342
+ * <var>then()</var> returned, from the browser's event loop.
343
+ * Minified implements the Promises/A+ specification, allowing interoperability with other Promises frameworks.
344
+ * You can chain <var>then()</var> invocations, as <var>then()</var> returns another Promise object that you can attach to.
345
+ *
346
+ * @example Simple handler for an HTTP request. Handles only success and ignores errors.
347
+ * <pre>
348
+ * $.request('get', '/weather.html')
349
+ * .then(function(txt) {
350
+ * alert('Got response!');
351
+ * });
352
+ * </pre>
353
+ *
354
+ * @example Including an error handler.
355
+ * <pre>
356
+ * $.request('get', '/weather.html')
357
+ * .then(function(txt) {
358
+ * alert('Got response!');
359
+ * }, function(err) {
360
+ * alert('Error!');
361
+ * }));
362
+ * </pre>
363
+ *
364
+ * @example Chained handler.
365
+ * <pre>
366
+ * $.request('get', '/weather.do')
367
+ * .then(function(txt) {
368
+ * showWeather(txt);
369
+ * }
370
+ * .then(function() {
371
+ * return $.request('get', '/traffic.do');
372
+ * }
373
+ * .then(function(txt) {
374
+ * showTraffic(txt);
375
+ * }
376
+ * .then(function() {
377
+ * alert('All result displayed');
378
+ * }, function() {
379
+ * alert('An error occurred');
380
+ * });
381
+ * </pre>
382
+ *
383
+ * @param onSuccess optional a callback function to be called when the operation has been completed successfully. The exact arguments it receives depend on the operation.
384
+ * If the function returns a ##promise#Promise##, that Promise will be evaluated to determine the state of the promise returned by <var>then()</var>. If it returns any other value, the
385
+ * returned Promise will also succeed. If the function throws an error, the returned Promise will be in error state.
386
+ * Pass <var>null</var> or <var>undefined</var> if you do not need the success handler.
387
+ * @param onError optional a callback function to be called when the operation failed. The exact arguments it receives depend on the operation. If the function returns a ##promise#Promise##, that promise will
388
+ * be evaluated to determine the state of the Promise returned by <var>then()</var>. If it returns anything else, the returned Promise will
389
+ * have success status. If the function throws an error, the returned Promise will be in the error state.
390
+ * You can pass <var>null</var> or <var>undefined</var> if you do not need the error handler.
391
+ * @return a new ##promise#Promise## object. If you specified a callback for success or error, the new Promises's state will be determined by that callback if it is called.
392
+ * If no callback has been provided and the original Promise changes to that state, the new Promise will change to that state as well.
393
+ */
394
+ var then = set['then'] = function(onFulfilled, onRejected) {
395
+ var newPromise = promise();
396
+ var callCallbacks = function() {
397
+ try {
398
+ var f = (state ? onFulfilled : onRejected);
399
+ if (isFunction(f)) {
400
+ var r = f.apply(null, values);
401
+ if (r && isFunction(r['then']))
402
+ r['then'](function(value){newPromise(true,[value]);}, function(value){newPromise(false,[value]);});
403
+ else
404
+ newPromise(true, [r]);
405
+ }
406
+ else
407
+ newPromise(state, values);
408
+ }
409
+ catch (e) {
410
+ newPromise(false, [e]);
411
+ }
412
+ };
413
+ if (state != null)
414
+ delay(callCallbacks);
415
+ else
416
+ deferred.push(callCallbacks);
417
+ return newPromise;
418
+ };
419
+ /*$
420
+ * @id always
421
+ * @group REQUEST
422
+ * @name promise.always()
423
+ * @syntax promise.always(callback)
424
+ * @module WEB, UTIL
425
+ * Registers a callback that will always be called when the ##promise#Promise##'s operation ended, no matter whether the operation succeeded or not.
426
+ * This is a convenience function that will call ##then() with the same function for both arguments. It shares all of its semantics.
427
+ *
428
+ * @example Simple handler for a HTTP request.
429
+ * <pre>
430
+ * $.request('get', '/weather.html')
431
+ * .always(function() {
432
+ * alert('Got response or error!');
433
+ * });
434
+ * </pre>
435
+ *
436
+ * @param callback a function to be called when the operation has been finished, no matter what its result was. The exact arguments depend on the operation and may
437
+ * vary depending on whether it succeeded or not. If the function returns a ##promise#Promise##, that Promise will
438
+ * be evaluated to determine the state of the returned Promise. If provided and it returns regularly, the returned promise will
439
+ * have success status. If it throws an error, the returned Promise will be in the error state.
440
+ * @return a new ##promise#Promise## object. Its state is determined by the callback.
441
+ */
442
+ set['always'] = function(func) { return then(func, func); };
443
+
444
+ /*$
445
+ * @id error
446
+ * @group REQUEST
447
+ * @name promise.error()
448
+ * @syntax promise.error(callback)
449
+ * @module WEB, UTIL
450
+ * Registers a callback that will be called when the operation failed.
451
+ * This is a convenience function that will invoke ##then() with the only the second argument set. It shares all of its semantics.
452
+ *
453
+ * @example Simple handler for a HTTP request.
454
+ * <pre>
455
+ * $.request('get', '/weather.html')
456
+ * .error(function() {
457
+ * alert('Got error!');
458
+ * });
459
+ * </pre>
460
+ *
461
+ * @param callback a function to be called when the operation has failed. The exact arguments depend on the operation. If the function returns a ##promise#Promise##, that Promise will
462
+ * be evaluated to determine the state of the returned Promise. If it returns regularly, the returned Promise will
463
+ * have success status. If it throws an error, the returned Promise will be in error state.
464
+ * @return a new ##promise#Promise## object. Its state is determined by the callback.
465
+ */
466
+ set['error'] = function(func) { return then(0, func); };
467
+ return set;
468
+ }
469
+
470
+ /*$
471
+ * @id ucode
472
+ * @dependency
473
+ */
474
+ // @condblock ie7compatibility
475
+ function ucode(a) {
476
+ return STRING_SUBSTITUTIONS[a] || ('\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4));
477
+ }
478
+ // @condend
479
+
480
+ /*$
481
+ * @stop
482
+ */
483
+
484
+ function $(selector, context, childOnly) {
485
+ // @condblock ready
486
+ // isList(selector) is no joke, older Webkit versions return a function for childNodes...
487
+ return isFunction(selector) ? ready(selector) : new M(dollarRaw(selector, context, childOnly));
488
+ // @condend
489
+ // @cond !ready return new M(dollarRaw(selector, context));
490
+ }
491
+
492
+ /*$
493
+ * @id debug
494
+ * @group OPTIONS
495
+ * (TBD) @configurable optional
496
+ * @doc no
497
+ * @name Debugging Support
498
+ */
499
+ function error(msg) {
500
+ if (_window.console) console.log(msg);
501
+ throw Exception("Minified debug error: " + msg);
502
+ }
503
+ // @cond debug MINI['debug'] = true;
504
+
505
+
506
+ /*$
507
+ * @id dollarraw
508
+ * @requires
509
+ * @dependency yes
510
+ */
511
+ function dollarRaw(selector, context, childOnly) {
512
+
513
+ function filterElements(list) { // converts into array, makes sure context is respected
514
+ var retList = (function flatten(a) { // flatten list, keep non-lists, remove nulls
515
+ return isList(a) ? collect(a, flatten) : a;
516
+ })(list);
517
+ if (parent)
518
+ return filter(retList, function(node) {
519
+ var a = node;
520
+ while (a = a.parentNode) {
521
+ if (a === parent)
522
+ return true;
523
+ if (childOnly)
524
+ return false;
525
+ }
526
+ // fall through to return undef
527
+ });
528
+ else
529
+ return retList;
530
+ }
531
+
532
+ var parent, steps, dotPos, subSelectors;
533
+ var elements, regexpFilter, useGEbC, className, elementName, reg;
534
+
535
+ if (context && (context = dollarRaw(context)).length != 1) // if not exactly one node, iterate through all and concat
536
+ return collect(context, function(ci) { return dollarRaw(selector, ci, childOnly);});
537
+ parent = context && context[0]; // note that context may have changed in the previous two lines!! you can't move this line
538
+
539
+ if (!isString(selector))
540
+ return filterElements(isList(selector) ? selector : [selector]);
541
+
542
+ // @condblock ie7compatibility
543
+ if ((subSelectors = selector.split(/\s*,\s*/)).length>1)
544
+ return collect(subSelectors, function(ssi) { return dollarRaw(ssi, parent, childOnly);});
545
+
546
+ if (steps = (/(\S+)\s+(.+)$/.exec(selector)))
547
+ return dollarRaw(steps[2], dollarRaw(steps[1], parent), childOnly);
548
+
549
+ if (selector != (subSelectors = replace(selector, /^#/)))
550
+ return filterElements([_document.getElementById(subSelectors)]);
551
+
552
+ // @cond debug if (/\s/.test(selector)) error("Selector has invalid format, please check for whitespace.");
553
+ // @cond debug if (/[ :\[\]]/.test(selector)) error("Only simple selectors with ids, classes and element names are allowed.");
554
+
555
+ parent = parent || _document;
556
+
557
+ elementName = (dotPos = /([^.]*)\.?([^.]*)/.exec(selector))[1];
558
+ className = dotPos[2];
559
+ elements = (useGEbC = parent.getElementsByClassName && className) ? parent.getElementsByClassName(className) : parent.getElementsByTagName(elementName || '*');
560
+
561
+ if (regexpFilter = useGEbC ? elementName : className) {
562
+ reg = new RegExp(BACKSLASHB + regexpFilter + BACKSLASHB, 'i');
563
+ elements = filter(elements, function(l) {return reg.test(l[useGEbC ? 'nodeName' : 'className']);});
564
+ }
565
+ // @condend
566
+
567
+ // @cond !ie7compatibility elements = (parent || _document).querySelectorAll(selector);
568
+ return parent ? filterElements(elements) : elements;
569
+ };
570
+
571
+
572
+ /*$
573
+ * @id length
574
+ * @group SELECTORS
575
+ * @requires dollar
576
+ * @name .length
577
+ * @syntax length
578
+ * @module WEB, UTIL
579
+ *
580
+ * Contains the number of elements in the list.
581
+ *
582
+ * @example
583
+ * <pre>
584
+ * var list = $('input');
585
+ * var myValues = {};
586
+ * for (var i = 0; i &lt; list.length; i++)
587
+ * myValues[list[i].name] = list[i].value;
588
+ * </pre>
589
+ */
590
+ // empty, always defined below
591
+
592
+ /*$
593
+ * @id listctor
594
+ */
595
+ /** @constructor */
596
+ function M(array) {
597
+ var len = this['length'] = array.length;
598
+ for (var i = 0; i < len; i++)
599
+ this[i] = array[i];
600
+ }
601
+
602
+ //// LIST FUNCTIONS ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
603
+
604
+ eachObj({
605
+ /*$
606
+ * @id each
607
+ * @group SELECTORS
608
+ * @requires dollar
609
+ * @configurable default
610
+ * @name .each()
611
+ * @syntax each(callback)
612
+ * @module WEB, UTIL
613
+ * Invokes the given function once for each item in the list. The function will be called with the item as first parameter and
614
+ * the zero-based index as second.
615
+ *
616
+ * @example This goes through all h2 elements of the class 'section' and changes their content:
617
+ * <pre>
618
+ * $('h2.section').each(function(item, index) {
619
+ * item.innerHTML = 'Section ' + index + ': ' + item.innerHTML;
620
+ * });
621
+ * </pre>
622
+ *
623
+ * @param callback The callback <code>function(item, index)</code> to invoke for each list element.
624
+ * <dl><dt>item</dt><dd>The current list element.</dd><dt>index</dt><dd>The second the zero-based index of the current element.</dd></dl>
625
+ * The callback's return value will be ignored.
626
+ * @return the list
627
+ */
628
+ 'each': function (callback) {
629
+ return each(this, callback);
630
+ },
631
+
632
+ /*$
633
+ * @id filter
634
+ * @group SELECTORS
635
+ * @requires dollar
636
+ * @configurable default
637
+ * @name .filter()
638
+ * @syntax filter(filterFunc)
639
+ * @module WEB, UTIL
640
+ * Creates a new ##list#Minified list## that contains only those items approved by the given callback function. The function is
641
+ * called once for each item.
642
+ * If the callback function returns true, the item is shallow-copied in the new list, otherwise it will be removed.
643
+ *
644
+ * @example Creates a list of all unchecked checkboxes.
645
+ * <pre>
646
+ * var list = $('input').filter(function(item) {
647
+ * return item.getAttribute('type') == 'checkbox' && item.checked;
648
+ * });
649
+ * </pre>
650
+ *
651
+ * @param filterFunc The filter callback <code>function(item, index)</code> that decides which elements to include:
652
+ * <dl><dt>item</dt><dd>The current list element.</dd><dt>index</dt><dd>The second the zero-based index of the current element.</dd>
653
+ * <dt class="returnValue">(callback return value)</dt><dd><var>true</var> to include the item in the new list, <var>false</var> to omit it.</dd></dl>
654
+ * @return the new, filtered ##list#list##
655
+ */
656
+ 'filter': function(filterFunc) {
657
+ return new M(filter(this, filterFunc));
658
+ },
659
+
660
+ /*$
661
+ * @id collect
662
+ * @group SELECTORS
663
+ * @requires dollar
664
+ * @configurable default
665
+ * @name .collect()
666
+ * @syntax collect(collectFunc)
667
+ * @module WEB, UTIL
668
+ * Creates a new ##list#Minified list## from the current list using the given callback function.
669
+ * The callback is invoked once for each element of the current list. The callback results will be added to the result list.
670
+ * The callback can return
671
+ * <ul>
672
+ * <li>an array or another list-like object. Its content will be appended to the resulting list.</li>
673
+ * <li>a regular object which will be appended to the list</li>
674
+ * <li><var>null</var> (or <var>undefined</var>), which means that no object will be added to the list.
675
+ * If you need to add <var>null</var> or <var>undefined</var> to the result list, put it into a single-element array.</li>
676
+ * </ul>
677
+ *
678
+ *
679
+ * @example Goes through input elements. If they are text inputs, their value will be added to the list:
680
+ * <pre>
681
+ * var texts = $('input').collect(function(input) {
682
+ * if (input.getAttribute('type') != null || input.getAttribute('type') == 'text')
683
+ * return input.value;
684
+ * else
685
+ * return null; // ignore
686
+ * });
687
+ * </pre>
688
+ *
689
+ * @example Creates a list of all children of the selected list.
690
+ * <pre>
691
+ * var childList = $('.mySections').collect(function(node) {
692
+ * return node.childNodes; // adds a while list of nodes
693
+ * });
694
+ * </pre>
695
+ *
696
+ * @example Goes through selected input elements. For each hit, the innerHTML is added twice, once in lower case and once in upper case:
697
+ * <pre>
698
+ * var elements = $('input.myTexts').collect(function(item) {
699
+ * return [item.innerHTML.toLowerCase(), item.innerHTML.toUpperCase()];
700
+ * });
701
+ * </pre>
702
+ *
703
+ * @param collectFunc The callback <code>function(item, index)</code> to invoke for each item:
704
+ * <dl><dt>item</dt><dd>The current list element.</dd><dt>index</dt><dd>The second the zero-based index of the current element.</dd>
705
+ * <dt class="returnValue">(callback return value)</dt><dd>If the callback returns a list, its elements will be added to
706
+ * the result list. Other objects will also be added. Nulls and <var>undefined</var> will be ignored and be not added to
707
+ * the new result list. </dd></dl>
708
+ * @return the new ##list#list##
709
+ */
710
+ 'collect': function(collectFunc) {
711
+ return new M(collect(this, collectFunc));
712
+ },
713
+
714
+ /*$
715
+ * @id sub
716
+ * @group SELECTORS
717
+ * @requires filter
718
+ * @configurable default
719
+ * @name .sub()
720
+ * @syntax sub(startIndex)
721
+ * @syntax sub(startIndex, endIndex)
722
+ * @module WEB, UTIL
723
+ * Returns a new ##list#Minified list## containing only the elements in the specified range. If there are no elements in the range,
724
+ * an empty list is returned.
725
+ * Negative indices are supported and will be added to the list's length, thus allowing you to specify ranges at the list's end.
726
+ *
727
+ * @example Adds some text the 3rd to 5th list elements:
728
+ * <pre>
729
+ * $('#myList li').sub(3, 6).add('Hello');
730
+ * </pre>
731
+ *
732
+ * @example Clears all elements but the first:
733
+ * <pre>
734
+ * $('#myList li').sub(1).fill();
735
+ * </pre>
736
+ *
737
+ * @example Changes the class of the last list element:
738
+ * <pre>
739
+ * $('#myList li').sub(-1).set('+lastItem');
740
+ * </pre>
741
+ *
742
+ * @param startIndex the 0-based position of the sub-list start. If negative, the list's length is added and the position is relative
743
+ * to the list's end.
744
+ * @param endIndex optional the 0-based position of the sub-list end. If negative, the list's length is added and the position is relative
745
+ * to the list's end. If omitted or null, all elements following the <var>startIndex</var> are included in the result.
746
+ * @return a new ##list#list## containing only the items in the index range.
747
+ */
748
+ 'sub': function(startIndex, endIndex) {
749
+ var self = this;
750
+ var s = (startIndex < 0 ? self['length']+startIndex : startIndex);
751
+ var e = endIndex >= 0 ? endIndex : self['length'] + (endIndex || 0);
752
+ return new M(filter(self, function(o, index) {
753
+ return index >= s && index < e;
754
+ }));
755
+ },
756
+
757
+
758
+ /*$
759
+ * @id find
760
+ * @group SELECTORS
761
+ * @requires
762
+ * @configurable default
763
+ * @name .find()
764
+ * @syntax find(findFunc)
765
+ * @syntax find(element)
766
+ * @module WEB, UTIL
767
+ * Finds a specific value in the list. There are two ways of calling <var>find()</var>:
768
+ * <ol>
769
+ * <li>With an element as argument. Then <var>find()</var> will search for the first occurrence of that element in the list
770
+ * and return the index. If it is not found, <var>find()</var> returns <var>undefined</var>.</li>
771
+ * <li>With a callback function. <var>find()</var> will then call the given function for each list element until the function
772
+ * returns a value that is not <var>null</var> or <var>undefined</var>. This value will be returned.</li>
773
+ * </ol>
774
+ *
775
+ * @example Determines the position of the element with the id '#wanted' among all li elements:
776
+ * <pre>
777
+ * var elementIndex = $('li').find($$('#wanted'));
778
+ * </pre>
779
+ *
780
+ * @example Goes through the elements to find the first div that has the class 'myClass', and returns this element:
781
+ * <pre>
782
+ * var myClassElement = $('div').find(function(e) { if ($(e).hasClass('myClass')) return e; });
783
+ * </pre>
784
+ *
785
+ * @param findFunc The callback <code>function(item, index)</code> that will be invoked for every list item until it returns a non-null value:
786
+ * <dl><dt>item</dt><dd>The current list element.</dd><dt>index</dt><dd>The second the zero-based index of the current element.</dd>
787
+ * <dt class="returnValue">(callback return value)</dt><dd>If the callback returns something other than <var>null</var> or
788
+ * <var>undefined</var>, <var>find()</var> will return it directly. Otherwise it will continue. </dd></dl>
789
+ * @param element the element to search for
790
+ * @return if called with an element, either the element's index in the list or <var>undefined</var> if not found. If called with a callback function,
791
+ * it returns either the value returned by the callback or <var>undefined</var>.
792
+ */
793
+ 'find': function(findFunc) {
794
+ var self = this, r;
795
+ var f = isFunction(findFunc) ? findFunc : function(obj, index) { if (findFunc === obj) return index; };
796
+ for (var i = 0; i < self.length; i++)
797
+ if ((r = f(self[i], i)) != null)
798
+ return r;
799
+ },
800
+
801
+ /*$
802
+ * @id hasclass
803
+ * @group SELECTORS
804
+ * @requires find
805
+ * @configurable default
806
+ * @name .hasClass()
807
+ * @syntax hasClass(className)
808
+ * @module WEB
809
+ * Checks whether at least one HTML element in the list has the given CSS class name.
810
+ * If yes, the first element that matches is returned. Otherwise the function returns <var>undefined</var>. List elements that do not
811
+ * have a <var>className</var> property will be ignored.
812
+ *
813
+ * @example Checks whether the element 'myElement' has the class 'myClass'. If yes, it sets the text color to red.
814
+ * <pre>
815
+ * if($('#myElement').hasClass('myClass'))
816
+ * $('#myElement').set('$color', 'red');
817
+ * </pre>
818
+ *
819
+ * @param className the class to to find
820
+ * @return the first element that has the given class, or <var>undefined</var> if not found
821
+ */
822
+ 'hasClass': function(className) {
823
+ var regexp = new RegExp(BACKSLASHB + className + BACKSLASHB);
824
+ return this['find'](function(e) { return regexp.test(e.className) ? e : null; });
825
+ },
826
+
827
+ /*$
828
+ * @id remove
829
+ * @group SELECTORS
830
+ * @requires dollar
831
+ * @configurable default
832
+ * @name .remove()
833
+ * @syntax remove()
834
+ * @module WEB
835
+ * Removes all nodes of the list from the DOM tree.
836
+ *
837
+ * @example Removes the element with the id 'myContainer', including all children, from the DOM tree.
838
+ * <pre>
839
+ * $('#myContainer').remove();
840
+ * </pre>
841
+ */
842
+ 'remove': function() {
843
+ each(this, function(obj) {obj.parentNode.removeChild(obj);});
844
+ },
845
+
846
+ /*$
847
+ * @id text
848
+ * @group SELECTORS
849
+ * @requires dollar
850
+ * @configurable default
851
+ * @name .text()
852
+ * @syntax text()
853
+ * @module WEB
854
+ * Returns the concatenated text content of all nodes in the list.
855
+ * This is done by going recursively through all elements and their children. The values of text and CDATA nodes
856
+ * will be appended to the resulting string.
857
+ *
858
+ * Please note that, unlike jQuery's <var>text()</var>, Minified's will not set text content. Use ##fill() to do this.
859
+ *
860
+ * @example Returns the text of the element with the id 'myContainer'.
861
+ * <pre>
862
+ * var content = $('#myContainer').text();
863
+ * </pre>
864
+ */
865
+ 'text': function () {
866
+ function extractString(e) {
867
+ var nodeType = isNode(e);
868
+ if (nodeType == 1)
869
+ return collect(e['childNodes'], extractString);
870
+ else if (nodeType < 5) // 2 is impossible (attribute), so only 3 (text) and 4 (cdata)..
871
+ return e['data'];
872
+ else
873
+ return null;
874
+ }
875
+ return collect(this, extractString)['join']('');
876
+ },
877
+
878
+ /*$
879
+ * @id get
880
+ * @group SELECTORS
881
+ * @requires dollar
882
+ * @configurable default
883
+ * @name .get()
884
+ * @syntax get(name)
885
+ * @syntax get(name, toNumber)
886
+ * @syntax get(list)
887
+ * @syntax get(list, toNumber)
888
+ * @syntax get(map)
889
+ * @syntax get(map, toNumber)
890
+ * @module WEB
891
+ * Retrieves properties, attributes and styles from the list's first element. The syntax to request those values is mostly identical with ##set(). You can either
892
+ * get a single value if you specify only one name, or get a name->value map when you specify several names using an array or a map.
893
+ *
894
+ * @example Retrieves the id, title attribute and the background color of the element '#myElement':
895
+ * <pre>
896
+ * var id = $('#myElement).get('id');
897
+ * var title = $('#myElement).get('@title');
898
+ * var bgColor = $('#myElement).get('$backgroundColor');
899
+ * </pre>
900
+ *
901
+ * @example Retrieves the id, title attribute and the background color of the element '#myElement' as a map:
902
+ * <pre>
903
+ * var m = $('#myElement).get(['id', '@title', '$backgroundColor']);
904
+ * var id = m.id;
905
+ * var title = m['@title'];
906
+ * var bgColor = m.$backgroundColor;
907
+ * </pre>
908
+ *
909
+ * @example Uses ##get() and ##set() to reposition an element:
910
+ * <pre>
911
+ * var coords = $('#myElement').get({$top: 0, $left: 0}, true);
912
+ * coords.$top = coords.$top + 10 + 'px';
913
+ * coords.$left = coords.$left + 20 + 'px';
914
+ * $('#myElement').set(coords);
915
+ * </pre>
916
+ * Please note that the values of $top and $left in the <var>get()</var> invocation do not matter and will be ignored!
917
+ *
918
+ * @param name the name of the property, attribute or style. To retrieve a JavaScript property, just use its name without prefix. To get an attribute value,
919
+ * prefix the name with a '@'. A '$' prefix will retrieve a CSS style. The syntax for the CSS styles is camel-case (e.g. "backgroundColor", not "background-color").
920
+ * Shorthand properties like "border" or "margin" are not supported. You must use the full name, e.g. "marginTop". Minified will try to determine the effective style
921
+ * and thus will return the value set in style sheets if not overwritten using a regular style.
922
+ * Using just '$' as name will retrieve the 'className' property of the object, a space-separated list of all CSS classes.
923
+ * The special name '$$' will set the element's style attribute in a browser independent way.
924
+ * '$$fade' returns a value between 0 and 1 that specifies the element's
925
+ * opacity. '$$slide' returns the height of the element in pixels, with a 'px' suffix. Both '$$fade' and '$$slide' will also check the CSS styles 'visibility' and 'display'
926
+ * to determine whether the object is visible at all. If not, they will return 0.
927
+ * @param list in order to retrieve more than one value, you can specify several names in an array or list. <var>get()</var> will then return a name->value map of results.
928
+ * @param map if you specify an object that is neither list nor string, <var>get()</var> will use it as a map of property names. Each property name will be requested. The values of the properties in
929
+ * the map will be ignored. <var>get()</var> will then return a name->value map of results.
930
+ * @param toNumber if 'true', <var>get()</var> converts all returned values into numbers. If they are strings,
931
+ * <var>get()</var> removes any non-numeric characters before the conversion. This is useful when you request
932
+ * a CSS property such as '$marginTop' that returns a value with a unit suffix, like "21px". <var>get()</var> will convert it
933
+ * into a number and return 21. If the returned value is not parsable as a number, <var>NaN</var> will be returned.
934
+ * @return if <var>get()</var> was called with a single name, it returns the corresponding value.
935
+ * If a list or map was given, <var>get()</var> returns a new map with the names as keys and the values as values.
936
+ * Always returns <var>undefined</var> if the list is empty.
937
+ */
938
+ 'get': function(spec, toNumber) {
939
+ var self = this, element = self[0];
940
+
941
+ if (element) {
942
+ if (isString(spec)) {
943
+ var name = replace(spec, /^[$@]/);
944
+ var s;
945
+ if (spec == '$')
946
+ s = element.className;
947
+ else if (spec == '$$') {
948
+ // @condblock ie8compatibility
949
+ if (IS_PRE_IE9)
950
+ s = element['style']['cssText'];
951
+ else
952
+ // @condend
953
+ s = element.getAttribute('style');
954
+ }
955
+ // @condblock fadeslide
956
+ else if (/\$\$/.test(spec) && (element['style']['visibility'] == 'hidden' || element['style']['display'] == 'none')) {
957
+ s = 0;
958
+ }
959
+ else if (spec == '$$fade') {
960
+ s = isNaN(s =
961
+ // @condblock ie8compatibility
962
+ IS_PRE_IE9 ? extractNumber(element['style']['filter'])/100 :
963
+ // @condend
964
+ extractNumber(element['style']['opacity'])
965
+ ) ? 1 : s;
966
+ }
967
+ else if (spec == '$$slide') {
968
+ s = self['get']('$height');
969
+ }
970
+ // @condend fadeslide
971
+ else if (/^\$/.test(spec)) {
972
+ // @condblock ie8compatibility
973
+ if (!_window.getComputedStyle)
974
+ s = (element.currentStyle||element['style'])[name];
975
+ else
976
+ // @condend
977
+ s = _window.getComputedStyle(element, null).getPropertyValue(replace(name, /[A-Z]/g, function (match) { return '-' + match.toLowerCase(); }));
978
+ }
979
+ else if (/^@/.test(spec))
980
+ s = element.getAttribute(name);
981
+ else
982
+ s = element[name];
983
+ return toNumber ? extractNumber(s) : s;
984
+ }
985
+ else {
986
+ var r = {};
987
+ (isList(spec) ? each : eachObj)(spec, function(name) {
988
+ r[name] = self['get'](name, toNumber);
989
+ });
990
+ return r;
991
+ }
992
+ }
993
+ },
994
+
995
+ /*$
996
+ * @id set
997
+ * @group SELECTORS
998
+ * @requires dollar get
999
+ * @configurable default
1000
+ * @name .set()
1001
+ * @syntax set(name, value)
1002
+ * @syntax set(properties)
1003
+ * @syntax set(cssClasses)
1004
+ * @module WEB
1005
+ *
1006
+ * Modifies the list's elements by setting their properties, attributes, CSS styles and/or CSS classes. You can either supply a
1007
+ * single name and value to set only one property, or you can provide an object that contains name/value pairs to describe more than one property.
1008
+ * More complex operations can be accomplished by supplying a function as value. It will then be called for each element that will
1009
+ * be set.
1010
+ *
1011
+ * The name given to <var>set()</var> defines what kind of data you are setting. The following name schemes are supported:
1012
+ *
1013
+ * <table>
1014
+ * <tr><th>Name Schema</th><th>Example</th><th>Sets what?</th><th>Description</th></tr>
1015
+ * <tr><td>name</td><td>innerHTML</td><td>Property</td><td>A name without prefix of '$' or '@' sets a property of the object.</td></tr>
1016
+ * <tr><td>@name</td><td>@href</td><td>Attribute</td><td>Sets the HTML attribute using setAttribute(). In order to stay compatible with Internet Explorer 7 and earlier,
1017
+ * you should not set the attributes '@class' and '@style'. Instead use '$' and '$$' as shown below.</td></tr>
1018
+ * <tr><td>$name</td><td>$fontSize</td><td>CSS Property</td><td>Sets a style using the element's <var>style</var> object.</td></tr>
1019
+ * <tr><td>$</td><td>$</td><td>CSS Classes</td><td>A simple <var>$</var> modifies the element's CSS classes using the object's <var>className</var> property. The value is a
1020
+ * space-separated list of class names. If prefixed with '-' the class is removed, a '+' prefix adds the class and a class name without prefix toggles the class.
1021
+ * The name '$' can also be omitted if <var>set</var> is called with class names as only argument.</td></tr>
1022
+ * <tr><td>$$</td><td>$$</td><td>Style</td><td>Sets the element's style attribute in a browser-independent way.</td></tr>
1023
+ * <tr><td>$$fade</td><td>$$fade</td><td>Fade Effect</td><td>The name '$$fade' sets the opacity of the element in a browser-independent way. The value must be a number
1024
+ * between 0 and 1. '$$fade' will also automatically control the element's 'visibility' and 'display' styles. If the value is 0,
1025
+ * the element's visibility will automatically be set to 'hidden'. If the value is larger, the visibility will be set to
1026
+ * 'visible' and the display style to 'block'. '$$fade' only works with block elements.</td></tr>
1027
+ * <tr><td>$$slide</td><td>$$slide</td><td>Slide Effect</td><td>The name '$$slide' allows a vertical slide-out or slide-in effect. The value must be a number
1028
+ * between 0 and 1. '$$slide' will also automatically control the element's 'visibility' and 'display' styles. If the value is 0,
1029
+ * the element's visibility will automatically be set to 'hidden'. If the value is larger, the visibility will be set to
1030
+ * 'visible' and the display style to 'block'. '$$slide' only works with block elements.</td></tr>
1031
+ * </table>
1032
+ *
1033
+ * @example Unchecking checkboxes:
1034
+ * <pre>
1035
+ * $('input.checkbox').set('checked', false);
1036
+ * </pre>
1037
+ *
1038
+ * @example Changing the <var>innerHTML</var property of an element:
1039
+ * <pre>
1040
+ * $('#toc').set('innerHTML', 'Content');
1041
+ * </pre>
1042
+ *
1043
+ * @example Changing attributes:
1044
+ * <pre>
1045
+ * $('a.someLinks').set('@href', 'http://www.example.com/');
1046
+ * </pre>
1047
+ *
1048
+ * @example Removing attributes:
1049
+ * <pre>
1050
+ * $('a.someLinks').set('@title', null);
1051
+ * </pre>
1052
+ *
1053
+ * @example Changing styles:
1054
+ * <pre>
1055
+ * $('.bigText').set('$font-size', 'x-large');
1056
+ * </pre>
1057
+ *
1058
+ * @example Adding and removing CSS classes:
1059
+ * <pre>
1060
+ * $('.myElem').set('$', '+myClass -otherClass');
1061
+ * </pre>
1062
+ *
1063
+ * @example Toggling a CSS class:
1064
+ * <pre>
1065
+ * $('.myElem').set('$', 'on');
1066
+ * </pre>
1067
+ *
1068
+ * @example Shortcut for CSS manipulation:
1069
+ * <pre>
1070
+ * $('.myElem').set('+myClass -otherClass on');
1071
+ * </pre>
1072
+ *
1073
+ * @example Making an element transparent:
1074
+ * <pre>
1075
+ * $('.seeThrough').set('$$fade', 0.5);
1076
+ * </pre>
1077
+ *
1078
+ * @example Making an element visible. Note that $$fade will set the element's display style to 'block' and visibility style to 'visible'.
1079
+ * <pre>
1080
+ * $('.myElem').set('$$fade', 1);
1081
+ * </pre>
1082
+ *
1083
+ * @example Using a map to change several properties:
1084
+ * <pre>
1085
+ * $('input.checkbox').set({checked: false,
1086
+ * 'parentNode.@title': 'Check this'});
1087
+ * </pre>
1088
+ *
1089
+ * @example Changing CSS with a map:
1090
+ * <pre>
1091
+ * $('.importantText').set({$fontSize: 'x-large',
1092
+ * $color: 'black',
1093
+ * $backgroundColor: 'red',
1094
+ * $: '+selected -default'});
1095
+ * </pre>
1096
+ *
1097
+ * @example You can specify a function as value to modify a value instead of just setting it:
1098
+ * <pre>
1099
+ * $('h2').set('innerHTML', function(oldValue, index) {
1100
+ * return 'Chapter ' + index + ': ' + oldValue.toUpperCase();
1101
+ * });
1102
+ * </pre>
1103
+ *
1104
+ * @param name the name of a single property or attribute to modify. If prefixed with '@', it is treated as a DOM element's attribute.
1105
+ * A dollar ('$') prefix is a shortcut for CSS styles. A simple dollar ('$') as name modifies CSS classes.
1106
+ * The special name '$$' allows you to set the <var>style</var> attribute in a browser independent way.
1107
+ * The special name '$$fade' and '$$slide' create fade and slide effects, and both expect a value between 0 and 1.
1108
+ *
1109
+ *
1110
+ * @param value the value to set. If value is null and name specified an attribute, the attribute will be removed.
1111
+ * If a dollar ('$') has been passed as name, the value can contain space-separated CSS class names. If prefixed with a '+' the class will be added,
1112
+ * with a '-' prefix the class will be removed. Without prefix, the class will be toggled.
1113
+ * If <var>value</var> is a function, the <code>function(oldValue, index, obj)</code> will be invoked for each list element
1114
+ * to evaluate the new value:
1115
+ * <dl><dt>oldValue</dt><dd>The old value of the property to be changed, as returned by ##get().
1116
+ * For the CSS style names, this is the computed style of the property </dd>
1117
+ * <dt>index</dt><dd>The list index of the object owning the property</dd>
1118
+ * <dt>obj</dt><dd>The list element owning the property.<dd>
1119
+ * <dt class="returnValue">(callback return value)</dt><dd>The value to be set.</dd></dl>
1120
+ * Functions are not supported by '$'.
1121
+ * @param properties a Object as map containing names as keys and the values to set as map values. See above for the name syntax.
1122
+ * @param cssClasses if <var>set()</var> is invoked with a string as single argument, the name "$" (CSS classes) is used and the argument is the
1123
+ * value. See above for CSS syntax.
1124
+ * Instead of a string, you can also specify a <code>function(oldValue, index, obj)</code> to modify the existing classes.
1125
+ * @return the list
1126
+ */
1127
+ 'set': function (name, value) {
1128
+ function setAttr(obj, n, v) {
1129
+ if (v != null)
1130
+ obj.setAttribute(n, v);
1131
+ else
1132
+ obj.removeAttribute(n);
1133
+ }
1134
+ var self = this, v;
1135
+ // @cond debug if (name == null) error("First argument must be set!");
1136
+ if (value !== undef) {
1137
+ // @cond debug if (!/string/i.test(typeof name)) error('If second argument is given, the first one must be a string specifying the property name");
1138
+
1139
+ // @condblock fadeslide
1140
+ if (name == '$$fade' || name == '$$slide') {
1141
+ self.set({'$visibility': (v = extractNumber(value)) > 0 ? 'visible' : 'hidden', '$display': 'block'})
1142
+ .set((name == '$$fade') ? (
1143
+ // @condblock ie8compatibility
1144
+ IS_PRE_IE9 ? {'$filter': 'alpha(opacity = '+(100*v)+')', '$zoom': 1} :
1145
+ // @condend ie8compatibility
1146
+ {'$opacity': v})
1147
+ :
1148
+ {'$height': /px$/.test(value) ? value : function(oldValue, idx, element) { return v * (v && getNaturalHeight($(element))) + 'px';},
1149
+ '$overflow': 'hidden'}
1150
+ );
1151
+ }
1152
+ else
1153
+ // @condend fadeslide
1154
+ each(self, function(obj, c) {
1155
+ var nameClean = replace(name, /^[@$]/);
1156
+ var className = obj['className'] || '';
1157
+ var newObj = /^\$/.test(name) ? obj.style : obj;
1158
+ var newValue = isFunction(value) ? value($(obj).get(name), c, obj) : value;
1159
+ if (name == '$') {
1160
+ if (newValue != null) {
1161
+ each(newValue.split(/\s+/), function(clzz) {
1162
+ var cName = replace(clzz, /^[+-]/);
1163
+ var oldClassName = className;
1164
+ className = replace(className, new RegExp(BACKSLASHB + cName + BACKSLASHB));
1165
+ if (/^\+/.test(clzz) || (cName==clzz && oldClassName == className)) // for + and toggle-add
1166
+ className += ' ' + cName;
1167
+ });
1168
+ obj['className'] = replace(className, /^\s+|\s+(?=\s|$)/g);
1169
+ }
1170
+ }
1171
+ else if (name == '$$') {
1172
+ // @condblock ie8compatibility
1173
+ if (IS_PRE_IE9)
1174
+ newObj['cssText'] = newValue;
1175
+ else
1176
+ // @condend
1177
+ setAttr(obj, 'style', newValue);
1178
+ }
1179
+ else if (!/^@/.test(name))
1180
+ newObj[nameClean] = newValue;
1181
+ else
1182
+ setAttr(newObj, nameClean, newValue);
1183
+ });
1184
+ }
1185
+ else if (isString(name) || isFunction(name))
1186
+ self.set('$', name);
1187
+ else
1188
+ eachObj(name, function(n,v) { self.set(n, v); });
1189
+ return self;
1190
+ },
1191
+
1192
+
1193
+ /*$
1194
+ * @id add
1195
+ * @group ELEMENT
1196
+ * @requires dollar
1197
+ * @configurable default
1198
+ * @name .add()
1199
+ * @syntax add(text)
1200
+ * @syntax add(factoryFunction)
1201
+ * @syntax add(list)
1202
+ * @syntax add(node)
1203
+ * @module WEB
1204
+ * Adds the given node(s) as content to the list's HTML elements. If a string has been given, it will be added as text node.
1205
+ * If you pass a function, it will be invoked for each list element to create the node to add. This is called a factory function. It can return all
1206
+ * values allowed by <var>add()</var>, including another function to be called.
1207
+ * If you pass a list or a function returning a list, all its elements will be added using the rules above.
1208
+ *
1209
+ * It is also possible to pass a DOM node, but it will be added <strong>only to the first element of the list</strong>, because DOM
1210
+ * does not allow adding it more than once. You should use a factory function to add DOM elements to more than one list element. ##EE()
1211
+ * and ##clone() are two simple ways to create factory functions.
1212
+ *
1213
+ * @example Using the following HTML:
1214
+ * <pre>
1215
+ * &lt;div id="comments">Here is some text.&lt;br/>&lt;/div>
1216
+ * </pre>
1217
+ * The next line appends a text node to the given 'comment' div:
1218
+ * <pre>
1219
+ * $('#comments').add('Some additional text.');
1220
+ * </pre>
1221
+ * This results in:
1222
+ * <pre>
1223
+ * &lt;div id="comments">Here is some text.&lt;br/>&lt;Some additional text./div>
1224
+ * </pre>
1225
+ *
1226
+ * @example Using the following HTML:
1227
+ * <pre>
1228
+ * &lt;ul id="myList">
1229
+ * &lt;li>First list entry&lt;/li>
1230
+ * &lt;li>Second list entry&lt;/li>
1231
+ * &lt;/ul>
1232
+ * </pre>
1233
+ * The following Javascript adds an element to the list:
1234
+ * <pre>
1235
+ * $('#myList').add(EE('li', 'My extra point');
1236
+ * </pre>
1237
+ * This results in
1238
+ * <pre>
1239
+ * &lt;ul id="myList">
1240
+ * &lt;li>First list entry&lt;/li>
1241
+ * &lt;li>Second list entry&lt;/li>
1242
+ * &lt;li>My extra point&lt;/li>
1243
+ * &lt;/ul>
1244
+ * </pre>
1245
+ *
1246
+ * @example Use a list to add several elements at once:
1247
+ * <pre>
1248
+ * $('#comments').add([
1249
+ * EE('br'),
1250
+ * 'Some text',
1251
+ * EE('span', {'className': 'highlight'}, 'Some highlighted text')
1252
+ * ]);
1253
+ * </pre>
1254
+ *
1255
+ * @example You can implement functions to create elements depending on the context:
1256
+ * <pre>
1257
+ * $('.chapter').add(function(parent, index) { return EE('h2', 'Chapter number ' + index); });
1258
+ * </pre>
1259
+ *
1260
+ * @param text a string or number to add as text node
1261
+ * @param factoryFunction a <code>function(listItem, listIndex)</code> that will be invoked for each list element to create the nodes:
1262
+ * <dl><dt>listItem</dt><dd>The list element that will receive the new children.</dd>
1263
+ * <dt>listIndex</dt><dd>The index of the list element that will receive the new children.</dd>
1264
+ * <dt class="returnValue">(callback return value)<dt><dd>The node(s) to be added to the list element.
1265
+ * Can be either a string for a text node, an HTML element or a list containing strings, lists, functions and/or DOM nodes.
1266
+ * If a function is returned or in the list, it will be invoked recursively with the same arguments.</dd></dl>
1267
+ * @param list a list containing text, functions, nodes or more lists. Please note that if you have DOM nodes in this list
1268
+ * and attempt to add them to more than one element, the result is undefined. You should always use factories
1269
+ * if you add DOM nodes to more than one element.
1270
+ * @param node a DOM node to add <strong>only to the first element</strong> of the list.
1271
+ * @return the current list
1272
+ */
1273
+ 'add': function (children, addFunction) {
1274
+ return each(this, function(e, index) {
1275
+ var lastAdded;
1276
+ (function appendChildren(c) {
1277
+ if (isList(c))
1278
+ each(c, appendChildren);
1279
+ else if (isFunction(c))
1280
+ appendChildren(c(e, index));
1281
+ else if (c != null) { // must check null, as 0 is a valid parameter
1282
+ var n = isNode(c) ? c : _document.createTextNode(c);
1283
+ if (lastAdded)
1284
+ lastAdded.parentNode.insertBefore(n, lastAdded.nextSibling);
1285
+ else if (addFunction)
1286
+ addFunction(n, e, e.parentNode);
1287
+ else
1288
+ e.appendChild(n);
1289
+ lastAdded = n;
1290
+ }
1291
+ })(isNode(children) && index ? null : children);
1292
+ });
1293
+ },
1294
+
1295
+
1296
+ /*$
1297
+ * @id fill
1298
+ * @group ELEMENT
1299
+ * @requires dollar add remove
1300
+ * @configurable default
1301
+ * @name .fill()
1302
+ * @syntax fill()
1303
+ * @syntax fill(text)
1304
+ * @syntax fill(factoryFunction)
1305
+ * @syntax fill(list)
1306
+ * @syntax fill(node)
1307
+ * @module WEB
1308
+ * Sets the content of the list's HTML elements, replacing old content. If a string has been given, it will be added as text node.
1309
+ * If you pass a function, it will be invoked for each list member to create a node. The function prototype is <code>function(parent, index)</code>.
1310
+ * It can return all values allowed by <var>fill()</var>, including another function to be called.
1311
+ * If you pass a list or a function returns a list, all its elements will be added using the rules above.
1312
+ *
1313
+ * It is also possible to pass a DOM node, but it will be set <strong>only in the first element of the list</strong>, because DOM
1314
+ * does not allow adding it more than once.
1315
+ *
1316
+ * Call <var>fill()</var> without arguments to remove all children from a node.
1317
+ *
1318
+ * @example Using the following HTML:
1319
+ * <pre>
1320
+ * &lt;div id="status">Done&lt;/div>
1321
+ * </pre>
1322
+ * <var>fill()</var> with a simple string replaces the element's content with the text:
1323
+ * <pre>
1324
+ * $('#status').fill('Please Wait..');
1325
+ * </pre>
1326
+ * Results in:
1327
+ * <pre>
1328
+ * &lt;div id="status">Please Wait..&lt;/div>
1329
+ * </pre>
1330
+ *
1331
+ * @example Pass an Element Factory to replace the old content with that:
1332
+ * <pre>
1333
+ * $('#status').fill(EE('span', {'className': 'bold'}, 'Please Wait...'));
1334
+ * </pre>
1335
+ * With the previous example's HTML, this would create this:
1336
+ * <pre>
1337
+ * &lt;div id="status">&lt;span class='bold'>Please Wait..&lt;/span>&lt;/div>
1338
+ * </pre>
1339
+ *
1340
+ * @example You can also pass a list of elements and texts:
1341
+ * <pre>
1342
+ * $('#status').fill(['Here', EE('br'), 'are', EE('br'), 'four', EE('br'), 'lines.]);
1343
+ * </pre>
1344
+ *
1345
+ * @example Or a complete structure built using EE:
1346
+ * <pre>
1347
+ * $('#myListContainer').fill([
1348
+ * EE('h2', 'My List'),
1349
+ * EE('ol', [EE('li', 'First Item'), EE('li', 'Second Item'), EE('li', 'Third Item')])
1350
+ * ]);
1351
+ * </pre>
1352
+ *
1353
+ * @example You can write a factory function that re-creates the list for every instance:
1354
+ * <pre>
1355
+ * $('.listContainers').fill(function(e, index) { return [
1356
+ * EE('h2', 'List Number '+index),
1357
+ * EE('ol', [EE('li', 'First Item'),
1358
+ * EE('li', 'Second Item'),
1359
+ * EE('li', 'Third Item')
1360
+ * ])]});
1361
+ * </pre>
1362
+ *
1363
+ * @example <var>fill()</var> without arguments deletes the content of the list elements:
1364
+ * <pre>
1365
+ * $('.listContainers').fill();
1366
+ * </pre>
1367
+ *
1368
+ * @param text a string to set as text node of the list elements
1369
+ * @param factoryFunction a <code>function(listItem, listIndex)</code> that will be invoked for each list element to create the nodes:
1370
+ * <dl><dt>listItem</dt><dd>The list element that will receive the new children.</dd>
1371
+ * <dt>listIndex</dt><dd>The index of the list element that will receive the new children.</dd>
1372
+ * <dt class="returnValue">(callback return value)<dt><dd>The node(s) to be added to the list element.
1373
+ * Can be either a string for a text node, an HTML element or a list containing strings, lists, functions and/or DOM nodes.
1374
+ * If a function is returned or in the list, it will be invoked recursively with the same arguments.</dd></dl>
1375
+
1376
+ * @param list a list containing text, functions, nodes or more list. Please note that if you have DOM nodes in this list
1377
+ * and attempt to add them to more than one element, the result is <var>undefined</var>. You should always use factories if your
1378
+ * Minified list contains more than one item.
1379
+ * @param node a DOM node to set <strong>only in the first element</strong> of the list.
1380
+
1381
+ * @return the current list
1382
+ */
1383
+ 'fill': function (children) {
1384
+ return each(this, function(e) { $(e.childNodes)['remove'](); }).add(children);
1385
+ },
1386
+
1387
+ /*$
1388
+ * @id addbefore
1389
+ * @group ELEMENT
1390
+ * @requires dollar add
1391
+ * @configurable default
1392
+ * @name .addBefore()
1393
+ * @syntax addBefore(text)
1394
+ * @syntax addBefore(factoryFunction)
1395
+ * @syntax addBefore(list)
1396
+ * @syntax addBefore(node)
1397
+ * @module WEB
1398
+ * Inserts the given text or element(s) as sibling in front of each HTML element in the list.
1399
+ * If a string has been given, it will be added as text node.
1400
+ * If you pass a function, it will be invoked for each list element to create the new node, with the arguments <code>function(parent, index)</code>.
1401
+ * It can return all values allowed by <var>addBefore()</var>, including another function to be called.
1402
+ * If you pass a list or a function returns a list, all its elements will be added using the rules above.
1403
+ *
1404
+ * It is also possible to pass a DOM node, but it will be added <strong>only to the first element of the list</strong>, because DOM
1405
+ * does not allow adding it more than once.
1406
+ *
1407
+ * @example Using the following HTML:
1408
+ * <pre>
1409
+ * &lt;div>
1410
+ * <div id="mainText">Here is some text</div>
1411
+ * &lt;/div>
1412
+ * </pre>
1413
+ * addBefore() adds text in front of the selected list items.
1414
+ * <pre>
1415
+ * $('#mainText').addBefore('COMMENT');
1416
+ * </pre>
1417
+ * This results in:
1418
+ * <pre>
1419
+ * &lt;div>
1420
+ * COMMENT
1421
+ * &lt;div id="mainText">Here is some text&lt;/div>
1422
+ * &lt;/div>
1423
+ * </pre>
1424
+ *
1425
+ * @example You can also pass an Element Factory:
1426
+ * <pre>
1427
+ * $('#mainText').addBefore(EE('span', {'className': 'important'}, 'WARNING'));
1428
+ * </pre>
1429
+ * With the previous example's HTML, this would create this HTML:
1430
+ * <pre>
1431
+ * &lt;div>
1432
+ * &lt;span class="important">WARNING&lt;/span>
1433
+ * &lt;div id="mainText">Here is some text&lt;/div>
1434
+ * &lt;/div>
1435
+ * </pre>
1436
+ *
1437
+ * @example Lists of elements and nodes are possible as well.
1438
+ * <pre>
1439
+ * $('#status').addBefore([EE('hr'), 'WARNING']);
1440
+ * </pre>
1441
+ *
1442
+ * @param text a string to add as text node of the list elements
1443
+ * @param factoryFunction a <code>function(listItem, listIndex)</code> that will be invoked for each list element to create the nodes:
1444
+ * <dl><dt>listItem</dt><dd>The list element that will receive the new children.</dd>
1445
+ * <dt>listIndex</dt><dd>The index of the list element that will receive the new children.</dd>
1446
+ * <dt class="returnValue">(callback return value)<dt><dd>The node(s) to be added to the list element.
1447
+ * Can be either a string for a text node, an HTML element or a list containing strings, lists, functions and/or DOM nodes.
1448
+ * If a function is returned or in the list, it will be invoked recursively with the same arguments.</dd></dl>
1449
+ * @param list a list containing text, functions, nodes or more list. Please note that if you have DOM nodes in this list
1450
+ * and attempt to add them to more than one element, the result is <var>undefined</var>. You should always use factories if your
1451
+ * Minified list contains more than one item.
1452
+ * @param node a DOM node to add <strong>only to the first element</strong> of the list.
1453
+ * @return the current list
1454
+ */
1455
+ 'addBefore': function (children) {
1456
+ return this.add(children, function(newNode, refNode, parent) { parent.insertBefore(newNode, refNode); });
1457
+ },
1458
+
1459
+ /*$
1460
+ * @id addafter
1461
+ * @group ELEMENT
1462
+ * @requires dollar add
1463
+ * @configurable default
1464
+ * @name .addAfter()
1465
+ * @syntax addAfter(text)
1466
+ * @syntax addAfter(factoryFunction)
1467
+ * @syntax addAfter(list)
1468
+ * @syntax addAfter(node)
1469
+ * @module WEB
1470
+ * Inserts the given text or element(s) as sibling after each HTML element in the list.
1471
+ * If a string has been given, it will be added as text node.
1472
+ * If you pass a function, it will be invoked for each list element to create the node(s) to add. It can return all values
1473
+ * allowed by <var>addAfter()</var>, including another function to be called.
1474
+ * If you pass a list or a function returns a list, all its elements will be added using the rules above.
1475
+ *
1476
+ * It is also possible to pass a DOM node, but it will be added <strong>only to the first element of the list</strong>, because DOM
1477
+ * does not allow adding it more than once.
1478
+ *
1479
+ * @example Using the following HTML:
1480
+ * <pre>
1481
+ * &lt;div>
1482
+ * &lt;div id="mainText">Here is some text&lt;/div>
1483
+ * &lt;/div>
1484
+ * </pre>
1485
+ * Use addAfter() with a simple string to add a text node.
1486
+ * <pre>
1487
+ * $('#mainText').addAfter('Disclaimer: bla bla bla');
1488
+ * </pre>
1489
+ * This results in the following HTML:
1490
+ * <pre>
1491
+ * &lt;div>
1492
+ * &lt;div id="mainText">Here is some text&lt;/div>
1493
+ * Disclaimer: bla bla bla
1494
+ * &lt;/div>
1495
+ * </pre>
1496
+ *
1497
+ * @example You can also pass an Element Factory:
1498
+ * <pre>
1499
+ * $('#mainText').addAfter(EE('span', {'className': 'disclaimer'}, 'Disclaimer: bla bla bla'));
1500
+ * </pre>
1501
+ * With the previous example's HTML, this would create this:
1502
+ * <pre>
1503
+ * &lt;div>
1504
+ * &lt;div id="mainText">Disclaimer: bla bla bla&lt;/div>
1505
+ * &lt;span class="disclaimer">WARNING&lt;/span>
1506
+ * &lt;/div>
1507
+ * </pre>
1508
+ *
1509
+ * @param text a string to add as text node of the list elements
1510
+ * @param factoryFunction a <code>function(listItem, listIndex)</code> that will be invoked for each list element to create the nodes:
1511
+ * <dl><dt>listItem</dt><dd>The list element that will receive the new children.</dd>
1512
+ * <dt>listIndex</dt><dd>The index of the list element that will receive the new children.</dd>
1513
+ * <dt class="returnValue">(callback return value)<dt><dd>The node(s) to be added to the list element.
1514
+ * Can be either a string for a text node, an HTML element or a list containing strings, lists, functions and/or DOM nodes.
1515
+ * If a function is returned or in the list, it will be invoked recursively with the same arguments.</dd></dl>
1516
+ * @param list a list containing text, functions, nodes or more list. Please note that if you have DOM nodes in this list
1517
+ * and attempt to add them to more than one element, the result is <var>undefined</var>. You should always use factories if your
1518
+ * Minified list contains more than one item.
1519
+ * @param node a DOM node to add <strong>only to the first element</strong> of the list.
1520
+ * @return the current list
1521
+ */
1522
+ 'addAfter': function (children) {
1523
+ return this.add(children, function(newNode, refNode, parent) { parent.insertBefore(newNode, refNode.nextSibling); });
1524
+ },
1525
+
1526
+ /*$
1527
+ * @id addfront
1528
+ * @group ELEMENT
1529
+ * @requires dollar add
1530
+ * @configurable default
1531
+ * @name .addFront()
1532
+ * @syntax addFront(text)
1533
+ * @syntax addFront(factoryFunction)
1534
+ * @syntax addFront(list)
1535
+ * @syntax addFront(node)
1536
+ * @module WEB
1537
+ * Adds the given node(s) as children to the list's HTML elements. Unlike ##add(), the new nodes will be the first children and not the last.
1538
+ * If a string has been given, it will be added as text node.
1539
+ * If you pass a function, it will be invoked for each list element to create node(s) with the arguments <code>function(parent, index)</code>.
1540
+ * It can return all values allowed by <var>addFront()</var>, including another function to be called.
1541
+ * If you pass a list or a function returns a list, all its elements will be added using the rules above.
1542
+ *
1543
+ * It is also possible to pass a DOM node, but it will be added <strong>only to the first element of the list</strong>, because DOM
1544
+ * does not allow adding it more than once.
1545
+ *
1546
+ * @example Using the following HTML:
1547
+ * <pre>
1548
+ * &lt;div id="comments">Here is some text.&lt;br/>&lt;/div>
1549
+ * </pre>
1550
+ * Add a text to the given 'comment' div:
1551
+ * <pre>
1552
+ * $('#comments').addFront('Some additional text. ');
1553
+ * </pre>
1554
+ * This results in:
1555
+ * <pre>
1556
+ * &lt;div id="comments">Some additional text. Here is some text.&lt;br/>&lt;/div>
1557
+ * </pre>
1558
+ *
1559
+ * @example Using the following HTML:
1560
+ * <pre>
1561
+ * &lt;ul id="myList">
1562
+ * &lt;li>First list entry&lt;/li>
1563
+ * &lt;li>Second list entry&lt;/li>
1564
+ * &lt;/ul>
1565
+ * </pre>
1566
+ * The following Javascript adds an element to the list:
1567
+ * <pre>
1568
+ * $('#myList').addFront(EE('li', 'My extra point'));
1569
+ * </pre>
1570
+ * This results in
1571
+ * <pre>
1572
+ * &lt;ul id="myList">
1573
+ * &lt;li>My extra point&lt;/li>
1574
+ * &lt;li>First list entry&lt;/li>
1575
+ * &lt;li>Second list entry&lt;/li>
1576
+ * &lt;/ul>
1577
+ * </pre>
1578
+ *
1579
+ * @example Use a list to add several elements at once:
1580
+ * <pre>
1581
+ * $('#comments').addFront([
1582
+ * EE('br'),
1583
+ * 'Some text',
1584
+ * EE('span', {'className': 'highlight'}, 'Some highlighted text')
1585
+ * ]);
1586
+ * </pre>
1587
+ *
1588
+ * @param text a string to add as text node of the list elements
1589
+ * @param factoryFunction a <code>function(listItem, listIndex)</code> that will be invoked for each list element to create the nodes:
1590
+ * <dl><dt>listItem</dt><dd>The list element that will receive the new children.</dd>
1591
+ * <dt>listIndex</dt><dd>The index of the list element that will receive the new children.</dd>
1592
+ * <dt class="returnValue">(callback return value)<dt><dd>The node(s) to be added to the list element.
1593
+ * Can be either a string for a text node, an HTML element or a list containing strings, lists, functions and/or DOM nodes.
1594
+ * If a function is returned or in the list, it will be invoked recursively with the same arguments.</dd></dl>
1595
+
1596
+ * @param list a list containing text, functions, nodes or nested lists containing those items. Please note that if you have DOM nodes in this list
1597
+ * and attempt to add them to more than one element, the result is undefined.
1598
+ * @param node a DOM node to add <strong>only to the first element</strong> of the list.
1599
+ * @return the current list
1600
+ */
1601
+ 'addFront': function (children) {
1602
+ return this.add(children, function(newNode, refNode) { refNode.insertBefore(newNode, refNode.firstChild); });
1603
+ },
1604
+
1605
+ /*$
1606
+ * @id replace
1607
+ * @group ELEMENT
1608
+ * @requires dollar add
1609
+ * @configurable default
1610
+ * @name .replace()
1611
+ * @syntax replace(text)
1612
+ * @syntax replace(factoryFunction)
1613
+ * @syntax replace(list)
1614
+ * @syntax replace(node)
1615
+ * @module WEB
1616
+ * Replaces the list items with the the given node(s) in the DOM tree.
1617
+ * If a string has been given, it will be set as text node.
1618
+ * If you pass a function, it will be invoked for each list element to create node(s) with the arguments <code>function(parent, index)</code>.
1619
+ * It can return all values allowed by <var>replace()</var>, including another function to be called.
1620
+ * If you pass a list or a function returns a list, all its elements will be set using the rules above.
1621
+ *
1622
+ * It is also possible to pass a DOM node, but it will replace <strong>only the first element of the list</strong>, because DOM
1623
+ * does not allow adding it more than once.
1624
+ *
1625
+ * @example Using the following HTML:
1626
+ * <pre>
1627
+ * &lt;div id="comments">
1628
+ * &lt;div id="commentOne">My old comment.&lt;/div>
1629
+ * &lt;/div>
1630
+ * </pre>
1631
+ * This replaces the div 'commentOne':
1632
+ * <pre>
1633
+ * $('#commentOne').replace('Some new comment.');
1634
+ * </pre>
1635
+ * The resulting HTML is:
1636
+ * <pre>
1637
+ * &lt;div id="comments">
1638
+ * Some new comment.
1639
+ * &lt;/div>
1640
+ * </pre>
1641
+ * Please note that not only the text has changed, but the whole &lt;div> has been replaced. If you only want to replace the element's text content
1642
+ * you should use ##fill() instead of <var>replace()</var>.
1643
+ *
1644
+ * @example Using the following HTML:
1645
+ * <pre>
1646
+ * &lt;ul id="myList">
1647
+ * &lt;li>First list entry&lt;/li>
1648
+ * &lt;li>Second list entry&lt;/li>
1649
+ * &lt;/ul>
1650
+ * </pre>
1651
+ * The following example will replace <strong>only the first &lt;li> element</strong>:
1652
+ * <pre>
1653
+ * $('#myList li').sub(0, 1).replace(EE('li', 'My extra point'));
1654
+ * </pre>
1655
+ * This results in
1656
+ * <pre>
1657
+ * &lt;ul id="myList">
1658
+ * &lt;li>My extra point&lt;/li>
1659
+ * &lt;li>Second list entry&lt;/li>
1660
+ * &lt;/ul>
1661
+ * </pre>
1662
+ *
1663
+ *
1664
+ * @param text a text for the text nodes that replace the list elements
1665
+ * @param factoryFunction a <code>function(listItem, listIndex)</code> that will be invoked for each list element to determine its content:
1666
+ * <dl><dt>listItem</dt><dd>The list element that will receive the new children.</dd>
1667
+ * <dt>listIndex</dt><dd>The index of the list element that will receive the new children.</dd>
1668
+ * <dt class="returnValue">(callback return value)<dt><dd>The node(s) to be added to the list element.
1669
+ * Can be either a string for a text node, an HTML element or a list containing strings, lists, functions and/or DOM nodes.
1670
+ * If a function is returned or in the list, it will be invoked recursively with the same arguments.</dd></dl>
1671
+ * @param node content to replace <strong>only to the first element</strong> of the list with. The content can be a string for a text node,
1672
+ * an HTML node or a list containing strings and/or HTML node.
1673
+ * @return the current list
1674
+ */
1675
+ 'replace': function (children) {
1676
+ return this.add(children, function(newNode, refNode, parent) { parent.replaceChild(newNode, refNode); });
1677
+ },
1678
+
1679
+ /*$
1680
+ * @id clone
1681
+ * @group ELEMENT
1682
+ * @requires dollar ee
1683
+ * @configurable default
1684
+ * @name .clone()
1685
+ * @syntax clone()
1686
+ * @syntax clone(onCreate)
1687
+ * @module WEB
1688
+ * Creates a ##list#Minified list## of strings and Element Factories that return clones of the list's HTML elements. An Element Factory is a function
1689
+ * that creates a Minified list of fresh DOM nodes. You can pass the list to ##add(), ##fill() or similar functions to re-create the cloned nodes.
1690
+ *
1691
+ * <var>clone()</var> is very limited in what it will clone. Only elements, their attributes, text nodes and CDATA will be cloned.
1692
+ * Modifications of the elements, such as event handlers, will not be cloned.
1693
+ *
1694
+ * Please note that id attributes will be automatically skipped by the Element Factory. This allows you to address the element to clone by id
1695
+ * without having to worry about duplicate ids in the result.
1696
+ *
1697
+ * @example Using the following HTML:
1698
+ * <pre>
1699
+ * &lt;div id="comments">
1700
+ * &lt;div id="comment1">My comment.&lt;/div>
1701
+ * &lt;/div>
1702
+ * </pre>
1703
+ * Creating a clone factory:
1704
+ * <pre>
1705
+ * var myCloneFactory = $('#comment1').clone();
1706
+ * </pre>
1707
+ * Creating a clone and adding it below the existing one:
1708
+ * <pre>
1709
+ * $('#comments').add(myCloneFactory);
1710
+ * </pre>
1711
+ *
1712
+ * @example Creating an event handler for a clone:
1713
+ * <pre>
1714
+ * var buttonCloner = $('#myButton').clone(function(newButton) {
1715
+ * newButton.on('click', function() { alert('Cloned button clicked'); });
1716
+ * });
1717
+ * $('#buttonContainer').add(buttonCloner);
1718
+ * </pre>
1719
+ *
1720
+ * @param onCreate optional A <code>function(elementList)</code> that will be called for each top-level element created by the Element
1721
+ * Factory:
1722
+ * <dl><dt>elementList</dt><dd>The newly created element wrapped in a Minified list. </dd></dl>
1723
+ * The function's return value will be ignored.
1724
+ * The callback allows you, for example, to add event handlers to the element using ##on().
1725
+ * Please note that the callback will be not be called for cloned text nodes. If you clone
1726
+ * more than one element, <var>onCreate</var> will be invoked for each element.
1727
+ * @return the list of Element Factory functions and strings to create clones
1728
+ */
1729
+ 'clone': function (onCreate) {
1730
+ return new M(collect(this, function(e) {
1731
+ var nodeType = isNode(e);
1732
+ if (nodeType == 1) {
1733
+ var attrs = {
1734
+ // @condblock ie8compatibility
1735
+ '$': e['className'] || null,
1736
+ '$$': IS_PRE_IE9 ? e['style']['cssText'] : e.getAttribute('style')
1737
+ // @condend
1738
+ };
1739
+ each(e['attributes'], function(a) {
1740
+ var attrName = a['name'];
1741
+ if (attrName != 'id'
1742
+ // @condblock ie8compatibility
1743
+ && attrName != 'style'
1744
+ && attrName != 'class'
1745
+ && e.getAttribute(attrName) // getAttribute for IE8
1746
+ // @condend
1747
+ ) {
1748
+ attrs['@'+attrName] = a['value'];
1749
+ }
1750
+ });
1751
+ return EE(e['tagName'], attrs, $(e['childNodes'])['clone'](), onCreate);
1752
+ }
1753
+ else if (nodeType < 5) // 2 is impossible (attribute), so only 3 (text) and 4 (cdata)..
1754
+ return e['data'];
1755
+ else
1756
+ return null;
1757
+ }));
1758
+ },
1759
+
1760
+
1761
+
1762
+
1763
+ /*$
1764
+ * @id animate
1765
+ * @group ANIMATION
1766
+ * @requires loop dollar set get
1767
+ * @configurable default
1768
+ * @name .animate()
1769
+ * @syntax animate(properties)
1770
+ * @syntax animate(properties, durationMs)
1771
+ * @syntax animate(properties, durationMs, linearity)
1772
+ * @syntax animate(properties, durationMs, interpolationFunc)
1773
+ * @syntax animate(properties, durationMs, linearity, state)
1774
+ * @syntax animate(properties, durationMs, interpolationFunc, state)
1775
+ * @module WEB
1776
+ * Animates the items of the list by modifying their properties, CSS styles and attributes. <var>animate()</var> can work with numbers, strings that contain exactly one
1777
+ * number, and with colors in the CSS notations 'rgb(r,g,b)', '#rrggbb' or '#rgb'.
1778
+ *
1779
+ * When you invoke the function, it will first read all old values from the object and extract their numbers and colors. These start values will be compared to
1780
+ * the destination values that have been specified in the given properties. Then <var>animate()</var> will create a background task using ##$.loop() that updates the
1781
+ * specified properties in frequent intervals so that they transition to their destination values.
1782
+ *
1783
+ * The start values will be obtained using ##get(). It is recommended to set the start values using ##set() before you start the animation, even if this is not
1784
+ * always required.
1785
+ *
1786
+ * You can define the kind of transition using the <var>linearity</var> parameter. If you omit it or pass 0, animate's default algorithm will cause a smooth transition
1787
+ * from the start value to the end value. If you pass 1, the transition will be linear, with a sudden start and end of the animation. Any value between 0 and 1
1788
+ * is also allowed and will give you a transition that is 'somewhat smooth'.
1789
+ *
1790
+ * Instead of the <var>linearity</var> function you can also provide your own interpolation <code>function(startValue, endValue, t)</code> which will be
1791
+ * called every time an interpolated value is required. <var>startValue</var> and <var>endValue</var> define the start and end values. <var>t</var>
1792
+ * is a value between 0 and 1 that specifies the state of the transition. The function should return <var>startValue</var> for 0 and
1793
+ * <var>endValue</var> for 1. For values between 0 and 1, the function should return a transitional value.
1794
+ *
1795
+ * If the start value of a property is a string containing a number, <var>animate()</var> will always ignore all the surrounding text and use the destination value as a template
1796
+ * for the value to write. This can cause problems if you mix units in CSS. For example, if the start value is '10%' and you specify an end value of '20px', animate
1797
+ * will do an animation from '10px' to '20px'. It is not able to convert units.
1798
+ *
1799
+ * <var>animate()</var> does not only support strings with units, but any string containing exactly one number. This allows you, among other things, with IE-specific CSS properties.
1800
+ * For example, you can transition from a start value 'alpha(opacity = 0)' to 'alpha(opacity = 100)'.
1801
+ *
1802
+ * When you animate colors, <var>animate()</var> is able to convert between the three notations rgb(r,g,b), #rrggbb or #rgb. You can use them interchangeably, but you can not
1803
+ * use color names such as 'red'.
1804
+ *
1805
+ * You can prefix any number, including numbers with units, with "-=" or "+=" in order to specify a value relative to the starting value. The new value will be added
1806
+ * to or substracted from the start value to determine the end value.
1807
+ *
1808
+ * To allow more complex animation, <var>animate()</var> returns a ##promise#Promise## that is fulfulled when the animation has finished.
1809
+ *
1810
+ * @example Move an element.
1811
+ * <pre>
1812
+ * $('#myMovingDiv').set({$left: '0px', $top: '0px'}) // start values
1813
+ * .animate({$left: '50px', $top: '100px'}, 1000); // animation
1814
+ * </pre>
1815
+ *
1816
+ * @example Using relative values for animation:
1817
+ * <pre>
1818
+ * $('#myMovingDiv').set({$left: '100px', $top: '100px'}) // start values
1819
+ * .animate({$left: '-=50px', $top: '+=100px'}, 1000); // animation
1820
+ * </pre>
1821
+ *
1822
+ * @example Change the color of an element:
1823
+ * <pre>
1824
+ * $('#myBlushingDiv').set({$backgroundColor: '#000000'})
1825
+ * .animate({$backgroundColor: '#ff0000'}, 1000);
1826
+ * </pre>
1827
+ *
1828
+ * @example Fade-out effect:
1829
+ * <pre>
1830
+ * $('#myFadingDiv').animate({$$fade: 0}, 1000);
1831
+ * </pre>
1832
+ *
1833
+ * @example Slide-in effect:
1834
+ * <pre>
1835
+ * $('#myInvisibleDiv').animate({$$slide: 1}, 1000);
1836
+ * </pre>
1837
+ *
1838
+ * @example Chained animation using ##promise#Promise## callbacks. The element is first moved to the position 200/0, then to 200/200
1839
+ * and finally moves to 100/100.
1840
+ * <pre>
1841
+ * var div = $('#myMovingDiv').set({$left: '0px', $top: '0px'});
1842
+ * div.animate({$left: '200px', $top: '0px'}, 600, 0)
1843
+ * .then(function() {
1844
+ * return div.animate({$left: '200px', $top: '200px'}, 800, 0);
1845
+ * }).then(function() {
1846
+ * return div.animate({$left: '100px', $top: '100px'}, 400);
1847
+ * });
1848
+ * });
1849
+ * </pre>
1850
+ * </pre>
1851
+ *
1852
+ *
1853
+ * @param properties a property map describing the end values of the corresponding properties. The names can use the
1854
+ * set() syntax ('@' prefix for attributes, '$' for styles, '$$fade' for fading and '$$slide' for slide effects).
1855
+ * Values must be either numbers, numbers with units (e.g. "2 px") or colors ('rgb(r,g,b)', '#rrggbb' or '#rgb').
1856
+ * Number values, including those with units, can be prefixed with "+=" or "-=", meaning that the value is relative
1857
+ * to the original value and should be added or subtracted.
1858
+ * @param durationMs optional the duration of the animation in milliseconds. Default: 500ms.
1859
+ * @param linearity optional defines whether the animation should be linear (1), very smooth (0) or something in between. Default: 0.
1860
+ * @param interpolationFunc optional an interpolation <code>function(startValue, endValue, t)</code> which will be
1861
+ * called every time an interpolated value is required:
1862
+ * <dl>
1863
+ * <dt>startValue</dt><dd>The start value of the transition.</dd>
1864
+ * <dt>endValue</dt><dd>The end value of the transition.</dd>
1865
+ * <dt>t</dt><dd>A value between 0 and 1 that specifies the state of the transition.</dd>
1866
+ * <dt class="returnValue">(callback return value)</dt><dd>The value at the time <var>t</var>.</dd>
1867
+ * </dl>
1868
+ * @param state optional if set, the animation controller will write information about its state in this object. When <var>animate()</var> returns,
1869
+ * there will be a <var>stop()</var> function in the property <var>state.stop</var> that can be used to abort the animation.
1870
+ * The property <var>state.time</var> will be continously updated while the animation is running
1871
+ * and contains the number of milliseconds that have passed from the start, allowing you to track the progress of the animation.
1872
+ * If the animation finished, controller writes null into <var>state.time</var>. <var>state.stop</var> will not be
1873
+ * modified and can still be safely invoked even when the animation ended.
1874
+ * @return a ##promise#Promise## object to monitor the animation's progress.
1875
+ * It is fulfilled when the animation ended, and rejected if the animation had been stopped.
1876
+ * The fulfillment handler will be called as <code>function(list)</code>:
1877
+ * <dl><dt>list</dt><dd>A reference to the animated list.</dd></dl>
1878
+ * The rejection handler is called as <code>function()</code> without arguments.
1879
+ */
1880
+ 'animate': function (properties, durationMs, linearity, state) {
1881
+ // @cond debug if (!properties || typeof properties == 'string') error('First parameter must be a map of properties (e.g. "{top: 0, left: 0}") ');
1882
+ // @cond debug if (linearity && !isFunction(linearity) && (linearity < 0 || linearity > 1)) error('Third parameter must be at least 0 and not larger than 1.');
1883
+ // @cond debug var colorRegexp = /^(rgb\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*\)|#\w{3}|#\w{6})\s*$/i;
1884
+ var self = this;
1885
+ var initState = []; // for each item contains a map {s:{}, e:{}, o} s/e are property name -> startValue of start/end. The item is in o.
1886
+ var numRegExp = /-?[\d.]+/;
1887
+ var loopStop;
1888
+ var prom = promise();
1889
+ var interpolate = isFunction(linearity) ? linearity : function(startValue, endValue, t) {
1890
+ return startValue + t * (endValue - startValue) * (linearity + (1-linearity) * t * (3 - 2*t));
1891
+ };
1892
+ state = state || {};
1893
+ state['time'] = 0;
1894
+ state['stop'] = function() { loopStop(); prom(false); };
1895
+ durationMs = durationMs || 500;
1896
+ linearity = linearity || 0;
1897
+
1898
+
1899
+ // find start values
1900
+ each(self, function(li) {
1901
+ var p = {o:$(li), e:{}};
1902
+ eachObj(p.s = p.o.get(properties), function(name, start) {
1903
+ var dest = properties[name];
1904
+ if (name == '$$slide')
1905
+ dest = dest*getNaturalHeight(p.o) + 'px';
1906
+ p.e[name] = /^[+-]=/.test(dest) ?
1907
+ replace(dest.substr(2), numRegExp, extractNumber(start) + extractNumber(replace(dest, /\+?=/)))
1908
+ : dest;
1909
+ });
1910
+ initState.push(p);
1911
+ });
1912
+
1913
+ // start animation
1914
+ loopStop = $.loop(function(timePassedMs) {
1915
+ function getColorComponent(colorCode, index) {
1916
+ return (/^#/.test(colorCode)) ?
1917
+ parseInt(colorCode.length > 6 ? colorCode.substr(1+index*2, 2) : ((colorCode=colorCode.charAt(1+index))+colorCode), 16)
1918
+ :
1919
+ parseInt(replace(colorCode, /[^\d,]+/g).split(',')[index]);
1920
+ }
1921
+
1922
+ state['time'] = timePassedMs;
1923
+ if (timePassedMs >= durationMs || timePassedMs < 0) {
1924
+ each(initState, function(isi) { // set destination values
1925
+ isi.o.set(isi.e);
1926
+ });
1927
+ loopStop();
1928
+ state['time'] = null;
1929
+ prom(true, [self]);
1930
+ }
1931
+ else
1932
+ each(initState, function(isi) {
1933
+ eachObj(isi.s, function(name, start) {
1934
+ var newValue = 'rgb(', end=isi.e[name];
1935
+ var t = timePassedMs/durationMs;
1936
+ if (/^#|rgb\(/.test(end)) { // color in format '#rgb' or '#rrggbb' or 'rgb(r,g,b)'?
1937
+ for (var i = 0; i < 3; i++)
1938
+ newValue += Math.round(interpolate(getColorComponent(start, i), getColorComponent(end, i), t)) + (i < 2 ? ',' : ')');
1939
+ }
1940
+ else
1941
+ newValue = replace(end, numRegExp, toString(interpolate(extractNumber(start), extractNumber(end), t)));
1942
+ isi.o.set(name, newValue);
1943
+ });
1944
+ });
1945
+ });
1946
+ return prom;
1947
+ },
1948
+
1949
+
1950
+ /*$
1951
+ * @id toggle
1952
+ * @group ANIMATION
1953
+ * @requires animate set
1954
+ * @configurable default
1955
+ * @name .toggle()
1956
+ * @syntax toggle(cssClasses)
1957
+ * @syntax toggle(state1, state2)
1958
+ * @syntax toggle(state1, state2, durationMs)
1959
+ * @syntax toggle(state1, state2, durationMs, linearity)
1960
+ * @syntax toggle(state1, state2, durationMs, interpolationFunction)
1961
+ * @module WEB
1962
+ *
1963
+ * Creates a function that switches between the two given states for the list. The states use the ##set() property syntax. You can also
1964
+ * just pass a string of CSS classes, as you do with <var>set()</var>.
1965
+ *
1966
+ * If no duration is given, the returned function changes the state immediately using ##set(). If a duration has been passed, the returned function
1967
+ * uses ##animate() to smoothly transition the state. If the returned function is invoked while an animation is running, it interrupts the
1968
+ * animation and returns to the other state.
1969
+ *
1970
+ * @example Creates a toggle function that changes the background color of the page.
1971
+ * <pre>
1972
+ * var light = $('body').set({$backgroundColor: #000}, {$backgroundColor: #fff});
1973
+ * light(); // toggles state to second state
1974
+ * light(false); // sets first state (background color to #000).
1975
+ * light(true); // sets second state (background color to #fff).
1976
+ * light(); // toggles state to first state
1977
+ * </pre>
1978
+ *
1979
+ * @example Takes the previous function, but adds it as an onclick event handler that toggles the color.
1980
+ * <pre>
1981
+ * var light = $('body').toggle({$backgroundColor: #000}, {$backgroundColor: #fff});
1982
+ * $('#mySwitch').on('click', light);
1983
+ * </pre>
1984
+ *
1985
+ * @example Using an animated transition by passing a duration:
1986
+ * <pre>
1987
+ * var dimmer = $('body').toggle({$backgroundColor: #000}, {$backgroundColor: #fff}, 500);
1988
+ * $('#mySwitch').on('click', dimmer);
1989
+ * </pre>
1990
+ *
1991
+ * @example Toggling CSS classes using the full syntax:
1992
+ * <pre>
1993
+ * var t = $('#myElement').toggle({$: '-myClass1 -myClass2'}, {$: '+myClass1 +myClass2'});
1994
+ * $('#myController').on('click', t);
1995
+ * </pre>
1996
+ *
1997
+ * @example There is a shortcut for toggling CSS classes. Just list them space-separated in a string:
1998
+ * <pre>
1999
+ * var t = $('#myElement').toggle('myClass1 myClass2');
2000
+ * </pre>
2001
+ *
2002
+ * @param cssClasses a string containing space-separated CSS class names to toggle. Classes are disabled in the first state
2003
+ * and enabled in the second.
2004
+ * @param state1 a property map in ##set() syntax describing the initial state of the properties. The properties will automatically be set when the
2005
+ * <var>toggle()</var> function is created. The properties will be set for all elements of the list.
2006
+ * @param state2 a property map describing the second state of the properties. Uses ##set() syntax, like the other state.
2007
+ * @param durationMs optional if set, the duration of the animation in milliseconds. By default, there is no animation and the
2008
+ * properties will be changed immediately.
2009
+ * @param linearity optional defines whether the animation should be linear (1), very smooth (0) or something in between. Default: 0. Ignored if durationMs is 0.
2010
+ * @param interpolationFunc optional an interpolation <code>function(startValue, endValue, t)</code> for the animation which will be called every
2011
+ * time an interpolated value is required:
2012
+ * <dl>
2013
+ * <dt>startValue</dt><dd>The start value of the transition.</dd>
2014
+ * <dt>endValue</dt><dd>The end value of the transition.</dd>
2015
+ * <dt>t</dt><dd>A value between 0 and 1 that specifies the state of the transition.</dd>
2016
+ * <dt class="returnValue">(callback return value)</dt><dd>The value at the time <var>t</var>.</dd>
2017
+ * </dl>
2018
+ * @return a toggle function <code>function(newState)</code> that will toggle between the two states, or set a specific state.
2019
+ * <dl>
2020
+ * <dt>newState (optional)</dt><dd>If a boolean <var>true</var or <var>false</var> is given,
2021
+ * the toggle will set the first or second state, respectively. If called with any other value, or without a value,
2022
+ * the function toggles to the other state.</dd></dl>
2023
+ */
2024
+ 'toggle': function(state1, state2, durationMs, linearity) {
2025
+ var self = this;
2026
+ var animState = {};
2027
+ var state = false, regexg = /\b(?=\w)/g;
2028
+
2029
+ return !state2 ?
2030
+ self['toggle'](replace(state1, regexg, '-'), replace(state1, regexg, '+')) :
2031
+ self['set'](state1) &&
2032
+ function(newState) {
2033
+ if (newState === state)
2034
+ return;
2035
+ state = newState===true||newState===false ? newState : !state;
2036
+
2037
+ if (durationMs)
2038
+ self['animate'](state ? state2 : state1, animState['stop'] ? (animState['stop']() || animState['time']) : durationMs, linearity, animState);
2039
+ else
2040
+ self['set'](state ? state2 : state1);
2041
+ };
2042
+ },
2043
+
2044
+
2045
+ /*$
2046
+ * @id on
2047
+ * @group EVENTS
2048
+ * @requires dollar
2049
+ * @configurable default
2050
+ * @name .on()
2051
+ * @syntax on(names, eventHandler)
2052
+ * @syntax on(names, customFunc, args)
2053
+ * @syntax on(names, customFunc, fThis, args)
2054
+ * @module WEB
2055
+ * Registers the function as event handler for all items in the list.
2056
+ *
2057
+ * By default, Minified cancels event propagation and the element's default behaviour for all elements that have an event handler.
2058
+ * You can override this by prefixing the event name with a '|' or by returning a 'true' value in the handler, which will reinstate
2059
+ * the original JavaScript behaviour.
2060
+ *
2061
+ * Handlers are called with the original event object as first argument, the index of the source element in the
2062
+ * list as second argument and 'this' set to the source element of the event (e.g. the button that has been clicked).
2063
+ *
2064
+ * Instead of the event objects, you can also pass an array of arguments and a new value for 'this' to the callback.
2065
+ * When you pass arguments, the handler's return value is always ignored and the event with unnamed prefixes
2066
+ * will always be cancelled.
2067
+ *
2068
+ * Event handlers can be unregistered using #off#$.off().
2069
+ *
2070
+ * @example Adds a handler to all divs which paints the div background color to red when clicked.
2071
+ * <pre>
2072
+ * $('div').on('click', function() {
2073
+ * this.style.backgroundColor = 'red'; // 'this' contains the element that caused the event
2074
+ * });
2075
+ * </pre>
2076
+ *
2077
+ * @example Registers a handler to call a method setStatus('running') using an inline function:
2078
+ * <pre>
2079
+ * $('#myButton').on('click', function() {
2080
+ * myObject.setStatus('running');
2081
+ * });
2082
+ * </pre>
2083
+ * The previous example can bere written like this, using <var>on()</var>'s <var>args</var> and <var>fThis</var> parameters:
2084
+ * <pre>
2085
+ * $('#myButton').on('click', myObject.setStatus, myObject, ['running']);
2086
+ * </pre>
2087
+ *
2088
+ * @example Adds two handlers on an input field. The event names are prefixed with '|' and thus keep their original behaviour:
2089
+ * <pre>
2090
+ * $('#myInput').on('|keypress |keydown', function() {
2091
+ * // do something
2092
+ * });
2093
+ * </pre>
2094
+ *
2095
+ * @param names the space-separated names of the events to register for, e.g. 'click'. Case-sensitive. The 'on' prefix in front of
2096
+ * the name must not used. You can register the handler for more than one event by specifying several
2097
+ * space-separated event names. If the name is prefixed
2098
+ * with '|' (pipe), the handler's return value is ignored and the event will be passed through the event's default actions will
2099
+ * be executed by the browser.
2100
+ * @param eventHandler the callback <code>function(event, index)</code> to invoke when the event has been triggered:
2101
+ * <dl>
2102
+ * <dt>event</dt><dd>The original DOM event object.</dd>
2103
+ * <dt>index</dt><dd>The index of the target object in the ##list#Minified list## .</dd>
2104
+ * <dt class="returnValue">(callback return value)</dt><dd>Unless the handler returns <var>true</var>
2105
+ * or the event name is prefixed by '|', all further processing of the event will be
2106
+ * stopped and event bubbling will be disabled.</dd>
2107
+ * </dl>
2108
+ * 'this' is set to the element that caused the event.
2109
+ * @param customFunc a function to be called instead of a regular event handler with the arguments given in <var>args</var>
2110
+ * and optionally the 'this' context given using <var>fThis</var>.
2111
+ * @param fThis optional an value for 'this' in the custom callback, as alternative to the event target
2112
+ * @param args optional an array of arguments to pass to the custom callback function instead of the event objects.
2113
+ * If you pass custom arguments, the return value of the handler will always be ignored.
2114
+ * @return the list
2115
+ */
2116
+ 'on': function (eventName, handler, fThisOrArgs, args) {
2117
+ // @cond debug if (!(name && handler)) error("Both parameters to on() are required!");
2118
+ // @cond debug if (/^on/i.test(name)) error("The event name looks invalid. Don't use an 'on' prefix (e.g. use 'click', not 'onclick'");
2119
+ return each(this, function(el, index) {
2120
+ each(eventName.split(/\s/), function(namePrefixed) {
2121
+ var name = replace(namePrefixed, /\|/);
2122
+ var h = function(event) {
2123
+ var e = event || _window.event;
2124
+ // @cond debug try {
2125
+ if ((!handler.apply(args ? fThisOrArgs : e.target, args || fThisOrArgs || [e, index]) || args) && namePrefixed==name) {
2126
+ // @condblock ie8compatibility
2127
+ if (e.stopPropagation) {// W3C DOM3 event cancelling available?
2128
+ // @condend
2129
+ e.preventDefault();
2130
+ e.stopPropagation();
2131
+ // @condblock ie8compatibility
2132
+ }
2133
+ e.returnValue = false; // cancel for IE
2134
+ e.cancelBubble = true; // cancel bubble for IE
2135
+ // @condend
2136
+ }
2137
+ // @cond debug } catch (ex) { error("Error in event handler \""+name+"\": "+ex); }
2138
+ };
2139
+ (handler['M'] = handler['M'] || []).push({'e':el, 'h':h, 'n': name});
2140
+ // @condblock ie8compatibility
2141
+ if (el.addEventListener)
2142
+ // @condend
2143
+ el.addEventListener(name, h, true); // W3C DOM
2144
+ // @condblock ie8compatibility
2145
+ else
2146
+ el.attachEvent('on'+name, h); // IE < 9 version
2147
+ // @condend
2148
+ });
2149
+ });
2150
+ }
2151
+
2152
+ /*$
2153
+ * @stop
2154
+ */
2155
+ // @cond !on dummy:null
2156
+ }, function(n, v) {M.prototype[n]=v;});
2157
+
2158
+
2159
+ //// MINI FUNCTIONS ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2160
+
2161
+ eachObj({
2162
+ /*$
2163
+ * @id request
2164
+ * @group REQUEST
2165
+ * @requires
2166
+ * @configurable default
2167
+ * @name $.request()
2168
+ * @syntax $.request(method, url)
2169
+ * @syntax $.request(method, url, data)
2170
+ * @syntax $.request(method, url, data, onSuccess)
2171
+ * @syntax $.request(method, url, data, onSuccess, onFailure)
2172
+ * @syntax $.request(method, url, data, onSuccess, onFailure, headers)
2173
+ * @syntax $.request(method, url, data, onSuccess, onFailure, headers, username, password)
2174
+ * @module WEB
2175
+ * Initiates a HTTP request to the given URL, using XMLHttpRequest. It returns a ##promise#Promise## object that allows you to obtain the result.
2176
+ *
2177
+ * @example Invokes a REST web service and parse the resulting document using JSON:
2178
+ * <pre>
2179
+ * $.request('get', 'http://service.example.com/weather', {zipcode: 90210})
2180
+ * .then(function(txt) {
2181
+ * var json = $.parseJSON(txt);
2182
+ * $('#weatherResult').fill('Today's forecast is is: ' + json.today.forecast);
2183
+ * })
2184
+ * .error(function(status, statusText, responseText) {
2185
+ * $('#weatherResult').fill('The weather service was not available.');
2186
+ * });
2187
+ * </pre>
2188
+ *
2189
+ * @example Sending a JSON object to a REST web service:
2190
+ * <pre>
2191
+ * var myRequest = { // create a request object that can be serialized via JSON
2192
+ * request: 'register',
2193
+ * entries: [
2194
+ * {name: 'Joe',
2195
+ * job: 'Plumber'
2196
+ * }]};
2197
+ *
2198
+ * function failureHandler() {
2199
+ * $('#registrationResult').fill('Registration failed');
2200
+ * }
2201
+ *
2202
+ * $.request('post', 'http://service.example.com/directory', $.toJSON(myRequest))
2203
+ * .then(function(txt) {
2204
+ * if (txt == 'OK')
2205
+ * $('#registrationResult').fill('Registration succeeded');
2206
+ * else
2207
+ * failureHandler();
2208
+ * })
2209
+ * .error(failureHandler);
2210
+ * </pre>
2211
+ *
2212
+ *
2213
+ * @param method the HTTP method, e.g. 'get', 'post' or 'head' (rule of thumb: use 'post' for requests that change data
2214
+ * on the server, and 'get' to request data). Not case sensitive.
2215
+ * @param url the server URL to request. May be a relative URL (relative to the document) or an absolute URL. Note that unless you do something
2216
+ * fancy on the server (keyword to google: Access-Control-Allow-Origin), you can only call URLs on the server your script originates from.
2217
+ * @param data optional data to send in the request, either as POST body or as URL parameters. It can be either an object as map of
2218
+ * parameters (for all HTTP methods), a string (for all HTTP methods) or a DOM document ('post' only). If the method is
2219
+ * 'post', it will be sent as body, otherwise parameters are appended to the URL. In order to send several parameters with the
2220
+ * same name, use an array of values in the map. Use null as value for a parameter without value.
2221
+ * @param headers optional a map of HTTP headers to add to the request. Note that you should use the proper capitalization for the
2222
+ * header 'Content-Type', if you set it, because otherwise it may be overwritten.
2223
+ * @param username optional username to be used for HTTP authentication, together with the password parameter
2224
+ * @param password optional password for HTTP authentication
2225
+ * @return a ##promise#Promise## containing the request's status. If the request has successfully completed with HTTP status 200,
2226
+ * the success handler will be called as <code>function(text, xml)</code>:
2227
+ * <dl><dt>text</dt><dd>The response sent by the server as text.</dd>
2228
+ * <dt>xml</dt><dd>If the response was a XML document, the DOM <var>Document</var>. Otherwise null.</a>.</dd></dl>
2229
+ * The failure handler will be called as <code>function(statusCode, statusText, text)</code>:
2230
+ * <dl><dt>statusCode</dt><dd>The HTTP status (never 200; 0 if no HTTP request took place).</dd>
2231
+ * <dt>statusText</dt><dd>The HTTP status text (or null, if the browser threw an exception).</dd>
2232
+ * <dt>text</dt><dd>the response's body text, if there was any, or the exception as string if the browser threw one.</a>.</dd></dl>
2233
+ */
2234
+ 'request': function (method, url, data, headers, username, password) {
2235
+ // @cond debug if (!method) error("request() requires a HTTP method as first argument.");
2236
+ // @cond debug if (!url) error("request() requires a url as second argument.");
2237
+ // @cond debug if (onSuccess && typeof onSuccess != 'function') error("request()'s fourth argument is optional, but if it is set, it must be a function.");
2238
+ // @cond debug if (onFailure && typeof onFailure != 'function') error("request()'s fifth argument is optional, but if it is set, it must be a function.");
2239
+ // @cond debug if (username && !password) error("If the user name is set (7th argument), you must also provide a password as 8th argument."); method = method.toUpperCase();
2240
+ /** @const */ var ContentType = 'Content-Type';
2241
+ var xhr, body = data, callbackCalled = 0, prom = promise();
2242
+ try {
2243
+ //@condblock ie6compatibility
2244
+ xhr = _window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Msxml2.XMLHTTP.3.0");
2245
+ //@condend
2246
+ // @cond !ie6compatibility xhr = new XMLHttpRequest();
2247
+ if (data != null) {
2248
+ headers = headers || {};
2249
+ if (!isString(data) && !isNode(data)) { // if data is parameter map...
2250
+ body = collectObj(data, function processParam(paramName, paramValue) {
2251
+ if (isList(paramValue))
2252
+ return collect(paramValue, function(v) {return processParam(paramName, v);});
2253
+ else
2254
+ return encodeURIComponent(paramName) + ((paramValue != null) ? '=' + encodeURIComponent(paramValue) : '');
2255
+ }).join('&');
2256
+ }
2257
+
2258
+ if (!/post/i.test(method)) {
2259
+ url += '?' + body;
2260
+ body = null;
2261
+ }
2262
+ else if (!isNode(data) && !isString(data) && !headers[ContentType])
2263
+ headers[ContentType] = 'application/x-www-form-urlencoded';
2264
+ }
2265
+
2266
+ xhr.open(method, url, true, username, password);
2267
+ eachObj(headers, function(hdrName, hdrValue) {
2268
+ xhr.setRequestHeader(hdrName, hdrValue);
2269
+ });
2270
+
2271
+ xhr.onreadystatechange = function() {
2272
+ if (xhr.readyState == 4 && !callbackCalled++) {
2273
+ if (xhr.status == 200) {
2274
+ prom(true, [xhr.responseText, xhr.responseXML]);
2275
+ }
2276
+ else
2277
+ prom(false, [xhr.status, xhr.statusText, xhr.responseText]);
2278
+ }
2279
+ };
2280
+
2281
+ xhr.send(body);
2282
+ }
2283
+ catch (e) {
2284
+ if (!callbackCalled)
2285
+ prom(false, [0, null, toString(e)]);
2286
+ }
2287
+ return prom;
2288
+ },
2289
+
2290
+
2291
+ /*
2292
+ * JSON Module. Uses browser built-ins or json.org implementation if available. Otherwise its own implementation,
2293
+ * originally based on public domain implementation http://www.JSON.org/json2.js / http://www.JSON.org/js.html.
2294
+ * Extremely simplified code, made variables local, removed all side-effects (especially new properties for String, Date and Number).
2295
+ */
2296
+
2297
+
2298
+ /*$
2299
+ * @id tojson
2300
+ * @group JSON
2301
+ * @requires ucode
2302
+ * @configurable default
2303
+ * @name $.toJSON()
2304
+ * @syntax $.toJSON(value)
2305
+ * @module WEB
2306
+ * Converts the given value into a JSON string. The value may be a map-like object, an array or list, a string, number, boolean or null.
2307
+ * If you build Minified without Internet Explorer compatibility, this is just an alias for <var>JSON.stringify</var>.
2308
+ *
2309
+ * The following types are supported by the built-in implementation:
2310
+ * <ul>
2311
+ * <li>Objects (direct properties will be serialized)</li>
2312
+ * <li>Arrays/Lists (with <var>length</var> property)</li>
2313
+ * <li>Strings</li>
2314
+ * <li>Numbers</li>
2315
+ * <li>Boolean</li>
2316
+ * <li>null</li>
2317
+ * </ul>
2318
+ * Any other types in your JSON tree, especially Dates, should be converted into Strings by you.
2319
+ *
2320
+ * @example Converts an object into a JSON object:
2321
+ * <pre>
2322
+ * var myObj = {name: 'Fruits', roles: ['apple', 'banana', 'orange']};
2323
+ * var jsonString = $.toJSON(myObj);
2324
+ * </pre>
2325
+ *
2326
+ * @param value the value (map-like object, array/list, string, number, boolean or null)
2327
+ * @return the JSON string
2328
+ */
2329
+ // @condblock ie7compatibility
2330
+ 'toJSON': function toJSON(value) {
2331
+ if (value == null)
2332
+ return ""+value; //result: "null"; toString(value) is not possible, because it returns an empty string for null
2333
+ if (isString(value = value.valueOf()))
2334
+ return '"' + replace(value, /[\\\"\x00-\x1f\x22\x5c]/g, ucode) + '"' ;
2335
+ if (isList(value))
2336
+ return '[' + collect(value, toJSON).join() + ']';
2337
+ if (isObject(value))
2338
+ return '{' + collectObj(value, function(k, n) { return toJSON(k) + ':' + toJSON(n); }).join() + '}';
2339
+ return toString(value);
2340
+ },
2341
+ // @condend
2342
+ // @cond !ie7compatibility 'toJSON': _window.JSON && JSON.stringify,
2343
+
2344
+ /*$
2345
+ * @id parsejson
2346
+ * @group JSON
2347
+ * @requires ucode
2348
+ * @configurable default
2349
+ * @name $.parseJSON()
2350
+ * @syntax $.parseJSON(text)
2351
+ * @module WEB
2352
+ * Parses a string containing JSON and returns the de-serialized object.
2353
+ * If the browser's built-in function <var>JSON.parse</var> is defined, which it is in pretty all browsers except
2354
+ * Internet Explorer 7 and earlier, it will be used. This is mainly to prevent possible security problems caused
2355
+ * by the use of <var>eval</var> in the implementation. Only in browsers without
2356
+ * <var>JSON.parse</var> Minified's own implementation will be used.
2357
+ *
2358
+ * If you use a Minified build without Internet Explorer 7 compatibility, <var>JSON.parse</var> will always be used.
2359
+ *
2360
+ * @example Parsing a JSON string:
2361
+ * <pre>
2362
+ * var jsonString = "{name: 'Fruits', roles: ['apple', 'banana', 'orange']}";
2363
+ * var myObj = $.parseJSON(jsonString);
2364
+ * </pre>
2365
+ *
2366
+ * @param text the JSON string
2367
+ * @return the resulting JavaScript object. <var>Undefined</var> if not valid.
2368
+ */
2369
+ // @condblock ie7compatibility
2370
+ 'parseJSON': _window.JSON ? _window.JSON.parse : function (text) {
2371
+ var t = replace(text, /[\x00\xad\u0600-\uffff]/g, ucode); // encode unsafe characters
2372
+ if (/^[[\],:{}\s]*$/ // test that, after getting rid of literals, only allowed characters can be found
2373
+ .test(replace(replace(t , /\\["\\\/bfnrtu]/g), // remove all escapes
2374
+ /"[^"\\\n\r]*"|true|false|null|[\d.eE+-]+/g)) // remove all literals
2375
+ )
2376
+ return eval('(' + t + ')');
2377
+ // fall through if not valid
2378
+ // @cond debug error('Can not parse JSON string. Aborting for security reasons.');
2379
+ },
2380
+ // @condend
2381
+ // @cond !ie7compatibility 'parseJSON': _window.JSON && JSON.parse,
2382
+
2383
+ /*$
2384
+ * @id ready
2385
+ * @group EVENTS
2386
+ * @requires ready_vars ready_init
2387
+ * @configurable default
2388
+ * @name $.ready()
2389
+ * @syntax $.ready(handler)
2390
+ * @module WEB
2391
+ * Registers a handler to be called as soon as the HTML has been fully loaded. Does not necessarily wait for images and other elements,
2392
+ * only the main HTML document needs to be complete. On older browsers, it is the same as <var>window.onload</var>.
2393
+ *
2394
+ * If you call <var>ready()</var> after the page is completed, the handler is scheduled for invocation in the event loop as soon as possible.
2395
+ *
2396
+ * @example Registers a handler that sets some text in an element:
2397
+ * <pre>
2398
+ * $.ready(function() {
2399
+ * $('#someElement').fill('ready() called');
2400
+ * });
2401
+ * </pre>
2402
+ *
2403
+ * @param handler the <code>function()</code> to be called when the HTML is ready.
2404
+ */
2405
+ 'ready': ready,
2406
+
2407
+
2408
+ /*$
2409
+ * @id setcookie
2410
+ * @group COOKIE
2411
+ * @configurable default
2412
+ * @name $.setCookie()
2413
+ * @syntax $.setCookie(name, value)
2414
+ * @syntax $.setCookie(name, value, dateOrDays)
2415
+ * @syntax $.setCookie(name, value, dateOrDays, path)
2416
+ * @syntax $.setCookie(name, value, dateOrDays, path, domain)
2417
+ * @module WEB
2418
+ * Creates, updates or deletes a cookie. If there is an an existing cookie
2419
+ * of the same name, will be overwritten with the new value and settings.
2420
+ *
2421
+ * To delete a cookie, overwrite it with an expiration date in the past. The easiest way to do this is to
2422
+ * use <code>-1</code> as third argument.
2423
+ *
2424
+ * @example Reads the existing cookie 'numberOfVisits', increases the number and stores it:
2425
+ * <pre>
2426
+ * var visits = $.getCookie('numberOfVisits');
2427
+ * $.setCookie('numberOfVisits',
2428
+ * visits ? (parseInt(visits) + 1) : 1, // if cookie not set, start with 1
2429
+ * 365); // store for 365 days
2430
+ * </pre>
2431
+ *
2432
+ * @example Deletes the cookie 'numberOfVisits':
2433
+ * <pre>
2434
+ * $.setCookie('numberOfVisits', '', -1);
2435
+ * </pre>
2436
+ *
2437
+ * @param name the name of the cookie. This should ideally be an alphanumeric name, as it will not be escaped by Minified and this
2438
+ * guarantees compatibility with all systems.
2439
+ * If it contains a '=', it is guaranteed not to work, because it breaks the cookie syntax.
2440
+ * @param value the value of the cookie. All characters can be used. Non-Alphanumeric other than "*@-_+./" will be escaped using the
2441
+ * JavaScript <var>escape()</var> function, unless you set the optional <var>dontEscape</var> parameter.
2442
+ * @param dateOrDays optional specifies when the cookie expires. Can be either a Date object or a number that specifies the
2443
+ * amount of days. If not set, the cookie has a session lifetime, which means it will be deleted as soon as the
2444
+ * browser has been closed. If the number negative or the date in the past, the cookie will be deleted.
2445
+ * @param path optional if set, the cookie will be restricted to documents in the given path. Otherwise it is valid
2446
+ * for the whole domain. This is rarely needed and defaults to '/'.
2447
+ * @param domain optional if set, you use it to specify the domain (e.g. example.com) which can read the cookie. If you don't set it,
2448
+ * the domain which hosts the current document is used. This parameter is rarely used, because there are only very
2449
+ * few use cases in which this makes sense.
2450
+ * @param dontEscape optional if set, the cookie value is not escaped. Note that without escaping you can not use every possible
2451
+ * character (e.g. ";" will break the cookie), but it may be needed for interoperability with systems that need
2452
+ * some non-alphanumeric characters unescaped or use a different escaping algorithm.
2453
+ */
2454
+ 'setCookie': function(name, value, dateOrDays, path, domain, dontEscape) {
2455
+ // @cond debug if (!name) error('Cookie name must be set!');
2456
+ // @cond debug if (/[^\w\d-_%]/.test(name)) error('Cookie name must not contain non-alphanumeric characters other than underscore and minus. Please escape them using encodeURIComponent().');
2457
+ _document.cookie = name + '=' + (dontEscape ? value : escape(value)) +
2458
+ (dateOrDays ? ('; expires='+(isObject(dateOrDays) ? dateOrDays : new Date(now() + dateOrDays * 8.64E7)).toUTCString()) : '') +
2459
+ '; path=' + (path ? escapeURI(path) : '/') + (domain ? ('; domain=' + escape(domain)) : '');
2460
+ },
2461
+
2462
+ /*$
2463
+ * @id getcookie
2464
+ * @group COOKIE
2465
+ * @requires
2466
+ * @configurable default
2467
+ * @name $.getCookie()
2468
+ * @syntax $.getCookie(name)
2469
+ * @syntax $.getCookie(name, dontUnescape)
2470
+ * @module WEB
2471
+ * Tries to find the cookie with the given name and returns it.
2472
+ *
2473
+ * @example Reads the existing cookie 'numberOfVisits' and displays the number in the element 'myCounter':
2474
+ * <pre>
2475
+ * var visits = $.getCookie('numberOfVisits');
2476
+ * if (!visits) // check whether cookie set. Null if not
2477
+ * $('#myCounter').set('innerHML', 'Your first visit.');
2478
+ * else
2479
+ * $('#myCounter').set('innerHTML', 'Visit No ' + visits);
2480
+ * </pre>
2481
+ *
2482
+ * @param name the name of the cookie. Should consist of alphanumeric characters, percentage, minus and underscore only, as it will not be escaped.
2483
+ * You may want to escape the name using <var>encodeURIComponent()</var> for all other characters.
2484
+ * @param dontUnescape optional if set and true, the value will be returned unescaped. Use this parameter only if the value has been encoded
2485
+ * in a special way, and not with the JavaScript <var>encode()</var> method.
2486
+ * @return the value of the cookie, or null if not found. Unless <var>dontUnescape</var> has been set, the value has been unescaped
2487
+ * using JavaScript's <code>unescape()</code> function.
2488
+ */
2489
+ 'getCookie': function(name, dontUnescape) {
2490
+ // @cond debug if (!name) error('Cookie name must be set!');
2491
+ // @cond debug if (/[^\w\d-_%]/.test(name)) error('Cookie name must not contain non-alphanumeric characters other than underscore and minus. Please escape them using encodeURIComponent().');
2492
+ var regexp, match = (regexp = new RegExp('(^|;)\\s*'+name+'=([^;]*)').exec(_document.cookie)) && regexp[2];
2493
+ return dontUnescape ? match : match && unescape(match);
2494
+ },
2495
+
2496
+ /*$
2497
+ * @id loop
2498
+ * @group ANIMATION
2499
+ * @requires animation_vars
2500
+ * @configurable default
2501
+ * @name $.loop()
2502
+ * @syntax $.loop(paintCallback)
2503
+ * @module WEB
2504
+ * Runs an animation loop. The given callback method will be invoked repeatedly to create a new animation frame.
2505
+ * In modern browsers, <var>requestAnimationFrame</var> will be used to invoke the callback every time the browser is ready for a new
2506
+ * animation frame.
2507
+ * The exact frequency is determined by the browser and may vary depending on factors such as the time needed to
2508
+ * render the current page, the screen's framerate and whether the page is currently visible to the user.
2509
+ * In older browsers, the callback function will be invoked approximately every 33 milliseconds.
2510
+ *
2511
+ * An animation loop runs indefinitely. To stop it, you have two options:
2512
+ * <ul><li><var>$.loop()</var> returns a <var>stop()</var> function. If you invoke it, the animation loops ends</li>
2513
+ * <li>The animation callback receives the same <var>stop()</var> function as second argument, so the callback can end the animation itself</li>
2514
+ * </ul>
2515
+ *
2516
+ * @example Animates a div by moving along in a circle.
2517
+ * <pre>
2518
+ * var myDiv = $$('#myAnimatedDiv');
2519
+ * var rotationsPerMs = 1000; // one rotation per second
2520
+ * var radius = 100;
2521
+ * var d = 3000; // duration in ms
2522
+ * $.loop(function(t, stopFunc) {
2523
+ * if (t > d) { // time is up: call stopFunc()!
2524
+ * stopFunc();
2525
+ * return;
2526
+ * }
2527
+ *
2528
+ * var a = 2 * Math.PI * t / rotationsPerMs // angular position
2529
+ * myDiv.style.left = (radius * Math.cos(a) + ' px';
2530
+ * myDiv.style.top = (radius * Math.sin(a) + ' px';
2531
+ * });
2532
+ * </pre>
2533
+ *
2534
+ * @param paintCallback a callback <code>function(timestamp, stopFunc)</code> to invoke for painting. Parameters given to callback:
2535
+ * <dl>
2536
+ * <dt>timestamp</dt><dd>The number of miliseconds since animation start.</dd>
2537
+ * <dt>stop</dt><dd>Call this <code>function()</code> to stop the currently running animation.</dd>
2538
+ * </dl>
2539
+ * The callback's return value will be ignored.
2540
+ * @return a <code>function()</code> that stops the currently running animation. This is the same function that is also given to the callback.
2541
+ */
2542
+ 'loop': function(paintCallback) {
2543
+ var entry = {c: paintCallback, t: now()};
2544
+ entry.s = function() {
2545
+ for (var i = 0; i < ANIMATION_HANDLERS.length; i++) // can't use each() or filter() here, list may be modified during run!!
2546
+ if (ANIMATION_HANDLERS[i] === entry)
2547
+ ANIMATION_HANDLERS.splice(i--, 1);
2548
+ };
2549
+
2550
+ if (ANIMATION_HANDLERS.push(entry) < 2) { // if first handler..
2551
+ (function raFunc() {
2552
+ if (each(ANIMATION_HANDLERS, function(a) {a.c(Math.max(0, now() - a.t), a.s);}).length) // check len after run, in case the callback invoked stop func
2553
+ REQUEST_ANIMATION_FRAME(raFunc);
2554
+ })();
2555
+ }
2556
+ return entry.s;
2557
+ },
2558
+
2559
+ /*$
2560
+ * @id wait
2561
+ * @configurable default
2562
+ * @requires
2563
+ * @name $.wait()
2564
+ * @syntax $.wait()
2565
+ * @syntax $.wait(durationMs)
2566
+ * @module WEB
2567
+ *
2568
+ * Creates a new promise that will be fulfilled as soon as the specified number of milliseconds have passed. This is mainly useful for animation,
2569
+ * because it allows you to chain delays into your animation chain.
2570
+ *
2571
+ * @example Chained animation using ##promise#Promise## callbacks. The element is first moved to the position 200/0, then to 200/200, waits for 50ms
2572
+ * and finally moves to 100/100.
2573
+ * <pre>
2574
+ * var div = $('#myMovingDiv').set({$left: '0px', $top: '0px'});
2575
+ * div.animate({$left: '200px', $top: '0px'}, 600, 0)
2576
+ * .then(function() {
2577
+ * div.animate({$left: '200px', $top: '200px'}, 800, 0);
2578
+ * }).then(function() {
2579
+ * return $.wait(50);
2580
+ * }).then(function() {
2581
+ * div.animate({$left: '100px', $top: '100px'}, 400);
2582
+ * });
2583
+ * });
2584
+ * </pre>
2585
+ *
2586
+ *
2587
+ * @param durationMs optional the number of milliseconds to wait. If omitted, the promise will be fulfilled as soon as the browser can run it
2588
+ * from the event loop.
2589
+ * @param args optional an array of arguments to pass to the promise handler
2590
+ * @return a ##promise#Promise## object that will be fulfilled when the time is over. It will never fail. The promise argument is the
2591
+ * <var>args</var> parameter as given to <var>wait()</var>.
2592
+ */
2593
+ 'wait': function(durationMs, args) {
2594
+ var p = promise();
2595
+ delay(function() {p(true, args);}, durationMs);
2596
+ return p;
2597
+ },
2598
+
2599
+ /*$
2600
+ * @id off
2601
+ * @group EVENTS
2602
+ * @requires on
2603
+ * @configurable default
2604
+ * @name $.off()
2605
+ * @syntax $.off(handler)
2606
+ * @module WEB
2607
+ * Removes the given event handler. The call will be ignored if the given handler has not been registered using ##on().
2608
+ * If the handler has been registered for more than one element or event, it will be removed from all instances.
2609
+ *
2610
+ * @example Adds a handler to an element:
2611
+ * <pre>
2612
+ * function myEventHandler() {
2613
+ * this.style.backgroundColor = 'red'; // 'this' contains the element that caused the event
2614
+ * }
2615
+ * $('#myElement').on('click', myEventHandler); // add event handler
2616
+ *
2617
+ * window.setInterval(function() { // after 5s, remove event handler
2618
+ * $.off(myEventHandler);
2619
+ * }, 5000);
2620
+ * </pre>
2621
+ *
2622
+ * @param handler the handler to unregister, as given to ##on(). It must be a handler that has previously been registered using ##on().
2623
+ * If the handler is not registered as event handler, the function does nothing.
2624
+ */
2625
+ 'off': function (handler) {
2626
+ // @cond debug if (!handler || !handler['M']) error("No handler given or handler invalid.");
2627
+ each(handler['M'], function(h) {
2628
+ // @condblock ie8compatibility
2629
+ if (h['e'].removeEventListener)
2630
+ // @condend
2631
+ h['e'].removeEventListener(h['n'], h['h'], true); // W3C DOM
2632
+ // @condblock ie8compatibility
2633
+ else
2634
+ h['e'].detachEvent('on'+h['n'], h['h']); // IE < 9 version
2635
+ // @condend
2636
+ });
2637
+ handler['M'] = null;
2638
+ }
2639
+
2640
+
2641
+ /*$
2642
+ * @stop
2643
+ */
2644
+ // @cond !off dummy:null
2645
+
2646
+ }, function(n, v) {$[n]=v;});
2647
+
2648
+ //// GLOBAL INITIALIZATION ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2649
+
2650
+ /*$
2651
+ * @id ready_init
2652
+ * @dependency
2653
+ */
2654
+ // @condblock ie8compatibility
2655
+ _window.onload = triggerDomReady;
2656
+
2657
+ if (_document.addEventListener)
2658
+ // @condend
2659
+ _document.addEventListener("DOMContentLoaded", triggerDomReady, false);
2660
+ /*$
2661
+ @stop
2662
+ */
2663
+
2664
+ // @condblock amdsupport
2665
+ return {
2666
+ // @condend amdsupport
2667
+
2668
+ // @cond !amdsupport var MINI = {
2669
+
2670
+ /*$
2671
+ * @id dollar
2672
+ * @group SELECTORS
2673
+ * @requires dollarraw
2674
+ * @dependency yes
2675
+ * @name $()
2676
+ * @syntax $(selector)
2677
+ * @syntax $(selector, context)
2678
+ * @syntax $(selector, context, childOnly)
2679
+ * @syntax $(list)
2680
+ * @syntax $(list, context)
2681
+ * @syntax $(list, context, childOnly)
2682
+ * @syntax $(object)
2683
+ * @syntax $(object, context)
2684
+ * @syntax $(object, context, childOnly)
2685
+ * @syntax $(domreadyFunction)
2686
+ * @module WEB
2687
+ * Creates a new ##list#Minified list##, or register a DOMReady-handler.
2688
+ * The most common usage is with a CSS-like selector. <var$()</var> will then create a list containing all elements of the current HTML
2689
+ * document that fulfill the filter conditions. Alternatively you can also specify a list of objects or a single object.
2690
+ * Nested lists will automatically be flattened, and nulls will automatically be removed from the resulting list.
2691
+ *
2692
+ * Additionally, you can specify a second argument to provide a context. Contexts only make sense if you selected only
2693
+ * HTML nodes with the first parameter. Then the context limits the resulting list to include only those nodes
2694
+ * that are descendants of the context nodes. The context can be either a selector, a list or a single HTML node, and will be
2695
+ * processed like the first argument. A third arguments allows you to limit the list to
2696
+ * only those elements that are direct children of the context nodes (so a child of a child would be filtered out).
2697
+ *
2698
+ *
2699
+ * As a special shortcut, if you pass a function to <var>$()</var>, it will be registered using #ready#$.ready() to be executed
2700
+ * when the DOM model is complete.
2701
+ *
2702
+ * @example A simple selector to find an element by id.
2703
+ * <pre>
2704
+ * var l0 = $('#myElementId');
2705
+ * </pre>
2706
+ *
2707
+ * @example You can pass a reference to a DOM node to the function to receive a list containing only this node:
2708
+ * <pre>
2709
+ * var l1 = $(document.getElementById('myElementId'));
2710
+ * </pre>
2711
+ *
2712
+ * @example Lists and arrays will be copied:
2713
+ * <pre>
2714
+ * var l2 = $([elementA, elementB, elementC]);
2715
+ * </pre>
2716
+ *
2717
+ * @example Lists will be automatically flattened and nulls removed. So this list <var>l3</var> has the same content as <var>l2</var>:
2718
+ * <pre>
2719
+ * var l3 = $([elementA, [elementB, null, elementC], null]);
2720
+ * </pre>
2721
+ *
2722
+ * @example This is a simple selector to find all elements with the given class.
2723
+ * <pre>
2724
+ * var l4 = $('.myClass');
2725
+ * </pre>
2726
+ *
2727
+ * @example A selector to find all elements with the given name.
2728
+ * <pre>
2729
+ * var l5 = $('input'); // finds all input elements
2730
+ * </pre>
2731
+ *
2732
+ * @example A selector to find all elements with the given name and class.
2733
+ * <pre>
2734
+ * var l6 = $('input.myRadio'); // finds all input elements with class 'myRadio'
2735
+ * </pre>
2736
+ *
2737
+ * @example A selector to find all elements that are descendants of the given element.
2738
+ * <pre>
2739
+ * var l7 = $('#myForm input'); // finds all input elements that are in the element with the id myForm
2740
+ * </pre>
2741
+ *
2742
+ * @example A selector to find all elements that have either CSS class 'a' or class 'b':
2743
+ * <pre>
2744
+ * var l8 = $('.a, .b'); // finds all elements that have either the class a or class b
2745
+ * </pre>
2746
+ *
2747
+ * @example A selector that finds all elements that are descendants of the element myDivision, are inside a .myForm class and are input elements:
2748
+ * <pre>
2749
+ * var l9 = $('#myDivision .myForm input');
2750
+ * </pre>
2751
+ *
2752
+ * @example Using contexts to make it easier to specify ancestors:
2753
+ * <pre>
2754
+ * var l10 = $('.myRadio', '#formA, #formB, #formC');
2755
+ * </pre>
2756
+ * The result is identical to:
2757
+ * <pre>
2758
+ * var l10 = $('#formA .myRadio, #formB .myRadio, #formC .myRadio');
2759
+ * </pre>
2760
+ *
2761
+ * @example Using one of the list functions, ##set(), on the list, and setting the element's text color. '$' at the beginning of the property name sets a CSS value.
2762
+ * <pre>
2763
+ * $('#myElementId').set('$color', 'red');
2764
+ * </pre>
2765
+ *
2766
+ * @example Most list methods return the list you invoked them on, allowing you to chain them:
2767
+ * <pre>
2768
+ * $('#myForm .myRadio').addClass('uncheckedRadio')
2769
+ * .set('checked', true)
2770
+ * .on('click', function() {
2771
+ * $(this).set({@: 'uncheckedRadio');
2772
+ * });
2773
+ * </pre>
2774
+ *
2775
+ * @example Using $() as a #ready#$.ready() shortcut:
2776
+ * <pre>
2777
+ * $(function() {
2778
+ * // in here you can safely work with the HTML document
2779
+ * });
2780
+ * </pre>
2781
+ *
2782
+ * @param selector a simple, CSS-like selector for HTML elements. It supports '#id' (lookup by id), '.class' (lookup by class),
2783
+ * 'element' (lookup by elements) and 'element.class' (combined class and element). Use commas to combine several selectors.
2784
+ * You can also join two or more selectors by space to find elements which are descendants of the previous selectors.
2785
+ * For example, use 'div' to find all div elements, '.header' to find all elements containing a class name called 'header', and
2786
+ * 'a.popup' for all a elements with the class 'popup'. To find all elements with 'header' or 'footer' class names,
2787
+ * write '.header, .footer'. To find all divs elements below the element with the id 'main', use '#main div'.
2788
+ * The selector "*" will return all elements.
2789
+ * @param list a list to copy. It can be an array, another Minified list, a DOM nodelist or anything else that has a <var>length</var> property and
2790
+ * allows read access by index. A shallow copy of the list will be returned. Nulls will be automatically removed from the copy. Nested lists
2791
+ * will be flattened, so the result only contains nodes.
2792
+ * @param object a object to create a single-element list containing only the object. If the object argument is null, an empty list will be returned.
2793
+ * @param domreadyFunction a function to be registered using #ready#$.ready().
2794
+ * @param context optional an optional selector, node or list of nodes which specifies one or more common ancestor nodes for the selection, using the same syntax variants as the
2795
+ * first argument. If given, the returned list contains only descendants of the context nodes, all others will be filtered out.
2796
+ * @param childOnly optional if set, only direct children of the context nodes are included in the list. Children of children will be filtered out. If omitted or not
2797
+ * true, all descendants of the context will be included.
2798
+ * @return the array-like ##list#Minified list## object containing the content specified by the selector.
2799
+ * Please note that duplicates (e.g. created using the comma-syntax or several context nodes) will not be removed. If the first argument was a list,
2800
+ * the existing order will be kept. If the first argument was a simple selector, the nodes are in document order. If you combined several selectors
2801
+ * using commas, only the individual results of the selectors will keep the document order, but will then be joined to form a single list. This list will,
2802
+ * not be in document order anymore, unless you use a build without legacy IE support.
2803
+ */
2804
+ '$': $,
2805
+
2806
+ /*$
2807
+ * @id dollardollar
2808
+ * @group SELECTORS
2809
+ * @requires dollarraw
2810
+ * @configurable default
2811
+ * @name $$()
2812
+ * @syntax $$(selector)
2813
+ * @shortcut $$() - It is recommended that you assign MINI.$$ to a variable $$.
2814
+ * @module WEB
2815
+ * Returns a DOM object containing the first match of the given selector, or <var>undefined</var> if no match was found.
2816
+ * <var>$$</var> allows you to easily access an element directly. It is the equivalent to writing "$(selector)[0]".
2817
+ *
2818
+ * Please note that the function <var>$$</var> will not be automatically exported by Minified. You should always import it
2819
+ * using the recommended import statement:
2820
+ * <pre>
2821
+ * var MINI = require('minified'), $ = MINI.$, $$ = MINI.$$, EE = MINI.EE;
2822
+ * </pre>
2823
+ *
2824
+ * @example Select the checkbox 'myCheckbox':
2825
+ * <pre>
2826
+ * $$('#myCheckbox').checked = true;
2827
+ * </pre>
2828
+ *
2829
+ * @param selector a simple, CSS-like selector for the element. Uses the full syntax described in #dollar#$(). The most common
2830
+ * parameter for this function is the id selector with the syntax "#id".
2831
+ * @return a DOM object of the first match, or <var>undefined</var> if the selector did not return at least one match
2832
+ */
2833
+ '$$': $$,
2834
+
2835
+
2836
+ /*$
2837
+ * @id ee
2838
+ * @group ELEMENT
2839
+ * @requires dollar set add
2840
+ * @configurable default
2841
+ * @name EE()
2842
+ * @syntax EE(elementName)
2843
+ * @syntax EE(elementName, properties)
2844
+ * @syntax EE(elementName, children)
2845
+ * @syntax EE(elementName, properties, children)
2846
+ * @syntax EE(elementName, properties, children, onCreate)
2847
+ * @shortcut EE() - It is recommended that you assign MINI.EE to a variable EE.
2848
+ * @module WEB
2849
+ * Creates a new Element Factory. An Element Factory is a function without arguments that returns a ##list#Minified list##
2850
+ * containing a newly created DOM element, optionally with attributes and children.
2851
+ * Typically it will be used to insert elements into the DOM tree using ##add() or a similar function.
2852
+ *
2853
+ * Please note that the function <var>EE</var> will not be automatically exported by Minified. You should always import it
2854
+ * using the recommended import statement:
2855
+ * <pre>
2856
+ * var MINI = require('minified'), $ = MINI.$, $$ = MINI.$$, EE = MINI.EE;
2857
+ * </pre>
2858
+ *
2859
+ * @example Creating a simple factory for a &lt;span> element with some text:
2860
+ * <pre>
2861
+ * var mySpan = EE('span', 'Hello World');
2862
+ * </pre>
2863
+ * creates a factory to produce this:
2864
+ * <pre>
2865
+ * &lt;span>Hello World&lt;/span>
2866
+ * </pre>
2867
+ *
2868
+ * @example Adding the 'Hello World; &lt;span> element to all elements with the class '.greeting':
2869
+ * <pre>
2870
+ * $('.greeting').add(EE('span', 'Hello World'));
2871
+ *
2872
+ * @example Creating a factory for a &lt;span> element with style and some text:
2873
+ * <pre>
2874
+ * var span2 = EE('span', {'@title': 'Greetings'}, 'Hello World');
2875
+ * </pre>
2876
+ * The factory creates this:
2877
+ * <pre>
2878
+ * &lt;span title="Greetings">Hello World&lt;/span>
2879
+ * </pre>
2880
+ *
2881
+ * @example Creating a &lt;form> element with two text fields, labels and a submit button:
2882
+ * <pre>var myForm = EE('form', {'@method': 'post'}, [
2883
+ * EE('label', {'@for': 'nameInput'}, 'Name:'),
2884
+ * EE('input', {'@id': 'nameInput', '@type': 'input'}),
2885
+ * EE('br'),
2886
+ * EE('label', {'@for': 'ageInput'}, 'Age:'),
2887
+ * EE('input', {'@id': 'ageInput', '@type': 'input'}),
2888
+ * EE('br'),
2889
+ * EE('input', {'@type': 'submit, '@value': 'Join'})
2890
+ * ]);
2891
+ * </pre>
2892
+ * results in (newlines and indentation added for readability):
2893
+ * <pre>
2894
+ * &lt;form method="post>
2895
+ * &lt;label for="nameInput">Name:&lt;/label>
2896
+ * &lt;input id="nameInput" type="input"/>
2897
+ * &lt;br/>
2898
+ * &lt;label for="ageInput"/>Age:&lt;/label>
2899
+ * &lt;input id="ageInput" type="input"/>
2900
+ * &lt;br/>
2901
+ * &lt;input value="Join" type="submit"/>
2902
+ * &lt;/form>
2903
+ * </pre>
2904
+ *
2905
+ * @example If you only want to add an attribute under a certain condition,
2906
+ * a simple trick is to pass null as value if you do not need it:
2907
+ * <pre>
2908
+ * var myInput = EE('input', {
2909
+ * '@id': 'myCheckbox',
2910
+ * '@type': 'checkbox',
2911
+ * '@checked': shouldBeChecked() ? 'checked' : null
2912
+ * });
2913
+ * </pre>
2914
+ *
2915
+ * @example You can set styles directly using a $ prefix for the name:
2916
+ * <pre>
2917
+ * var myStylesSpan = EE('span', {$color: "red", $fontWeight: "bold"}, "I'm styled");
2918
+ * </pre>
2919
+ *
2920
+ * @example To add event handlers, use the fourth argument:
2921
+ * <pre>
2922
+ * var myStylesSpan = EE('input', {'@name': "myInput"}, null, function(e) {
2923
+ * e.on('change', inputChanged);
2924
+ * });
2925
+ * </pre>
2926
+ *
2927
+ * @param elementName the element name to create (e.g. 'div')
2928
+ * @param properties optional an object which contains a map of attributes and other values. Uses the ##set() syntax:
2929
+ * Attribute values are prefixed with '@', CSS styles with '$' and regular properties can be set without prefix.
2930
+ * If the attribute value is null, the attribute will omitted (styles and properties can be set to null).
2931
+ * In order to stay compatible with Internet Explorer 7 and earlier, you should not set the
2932
+ * attributes '@class' and '@style'. Instead set the property 'className' instead of '@class' and set
2933
+ * styles using the '$' syntax.
2934
+ * @param children optional a node or a list of nodes to be added as children. Strings will be converted to text nodes.
2935
+ * Functions will be invoked and their return value will be used. Lists can be
2936
+ * nested and will then automatically be flattened. Null elements in lists will be ignored.
2937
+ * The syntax is exactly like ##add().
2938
+ * @param onCreate optional a <code>function(elementList)</code> that will be called each time an element had been created.
2939
+ * <dl><dt>elementList</dt><dd>The newly created element wrapped in a Minified list. </dd></dl>
2940
+ * The function's return value will be ignored.
2941
+ * The callback allows you, for example, to add event handlers to the element using ##on().
2942
+ * @return a Element Factory function, which returns a Minified list containing the DOM HTMLElement that has been created or modified as only element
2943
+ */
2944
+ 'EE': EE
2945
+
2946
+ /*$
2947
+ * @stop
2948
+ */
2949
+ // @cond !ee dummy:null
2950
+ };
2951
+ // @cond !amdsupport _window['require'] = function(n) { if (n == 'minified') return MINI; };
2952
+
2953
+
2954
+ // @condblock amdsupport
2955
+ });
2956
+ // @condend amdsupport
2957
+
2958
+ // @cond !amdsupport })();
2959
+
2960
+
2961
+ /*$
2962
+ * @id list
2963
+ * @name Minified Lists
2964
+ * @module WEB, UTIL
2965
+ *
2966
+ * <i>Minified lists</i> are Array-like objects provided by Minified. Like a regular JavaScript array,
2967
+ * they provide a <var>length</var> property and you can access their content using the index operator (<code>a[5]</code>).
2968
+ * However, they do not provide the same methods as JavaScript's native array.
2969
+ *
2970
+ * Minified lists are usually created using the #dollar#$()</a></code> function. You can
2971
+ * also use <code>$()</code> to convert a JavaScript array into a Minified list, just be aware that <code>$()</code> will
2972
+ * remove nulls from the lists and will flatten nested lists.
2973
+ *
2974
+ * There is currently no function to convert a Minified list into a JavaScript array. The upcoming Utility module
2975
+ * will provide one though.
2976
+ *
2977
+ * The Minified Web module provides HTML-node oriented functions like ##set() to modify a list of nodes. It also has a
2978
+ * number of helper methods for working with Minified lists:
2979
+ * <ul>
2980
+ * <li>##collect() creates a new list using the collect function which can
2981
+ * transform list elements or collect data from them ("map() on steriods")</li>
2982
+ * <li>##each() iterates through all list elements</li>
2983
+ * <li>##filter() creates a new list that contains only elements that pass the
2984
+ * filter function's test</li>
2985
+ * <li>##find() finds a list element or its position</li>
2986
+ * <li>##sub() creates a list that copies the elements from the specified index range </li>
2987
+ * </ul>
2988
+ */
2989
+
2990
+ /*$
2991
+ * @id promise
2992
+ * @name Promise
2993
+ * @module WEB, UTIL
2994
+ *
2995
+ * <i>Promises</i> are objects that represent the result of an asynchronous operation. When you start such an operation, using #request#$.request(),
2996
+ * ##animate(), or ##wait(), you will get a Promise object that allows you to get the result as soon as the operation is finished.
2997
+ *
2998
+ * Minified ships with a <a href="http://promises-aplus.github.io/promises-spec/">Promises/A+</a>-compliant implementation of Promises that should
2999
+ * be able to interoperate with most other Promises implementations.
3000
+ *
3001
+ * What may be somewhat surprising about this Promises specification is that there is no direct way to find out the state of the operation.
3002
+ * There is neither a property nor a function to find out what the result is or whether it is available. Instead, you always have to
3003
+ * register callbacks to find out the result. They will be invoked as soon as the operation is finished.
3004
+ * If the operation already ended when you register the callbacks, the callback will then just be called from the event loop as soon
3005
+ * as possible (but never while the ##then() you register them with is still running).<br/>
3006
+ * This design forces you to handle the operation result asynchronously and disencourages 'bad' techniques such as polling.
3007
+ *
3008
+ * The central method of a Promises, and indeed the only required function in Promises/A+, is ##then(). It allows you to register
3009
+ * two callback methods, one for success (called 'fulfillment' in Promises/A+ terminology) and one for failures (called 'rejection' in Promises/A+).
3010
+ *
3011
+ * This example shows you how to use <var>then()</var>:
3012
+ * <pre>
3013
+ * $.request('get', 'http://example.com/weather?zip=90210')
3014
+ * .then(function success(result) {
3015
+ * alert('The weather is ' + result);
3016
+ * }, function error(exception) {
3017
+ * alert('Something went wrong');
3018
+ * });
3019
+ * </pre>
3020
+ *
3021
+ * What makes Promises so special is that ##then() itself returns a new Promise, which is based on the Promise <var>then()</var> was called on, but can be
3022
+ * modified by the outcome of callbacks. Both arguments to <var>then()</var> are optional, and you can also write the code like this:
3023
+ * <pre>
3024
+ * $.request('get', 'http://example.com/weather?zip=90210')
3025
+ * .then(function success(result) {
3026
+ * alert('The weather is ' + result);
3027
+ * })
3028
+ * .then(null, function error(exception) {
3029
+ * alert('Something went wrong');
3030
+ * });
3031
+ * </pre>
3032
+ *
3033
+ * Because the first ##then() returns a new Promise based on the original Promise, the second <var>then()</var> will handle errors of the request just like
3034
+ * the first one did. There is only one subtle difference in the second example: the error handler will not only be called if the request failed,
3035
+ * but also when the request succeded but the success handler threw an exception. That's one of the two differences between the original Promise and
3036
+ * the Promise returned by <var>then()</var>. Any exception thrown in a callback causes the new Promise to be in error state.
3037
+ *
3038
+ * Before I show you the second difference between the original Promise and the new Promise, let me make the example a bit more readable
3039
+ * by using ##error(), which is not part of Promises/A+, but a simple extension by Minified. It just registers the failure callback without
3040
+ * forcing you to specify <var>null</var> as first argument:
3041
+ * <pre>
3042
+ * $.request('get', 'http://example.com/weather?zip=90210')
3043
+ * .then(function success(result) {
3044
+ * alert('The weather is ' + result);
3045
+ * })
3046
+ * .error(function error(exception) { // error(callback) is equivalent to then(null, callback)
3047
+ * alert('Something went wrong');
3048
+ * });
3049
+ * </pre>
3050
+ *
3051
+ * A very powerful capability of Promises is that you can easily chain them. If a ##then() callback returns a value, the new Promise returned
3052
+ * by <var>then()</var> will be marked as success (fulfilled) and this value is the result of the operation. If a callback returns a Promise,
3053
+ * the new Promise will assume the state of the returned Promise. You can use the latter to create chains of asynchronous operations,
3054
+ * but you still need only a single error handler for all of them and you do not need to nest functions to achieve this:
3055
+ * <pre>
3056
+ * $.request('get', 'http://example.com/zipcode?location=Beverly+Hills,+CA')
3057
+ * .then(function(resultZip) {
3058
+ * return $.request('get', 'http://example.com/weather', {zip: resultZip});
3059
+ * })
3060
+ * .then(function(resultWeather) {
3061
+ * alert('The weather in Beverly Hills is ' + resultWeather);
3062
+ * })
3063
+ * .error(function(exception) {
3064
+ * alert('Something went wrong');
3065
+ * });
3066
+ * </pre>
3067
+ *
3068
+ * Sometimes you want to just be notified of the end of an operation but are not interested in the outcome. For these cases, if you just had
3069
+ * the Promises/A+-compliant ##then() method, you would have to register the same callback handler twice. This is not very convenient,
3070
+ * especially when you define the handler function inline. Therefore Minified comes with a second small extension, ##always():
3071
+ *
3072
+ * <pre>
3073
+ * $.request('post', 'http://example.com/pageHit', {pageId: 12345})
3074
+ * .always(function() { // always(callback) is equivalent to then(callback, callback)
3075
+ * pageCountDone();
3076
+ * });
3077
+ * </pre>
3078
+ *
3079
+ * Please note that the Minified Web module only returns Promises, but it <strong>does not allow you to create Promises</strong> directly. The upcoming
3080
+ * Minified App module will allow this though.
3081
+ */
3082
+
3083
+
3084
+
3085
+
3086
+