├── .gitattributes
├── LICENSE
├── .gitignore
├── README.md
└── qatrix.js
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Disable LF normalization for all files
2 | * -text
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | [MIT LICENSE]
2 |
3 | Copyright (c) 2013 Angel Lai, http://qatrix.com
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, andor 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.
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Eclipse
3 | #################
4 |
5 | *.pydevproject
6 | .project
7 | .metadata
8 | bin/
9 | tmp/
10 | *.tmp
11 | *.bak
12 | *.swp
13 | *~.nib
14 | local.properties
15 | .classpath
16 | .settings/
17 | .loadpath
18 |
19 | # External tool builders
20 | .externalToolBuilders/
21 |
22 | # Locally stored "Eclipse launch configurations"
23 | *.launch
24 |
25 | # CDT-specific
26 | .cproject
27 |
28 | # PDT-specific
29 | .buildpath
30 |
31 |
32 | #################
33 | ## Visual Studio
34 | #################
35 |
36 | ## Ignore Visual Studio temporary files, build results, and
37 | ## files generated by popular Visual Studio add-ons.
38 |
39 | # User-specific files
40 | *.suo
41 | *.user
42 | *.sln.docstates
43 |
44 | # Build results
45 | [Dd]ebug/
46 | [Rr]elease/
47 | *_i.c
48 | *_p.c
49 | *.ilk
50 | *.meta
51 | *.obj
52 | *.pch
53 | *.pdb
54 | *.pgc
55 | *.pgd
56 | *.rsp
57 | *.sbr
58 | *.tlb
59 | *.tli
60 | *.tlh
61 | *.tmp
62 | *.vspscc
63 | .builds
64 | *.dotCover
65 |
66 | ## TODO: If you have NuGet Package Restore enabled, uncomment this
67 | #packages/
68 |
69 | # Visual C++ cache files
70 | ipch/
71 | *.aps
72 | *.ncb
73 | *.opensdf
74 | *.sdf
75 |
76 | # Visual Studio profiler
77 | *.psess
78 | *.vsp
79 |
80 | # ReSharper is a .NET coding add-in
81 | _ReSharper*
82 |
83 | # Installshield output folder
84 | [Ee]xpress
85 |
86 | # DocProject is a documentation generator add-in
87 | DocProject/buildhelp/
88 | DocProject/Help/*.HxT
89 | DocProject/Help/*.HxC
90 | DocProject/Help/*.hhc
91 | DocProject/Help/*.hhk
92 | DocProject/Help/*.hhp
93 | DocProject/Help/Html2
94 | DocProject/Help/html
95 |
96 | # Click-Once directory
97 | publish
98 |
99 | # Others
100 | [Bb]in
101 | [Oo]bj
102 | sql
103 | TestResults
104 | *.Cache
105 | ClientBin
106 | stylecop.*
107 | ~$*
108 | *.dbmdl
109 | Generated_Code #added for RIA/Silverlight projects
110 |
111 | # Backup & report files from converting an old project file to a newer
112 | # Visual Studio version. Backup files are not needed, because we have git ;-)
113 | _UpgradeReport_Files/
114 | Backup*/
115 | UpgradeLog*.XML
116 |
117 |
118 |
119 | ############
120 | ## Windows
121 | ############
122 |
123 | # Windows image file caches
124 | Thumbs.db
125 |
126 | # Folder config file
127 | Desktop.ini
128 |
129 |
130 | #############
131 | ## Python
132 | #############
133 |
134 | *.py[co]
135 |
136 | # Packages
137 | *.egg
138 | *.egg-info
139 | dist
140 | build
141 | eggs
142 | parts
143 | bin
144 | var
145 | sdist
146 | develop-eggs
147 | .installed.cfg
148 |
149 | # Installer logs
150 | pip-log.txt
151 |
152 | # Unit test / coverage reports
153 | .coverage
154 | .tox
155 |
156 | #Translations
157 | *.mo
158 |
159 | #Mr Developer
160 | .mr.developer.cfg
161 |
162 | # Mac crap
163 | .DS_Store
164 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Qatrix - Easily build up high-performance applications with less code.
2 |
3 | > This project is no longer maintained.
4 |
5 | Qatrix is a new kind of JavaScript framework targeting building up high-performance and flexible web applications with less code and friendly construction. It`s free and open source.
6 |
7 | Designed to simplify the script with friendly and easy-to-learn code construction and noticeably increase the performance and efficiency of the development of web applications.
8 |
9 | ### Main Features
10 |
11 | * **Hardware accelerated animation** - The first framework supports hardware-accelerated native CSS3 transition for animation. The animation of Qatrix will be impressively faster and smoother than other frameworks. Significantly improved the visual effects on the web application.
12 |
13 | * **High performance code** - Supports CSS3 and HTML5. Qatrix is using more native code and special design to increase performance. The web application will run much faster and more efficiently than other frameworks about 50% on average.
14 |
15 | * **Easy-to-learn** - The names of functions on Qatrix are simple, user-friendly, and familiar with jQuery. It will be much easier to use without re-learn other new concepts and knowledge.
16 |
17 | * **Incredible size** - Only 6KB compressed and gzipped file size with 60+ functions, including hardware accelerated animation, DOM, AJAX, template, require loader, various selectors, cookie, event handle, local storage, and so on, enough for most common web development needs. Load powerful script instantly without expectation.
18 |
19 | ### Quick start
20 |
21 | #### DOM & Animation
22 | ```JavaScript
23 | $tag($('wrap'), 'div', function (item) {
24 | $html(item, 'some value');
25 | });
26 |
27 | $hide($('element_id'));
28 |
29 | $hide($('element_id_1 element_id_2 element_id_3'), 500);
30 |
31 | $animate($("element"), {
32 | "width": {
33 | from: 200,
34 | to: 30
35 | }
36 | }, 500, function () {
37 | // Do something
38 | });
39 | ```
40 |
41 | #### AJAX
42 | ```JavaScript
43 | $ajax("example.php", {
44 | data: {
45 | "foo": "bar"
46 | },
47 | success: function (data) {
48 | // Do something
49 | }
50 | });
51 | ```
52 |
53 | #### Template
54 | ```JavaScript
55 | var template = "
{{header}}
{{header2}}
{{#list}}- {{this}}
{{/list}}
{{#people}}- {{name}} - {{city}}
{{/people}}
";
56 |
57 | var data = {
58 | header: "Header",
59 | header2: "Header2",
60 | header3: "Header3",
61 | list: ["1", "2", "3"],
62 | people: [
63 | {"name": "Tom", "city": "California"},
64 | {"name": "Jack", "city": "Newton"},
65 | {"name": "Jone", "city": "Tokyo"}
66 | ]
67 | };
68 |
69 | $append($("container"), $template(template, data));
70 | ```
71 |
72 | #### Require
73 | ```JavaScript
74 | $require([
75 | "http://abc.com/foo.js",
76 | "http://abc.com/foo.css"
77 | ], function () {
78 | // Do something
79 | });
80 | ```
81 |
82 | #### Cookie & storage
83 | ```JavaScript
84 | $cookie.set("foo", "bar");
85 | $storage.set("foo", "bar");
86 | ```
87 |
88 | ### License
89 |
90 | Qatrix is under the MIT license. You can freely use or distribute your project as long as declaring the original copyright information.
91 |
92 | ### Compatibility
93 |
94 | IE6+, Chrome, Firefox 2+, Safari 3+, Opera 9+.
95 |
96 | ### Benchmark
97 |
98 | Template (500% faster) - [http://jsperf.com/dom-vs-innerhtml-based-templating/735](http://jsperf.com/dom-vs-innerhtml-based-templating/735)
99 |
--------------------------------------------------------------------------------
/qatrix.js:
--------------------------------------------------------------------------------
1 | /*
2 | Qatrix JavaScript v1.1.2
3 |
4 | Copyright (c) 2013, Angel Lai
5 | The Qatrix project is under MIT license.
6 | For details, see the Qatrix website: http://qatrix.com
7 | */
8 |
9 | (function (window, document, undefined) {
10 |
11 | var
12 | version = '1.1.2',
13 |
14 | docElem = document.documentElement,
15 |
16 | rbline = /(^\n+)|(\n+$)/g,
17 | rbrace = /^(?:\{.*\}|\[.*\])$/,
18 | rcamelCase = /-([a-z])/ig,
19 | rdigit = /\d/,
20 | rline = /\r\n/g,
21 | rnum = /[\-\+0-9\.]/ig,
22 | rspace = /\s+/,
23 | rquery = /\?/,
24 | ropacity = /opacity=([^)]*)/,
25 | rvalidchars = /^[\],:{}\s]*$/,
26 | rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
27 | rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,
28 | rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
29 |
30 | animDisplay = 'height margin-top margin-bottom padding-top padding-bottom'.split(' '),
31 |
32 | // For $require loaded resource
33 | require_loaded = {},
34 |
35 | // For complied template
36 | template_cache = {},
37 |
38 | // For DOM ready
39 | readyList = [],
40 | ready = function ()
41 | {
42 | $each(readyList, function (i, callback)
43 | {
44 | callback();
45 | });
46 | document.removeEventListener('DOMContentLoaded', ready, false);
47 | },
48 |
49 | // For $append, $prepend, $before, $after
50 | nodeManip = function (elem, node)
51 | {
52 | var type = typeof node;
53 |
54 | if (type === 'string')
55 | {
56 | var doc = elem && elem.ownerDocument || document,
57 | fragment = doc.createDocumentFragment(),
58 | div = $new('div'),
59 | ret = [];
60 |
61 | div.innerHTML = node;
62 | while (div.childNodes[0] != null)
63 | {
64 | fragment.appendChild(div.childNodes[0]);
65 | }
66 | node = fragment;
67 |
68 | // Release memory
69 | div = null;
70 | }
71 |
72 | if (type === 'number')
73 | {
74 | node += '';
75 | }
76 |
77 | return node;
78 | },
79 |
80 | // For map function callback
81 | mapcall = function (match, callback)
82 | {
83 | if (match === null)
84 | {
85 | return;
86 | }
87 |
88 | if (callback === undefined)
89 | {
90 | return match;
91 | }
92 |
93 | var i = 0,
94 | length = match.length;
95 |
96 | if (length !== undefined && length > 0)
97 | {
98 | for (; i < length;)
99 | {
100 | if (callback.call(match[i], match[i], match[i++]) === false)
101 | {
102 | break;
103 | }
104 | }
105 |
106 | return match;
107 | }
108 | else
109 | {
110 | return callback.call(match, match);
111 | }
112 | },
113 |
114 | // For $show and $hide
115 | displayElem = function (elem, type, duration, callback)
116 | {
117 | return mapcall(elem, function (elem)
118 | {
119 | var prop = {},
120 | show = type === 'show',
121 | style = elem.style,
122 | display = elem['_display'],
123 | temp, overflow;
124 |
125 | if (!display)
126 | {
127 | display = $style.get(elem, 'display');
128 | if (display === 'none' || display === 'inherit')
129 | {
130 | temp = $append(document.body, $new(elem.nodeName));
131 | display = $style.get(temp, 'display');
132 | $remove(temp);
133 | }
134 | elem['_display'] = display;
135 | }
136 |
137 | if (show)
138 | {
139 | style.display = display;
140 | }
141 | else
142 | {
143 | display = 'none';
144 | }
145 |
146 | if (duration)
147 | {
148 | overflow = $style.get(elem, 'overflow');
149 | style.overflow = 'hidden';
150 |
151 | prop.opacity = show ? {
152 | from: 0,
153 | to: 1
154 | } : {
155 | from: 1,
156 | to: 0
157 | };
158 |
159 | $each(animDisplay, function (i, css)
160 | {
161 | prop[css] = show ? {
162 | from: 0,
163 | to: $style.get(elem, css)
164 | } : 0;
165 | });
166 | $animate(elem, prop, duration, function ()
167 | {
168 | $each(animDisplay, function (i, css)
169 | {
170 | $css.set(elem, css, '');
171 | });
172 | style.filter = style.opacity = style.overflow = '';
173 | style.display = display;
174 |
175 | if (callback)
176 | {
177 | callback.call(elem);
178 | }
179 | });
180 | }
181 | else
182 | {
183 | style.display = display;
184 | }
185 | });
186 | },
187 |
188 | // For $ajax parameter
189 | addParam = function (prefix, data)
190 | {
191 | if (typeof data === 'object')
192 | {
193 | var rdata = [];
194 |
195 | $each(data, function (key, value)
196 | {
197 | if (typeof value === 'object')
198 | {
199 | rdata.push(addParam(prefix + '[' + key + ']', value));
200 | }
201 | else
202 | {
203 | rdata.push(prefix + '[' + $url(key) + ']=' + $url(value));
204 | }
205 | });
206 |
207 | return rdata.join('&');
208 | }
209 | else
210 | {
211 | return $url(prefix) + '=' + $url(data);
212 | }
213 | },
214 |
215 | removeEvent = document.removeEventListener ?
216 | function(elem, type, fn)
217 | {
218 | elem.removeEventListener(type, fn, false);
219 | } :
220 | function(elem, type, fn)
221 | {
222 | elem.detachEvent('on' + type, fn);
223 | },
224 |
225 | Qatrix = {
226 | $: function (id)
227 | {
228 | return document.getElementById(id);
229 | },
230 |
231 | $each: function (haystack, callback)
232 | {
233 | var i = 0,
234 | length = haystack.length,
235 | type = typeof haystack,
236 | is_object = type === 'object',
237 | name;
238 |
239 | if (is_object && (length - 1) in haystack)
240 | {
241 | for (; i < length;)
242 | {
243 | if (callback.call(haystack[i], i, haystack[i++]) === false)
244 | {
245 | break;
246 | }
247 | }
248 | }
249 | else if (is_object)
250 | {
251 | for (name in haystack)
252 | {
253 | callback.call(haystack[name], name, haystack[name]);
254 | }
255 | }
256 | else
257 | {
258 | callback.call(haystack, 0, haystack);
259 | }
260 |
261 | return haystack;
262 | },
263 |
264 | $id: function (id, callback)
265 | {
266 | var match = [],
267 | elem;
268 |
269 | $each(id instanceof Array ? id : id.split(' '), function (i, item)
270 | {
271 | elem = $(item);
272 | if (elem !== null)
273 | {
274 | match.push(elem);
275 | }
276 | });
277 |
278 | return callback ? mapcall(match, callback) : match;
279 | },
280 |
281 | $dom: function (dom, callback)
282 | {
283 | if (callback)
284 | {
285 | dom.length ? mapcall(dom, callback) : callback(dom);
286 | }
287 |
288 | return dom;
289 | },
290 |
291 | $tag: function (elem, name, callback)
292 | {
293 | var stack = [],
294 | nodeList = elem.getElementsByTagName(name),
295 | l = nodeList.length,
296 | i = 0;
297 |
298 | if (l > 0)
299 | {
300 | for ( ;i < l; i++)
301 | {
302 | stack.push( nodeList[ i ] );
303 | }
304 |
305 | return mapcall(stack, callback);
306 | }
307 | else
308 | {
309 | return stack;
310 | }
311 | },
312 |
313 | $class: document.getElementsByClassName ?
314 | function (elem, className, callback)
315 | {
316 | var stack = [],
317 | nodeList = elem.getElementsByClassName(className),
318 | l = nodeList.length,
319 | i = 0;
320 |
321 | if (l > 0)
322 | {
323 | for ( ;i < l; i++)
324 | {
325 | stack.push( nodeList[ i ] );
326 | }
327 |
328 | return mapcall(stack, callback);
329 | }
330 | else
331 | {
332 | return stack;
333 | }
334 | } :
335 | function (elem, className, callback)
336 | {
337 | var match = [],
338 | rclass = new RegExp("(^|\\s)" + className + "(\\s|$)");
339 |
340 | $tag(elem, '*', function (item)
341 | {
342 | if (rclass.test(item.className))
343 | {
344 | match.push(item);
345 | }
346 | });
347 |
348 | return mapcall(match, callback);
349 | },
350 |
351 | $select: document.querySelectorAll ?
352 | function (selector, callback)
353 | {
354 | return mapcall(document.querySelectorAll(selector), callback);
355 | } :
356 | // Hack native CSS selector quering matched element for IE6/7
357 | function (selector, callback)
358 | {
359 | var style = Qatrix.Qselector.styleSheet,
360 | match = [];
361 |
362 | style.addRule(selector, 'q:a');
363 | $tag(document, '*', function (item)
364 | {
365 | if (item.currentStyle.q === 'a')
366 | {
367 | match.push(item);
368 | }
369 | });
370 | style.cssText = '';
371 |
372 | return mapcall(match, callback);
373 | },
374 |
375 | $new: function (tag, properties)
376 | {
377 | var elem = document.createElement(tag);
378 |
379 | if (properties)
380 | {
381 | try
382 | {
383 | $each(properties, function (name, property)
384 | {
385 | switch (name)
386 | {
387 | case 'css':
388 | case 'style':
389 | $css.set(elem, property);
390 | break;
391 |
392 | case 'innerHTML':
393 | case 'html':
394 | $html(elem, property);
395 | break;
396 |
397 | case 'className':
398 | case 'class':
399 | $className.set(elem, property);
400 | break;
401 |
402 | case 'text':
403 | $text(elem, property);
404 | break;
405 |
406 | default:
407 | $attr.set(elem, name, property);
408 | break;
409 | }
410 | });
411 |
412 | return elem;
413 | }
414 | catch (e)
415 | {}
416 | finally
417 | {
418 | // Prevent memory leak
419 | elem = null;
420 | }
421 | }
422 |
423 | return elem;
424 | },
425 |
426 | $string: {
427 | camelCase: function (string)
428 | {
429 | return string.replace('-ms-', 'ms-').replace(rcamelCase, function (match, letter)
430 | {
431 | return (letter + '').toUpperCase();
432 | });
433 | },
434 |
435 | replace: function (string, replacements)
436 | {
437 | for (var key in replacements)
438 | {
439 | string = string.replace(new RegExp(key, 'ig'), replacements[key]);
440 | }
441 |
442 | return string;
443 | },
444 |
445 | slashes: function (string)
446 | {
447 | return $string.replace(string, {
448 | "\\\\": '\\\\',
449 | "\b": '\\b',
450 | "\t": '\\t',
451 | "\n": '\\n',
452 | "\r": '\\r',
453 | '"': '\\"'
454 | });
455 | },
456 |
457 | trim: "".trim ?
458 | function (string)
459 | {
460 | return string.trim();
461 | } :
462 | function (string)
463 | {
464 | return (string + '').replace(/^\s\s*/, '').replace(/\s\s*$/, '');
465 | }
466 | },
467 |
468 | $attr: {
469 | get: function (elem, name)
470 | {
471 | return elem.getAttribute(name);
472 | },
473 |
474 | set: function (elem, name, value)
475 | {
476 | return mapcall(elem, function (elem)
477 | {
478 | elem.setAttribute(name, value);
479 | });
480 | },
481 |
482 | remove: function (elem, name)
483 | {
484 | return mapcall(elem, function (elem)
485 | {
486 | elem.removeAttribute(name);
487 | });
488 | }
489 | },
490 |
491 | $data: {
492 | get: function (elem, name)
493 | {
494 | var value = $attr.get(elem, 'data-' + name);
495 |
496 | return value === "true" ? true :
497 | value === "false" ? false :
498 | value === "null" ? '' :
499 | value === null ? '' :
500 | value === '' ? '' :
501 | !isNaN(parseFloat(value)) && isFinite(value) ? +value :
502 | rbrace.test(value) ? $json.decode(value) :
503 | value;
504 | },
505 |
506 | set: function (elem, name, value)
507 | {
508 | return mapcall(elem, function (elem)
509 | {
510 | value = typeof value === 'object' ? $json.encode(value) : value;
511 | typeof name === 'object' ? $each(name, function (key, value)
512 | {
513 | $attr.set(elem, 'data-' + key, value);
514 | }) : $attr.set(elem, 'data-' + name, value);
515 |
516 | return elem;
517 | });
518 | },
519 |
520 | remove: function (elem, name)
521 | {
522 | return mapcall(elem, function (elem)
523 | {
524 | $attr.remove(elem, 'data-' + name);
525 | });
526 | }
527 | },
528 |
529 | $storage: window.localStorage ?
530 | {
531 | set: function (name, value)
532 | {
533 | localStorage[name] = typeof value === 'object' ? $json.encode(value) : value;
534 | },
535 |
536 | get: function (name)
537 | {
538 | var data = localStorage[name];
539 |
540 | if ($json.isJSON(data))
541 | {
542 | return $json.decode(data);
543 | }
544 |
545 | return data || '';
546 | },
547 |
548 | remove: function (name)
549 | {
550 | localStorage.removeItem(name);
551 |
552 | return true;
553 | }
554 | } :
555 | {
556 | set: function (name, value)
557 | {
558 | value = typeof value === 'object' ? $json.encode(value) : value;
559 | $data.set(Qatrix.storage, name, value);
560 | Qatrix.storage.save('Qstorage');
561 | },
562 |
563 | get: function (name)
564 | {
565 | Qatrix.storage.load('Qstorage');
566 |
567 | return $data.get(Qatrix.storage, name) || '';
568 | },
569 |
570 | remove: function (name)
571 | {
572 | Qatrix.storage.load('Qstorage');
573 | $data.remove(Qatrix.storage, name);
574 |
575 | return true;
576 | }
577 | },
578 |
579 | $event: {
580 | guid: 0,
581 |
582 | global: {},
583 |
584 | handler: {
585 | call: function (event, target, delegate_event, fn)
586 | {
587 | var handler = $event.handler;
588 |
589 | delegate_event.currentTarget = target;
590 |
591 | if (fn === false || fn.call(target, delegate_event) === false)
592 | {
593 | handler.stopPropagation.call(delegate_event);
594 | handler.preventDefault.call(delegate_event);
595 | }
596 | },
597 |
598 | preventDefault: function ()
599 | {
600 | var original = this.originalEvent;
601 |
602 | if (original.preventDefault)
603 | {
604 | original.preventDefault();
605 | }
606 | },
607 |
608 | stopPropagation: function ()
609 | {
610 | var original = this.originalEvent;
611 |
612 | if (original.stopPropagation)
613 | {
614 | original.stopPropagation();
615 | }
616 | },
617 |
618 | stopImmediatePropagation: function()
619 | {
620 | this.stopPropagation();
621 | },
622 |
623 | mouseenter: function (handler)
624 | {
625 | return function (event)
626 | {
627 | var target = event.relatedTarget;
628 |
629 | if (this === target)
630 | {
631 | return;
632 | }
633 |
634 | while (target && target !== this)
635 | {
636 | target = target.parentNode;
637 | }
638 |
639 | if (target === this)
640 | {
641 | return;
642 | }
643 |
644 | handler.call(this, event);
645 | }
646 | }
647 | },
648 |
649 | on: function (context, types, selector, data, fn)
650 | {
651 | return mapcall(context, function (elem)
652 | {
653 | if (elem.nodeType === 3 || elem.nodeType === 8)
654 | {
655 | return false;
656 | }
657 |
658 | if (typeof types === 'object')
659 | {
660 | if (typeof selector !== 'string')
661 | {
662 | data = data || selector;
663 | selector = undefined;
664 | }
665 |
666 | for (type in types)
667 | {
668 | $event.on(elem, type, selector, data, types[type]);
669 | }
670 |
671 | return this;
672 | }
673 |
674 | if (data == null && fn == null)
675 | {
676 | fn = selector;
677 | data = selector = undefined;
678 | }
679 | else if (fn == null)
680 | {
681 | if (typeof selector === 'string')
682 | {
683 | fn = data;
684 | data = undefined;
685 | }
686 | else
687 | {
688 | fn = data;
689 | data = selector;
690 | selector = undefined;
691 | }
692 | }
693 |
694 | if (elem.guid === undefined)
695 | {
696 | $event.guid++;
697 | elem.guid = $event.guid;
698 | $event.global[ $event.guid ] = {};
699 | }
700 |
701 | var guid = elem.guid,
702 | event_key = (selector || '') + types,
703 | events = $event.global[ guid ][ event_key ];
704 |
705 | if (!events)
706 | {
707 | $event.global[ guid ][ event_key ] = {};
708 | }
709 |
710 | delegate_fn = function (event)
711 | {
712 | var delegate_event = {},
713 | match = null,
714 | classSelector,
715 | event_prop = 'altKey bubbles button buttons cancelable relatedTarget clientX clientY ctrlKey fromElement offsetX offsetY pageX pageY screenX screenY shiftKey toElement timeStamp'.split(' '),
716 | target;
717 |
718 | $each(event_prop, function (i, key)
719 | {
720 | if (event[key] !== undefined)
721 | {
722 | delegate_event[key] = event[key];
723 | }
724 | });
725 | delegate_event.originalEvent = event;
726 | delegate_event.preventDefault = $event.handler.preventDefault;
727 | delegate_event.stopPropagation = $event.handler.stopPropagation;
728 | delegate_event.stopImmediatePropagation = $event.handler.stopImmediatePropagation;
729 | delegate_event.delegateTarget = elem;
730 |
731 | delegate_event.data = data;
732 |
733 | target = delegate_event.target = !selector ? elem : event.target || event.srcElement || document;
734 |
735 | delegate_event.which = event.which || event.charCode || event.keyCode;
736 |
737 | delegate_event.metaKey = event.metaKey || event.ctrlKey;
738 |
739 | if (!selector)
740 | {
741 | $event.handler.call(event, target, delegate_event, fn);
742 | }
743 | else
744 | {
745 | classSelector = selector ? selector.replace('.', '') : '';
746 |
747 | for (; target !== elem; target = target.parentNode)
748 | {
749 | if (target === null || target === document.body)
750 | {
751 | return false;
752 | }
753 |
754 | if (target.tagName.toLowerCase() === selector || $className.has(target, classSelector))
755 | {
756 | $event.handler.call(event, target, delegate_event, fn);
757 | }
758 | }
759 | }
760 | };
761 |
762 | if (elem.addEventListener)
763 | {
764 | if (types === 'mouseenter' || types === 'mouseleave')
765 | {
766 | types = types === 'mouseenter' ? 'mouseover' : 'mouseout';
767 | delegate_fn = $event.handler.mouseenter(delegate_fn);
768 | }
769 |
770 | elem.addEventListener(types, delegate_fn, (types === 'blur' || types === 'focus'));
771 | }
772 | else
773 | {
774 | elem.attachEvent('on' + types, delegate_fn);
775 | }
776 |
777 | $event.global[ guid ][ event_key ][ fn + '' ] = delegate_fn;
778 |
779 | return elem;
780 | });
781 | },
782 |
783 | off: function (context, types, selector, fn)
784 | {
785 | if (typeof types === 'object')
786 | {
787 | for (type in types)
788 | {
789 | $event.off(context, type, types[type]);
790 | }
791 | return this;
792 | }
793 |
794 | if (fn == null)
795 | {
796 | fn = selector;
797 | selector = null;
798 | }
799 |
800 | var guid = context.guid,
801 | event_key = (selector || '') + types;
802 | fn_key = fn + '';
803 |
804 | if (!fn)
805 | {
806 | $each($event.global[ guid ][ event_key ], function (i, item)
807 | {
808 | removeEvent(context, types, item);
809 | });
810 | delete $event.global[ guid ][ event_key ];
811 | }
812 | else
813 | {
814 | removeEvent(context, types, $event.global[ guid ][ event_key ][ fn_key ]);
815 | delete $event.global[ guid ][ event_key ][ fn_key ];
816 | }
817 | }
818 | },
819 |
820 | $clear: function (timer)
821 | {
822 | if (timer)
823 | {
824 | clearTimeout(timer);
825 | clearInterval(timer);
826 | }
827 |
828 | return null;
829 | },
830 |
831 | $ready: function (callback)
832 | {
833 | if (document.readyState === 'complete')
834 | {
835 | return setTimeout(callback, 1);
836 | }
837 | if (document.addEventListener)
838 | {
839 | readyList.push(callback);
840 | document.addEventListener('DOMContentLoaded', ready, false);
841 |
842 | return;
843 | }
844 | // Hack IE DOM for ready event
845 | var domready = function ()
846 | {
847 | try
848 | {
849 | docElem.doScroll('left');
850 | }
851 | catch (e)
852 | {
853 | setTimeout(domready, 1);
854 | return;
855 | }
856 | callback();
857 | };
858 | domready();
859 | },
860 |
861 | $css: {
862 | get: function (elem, name)
863 | {
864 | if (typeof name === 'object')
865 | {
866 | var haystack = {};
867 |
868 | $each(name, function (i, property)
869 | {
870 | haystack[property] = $style.get(elem, property);
871 | });
872 |
873 | return haystack;
874 | }
875 |
876 | return $style.get(elem, name);
877 | },
878 |
879 | set: function (elem, name, value)
880 | {
881 | return mapcall(elem, function (elem)
882 | {
883 | typeof name === 'object' ? $each(name, function (propertyName, value)
884 | {
885 | $style.set(elem, $string.camelCase(propertyName), $css.fix(propertyName, value));
886 | }) : $style.set(elem, $string.camelCase(name), $css.fix(name, value));
887 |
888 | return elem;
889 | });
890 | },
891 |
892 | number: {
893 | 'fontWeight': true,
894 | 'lineHeight': true,
895 | 'opacity': true,
896 | 'zIndex': true
897 | },
898 |
899 | unit: function (name, value)
900 | {
901 | if ($css.number[name])
902 | {
903 | return '';
904 | }
905 | var unit = (value + '').replace(rnum, '');
906 |
907 | return unit === '' ? 'px' : unit;
908 | },
909 |
910 | fix: function (name, value)
911 | {
912 | if (typeof value === 'number' && !$css.number[name])
913 | {
914 | value += 'px';
915 | }
916 |
917 | return value === null && isNaN(value) ? false : value;
918 | }
919 | },
920 |
921 | $style: {
922 | get: window.getComputedStyle ?
923 | function (elem, property)
924 | {
925 | if (elem !== null)
926 | {
927 | var value = document.defaultView.getComputedStyle(elem, null).getPropertyValue(property);
928 |
929 | return value === 'auto' || value === '' ? 0 : value;
930 | }
931 |
932 | return false;
933 | } :
934 | function (elem, property)
935 | {
936 | if (elem !== null)
937 | {
938 | var value = property === 'opacity' ? ropacity.test(elem.currentStyle['filter']) ?
939 | (0.01 * parseFloat(RegExp.$1)) + '' :
940 | 1 : elem.currentStyle[$string.camelCase(property)];
941 |
942 | return value === 'auto' ? 0 : value;
943 | }
944 |
945 | return false;
946 | },
947 |
948 | set: docElem.style.opacity !== undefined ?
949 | function (elem, name, value)
950 | {
951 | return mapcall(elem, function (elem)
952 | {
953 | elem.style[name] = value;
954 |
955 | return true;
956 | });
957 | } :
958 | function (elem, name, value)
959 | {
960 | return mapcall(elem, function (elem)
961 | {
962 | if (!elem.currentStyle || !elem.currentStyle.hasLayout)
963 | {
964 | elem.style.zoom = 1;
965 | }
966 |
967 | if (name === 'opacity')
968 | {
969 | elem.style.filter = 'alpha(opacity=' + value * 100 + ')';
970 | elem.style.zoom = 1;
971 | }
972 | else
973 | {
974 | elem.style[name] = value;
975 | }
976 |
977 | return true;
978 | });
979 | }
980 | },
981 |
982 | $pos: function (elem, x, y)
983 | {
984 | return mapcall(elem, function (elem)
985 | {
986 | $style.set(elem, 'left', x + 'px');
987 | $style.set(elem, 'top', y + 'px');
988 |
989 | return elem;
990 | });
991 | },
992 |
993 | $offset: function (elem)
994 | {
995 | var body = document.body,
996 | box = elem.getBoundingClientRect();
997 |
998 | return {
999 | top: box.top + (window.scrollY || body.parentNode.scrollTop || elem.scrollTop) - (docElem.clientTop || body.clientTop || 0),
1000 | left: box.left + (window.scrollX || body.parentNode.scrollLeft || elem.scrollLeft) - (docElem.clientLeft || body.clientLeft || 0),
1001 | width: elem.offsetWidth,
1002 | height: elem.offsetHeight
1003 | };
1004 | },
1005 |
1006 | $append: function (elem, node)
1007 | {
1008 | return mapcall(elem, function (elem)
1009 | {
1010 | return elem.appendChild(nodeManip(elem, node));
1011 | });
1012 | },
1013 |
1014 | $prepend: function (elem, node)
1015 | {
1016 | return mapcall(elem, function (elem)
1017 | {
1018 | return elem.firstChild ?
1019 | elem.insertBefore(nodeManip(elem, node), elem.firstChild) :
1020 | elem.appendChild(nodeManip(elem, node));
1021 | });
1022 | },
1023 |
1024 | $before: function (elem, node)
1025 | {
1026 | return mapcall(elem, function (elem)
1027 | {
1028 | return elem.parentNode.insertBefore(nodeManip(elem, node), elem);
1029 | });
1030 | },
1031 |
1032 | $after: function (elem, node)
1033 | {
1034 | return mapcall(elem, function (elem)
1035 | {
1036 | return elem.nextSibling ?
1037 | elem.parentNode.insertBefore(nodeManip(elem, node), elem.nextSibling) :
1038 | elem.parentNode.appendChild(nodeManip(elem, node));
1039 | });
1040 | },
1041 |
1042 | $remove: function (elem)
1043 | {
1044 | return mapcall(elem, function (elem)
1045 | {
1046 | $empty(elem);
1047 | if (elem.guid !== undefined)
1048 | {
1049 | delete $event.global[elem.guid];
1050 | }
1051 |
1052 | return elem !== null && elem.parentNode ? elem.parentNode.removeChild(elem) : elem;
1053 | });
1054 | },
1055 |
1056 | $empty: function (elem)
1057 | {
1058 | return mapcall(elem, function (elem)
1059 | {
1060 | while (elem.firstChild)
1061 | {
1062 | if (elem.nodeType === 1 && elem.guid !== undefined)
1063 | {
1064 | delete $event.global[elem.guid];
1065 | }
1066 | elem.removeChild(elem.firstChild);
1067 | }
1068 |
1069 | return elem;
1070 | });
1071 | },
1072 |
1073 | $html: function (elem, html)
1074 | {
1075 | return mapcall(elem, function (elem)
1076 | {
1077 | if (html)
1078 | {
1079 | try
1080 | {
1081 | elem.innerHTML = html;
1082 | }
1083 | catch (e)
1084 | {
1085 | $append($empty(elem), html);
1086 | }
1087 | return elem;
1088 | }
1089 |
1090 | return elem.nodeType === 1 ? elem.innerHTML : null;
1091 | });
1092 | },
1093 |
1094 | $text: function (elem, text)
1095 | {
1096 | // Retrieve the text value
1097 | // textContent and innerText returns different results from different browser
1098 | // So it have to rewrite the process method
1099 | return mapcall(elem, function (elem)
1100 | {
1101 | if (text)
1102 | {
1103 | // Set text node.
1104 | $empty(elem);
1105 | elem.appendChild(document.createTextNode(text));
1106 |
1107 | return elem;
1108 | }
1109 | else
1110 | {
1111 | var rtext = '',
1112 | textContent = elem.textContent,
1113 | nodeType;
1114 |
1115 | // If the content of elem is text only
1116 | if ((textContent || elem.innerText) === elem.innerHTML)
1117 | {
1118 | rtext = textContent ? $string.trim(elem.textContent.replace(rbline, '')) : elem.innerText.replace(rline, '');
1119 | }
1120 | else
1121 | {
1122 | for (elem = elem.firstChild; elem; elem = elem.nextSibling)
1123 | {
1124 | nodeType = elem.nodeType;
1125 |
1126 | if (nodeType === 3 && $string.trim(elem.nodeValue) !== '')
1127 | {
1128 | rtext += elem.nodeValue.replace(rbline, '') + (elem.nextSibling && elem.nextSibling.tagName && elem.nextSibling.tagName.toLowerCase() !== 'br' ? "\n" : '');
1129 | }
1130 |
1131 | if (nodeType === 1 || nodeType === 2)
1132 | {
1133 | rtext += $text(elem) + ($style.get(elem, 'display') === 'block' || elem.tagName.toLowerCase() === 'br' ? "\n" : '');
1134 | }
1135 | }
1136 | }
1137 |
1138 | return rtext;
1139 | }
1140 | });
1141 | },
1142 |
1143 | $className: {
1144 | add: function (elem, name)
1145 | {
1146 | return mapcall(elem, function (elem)
1147 | {
1148 | if (elem.className === '')
1149 | {
1150 | elem.className = name;
1151 | }
1152 | else
1153 | {
1154 | var ori = elem.className,
1155 | nclass = [];
1156 |
1157 | $each(name.split(rspace), function (i, item)
1158 | {
1159 | if (!new RegExp('\\b(' + item + ')\\b').test(ori))
1160 | {
1161 | nclass.push(' ' + item);
1162 | }
1163 | });
1164 | elem.className += nclass.join('');
1165 | }
1166 |
1167 | return elem;
1168 | });
1169 | },
1170 |
1171 | set: function (elem, name)
1172 | {
1173 | return mapcall(elem, function (elem)
1174 | {
1175 | elem.className = name;
1176 |
1177 | return elem;
1178 | });
1179 | },
1180 |
1181 | has: function (elem, name)
1182 | {
1183 | return new RegExp('\\b(' + name.split(rspace).join('|') + ')\\b').test(elem.className);
1184 | },
1185 |
1186 | remove: function (elem, name)
1187 | {
1188 | return mapcall(elem, function (elem)
1189 | {
1190 | elem.className = name ? $string.trim(
1191 | elem.className.replace(
1192 | new RegExp('\\b(' + name.split(rspace).join('|') + ')\\b'), '')
1193 | .split(rspace)
1194 | .join(' ')
1195 | ) : '';
1196 |
1197 | return elem;
1198 | });
1199 | }
1200 | },
1201 |
1202 | $hide: function (elem, duration, callback)
1203 | {
1204 | displayElem(elem, 'hide', duration, callback);
1205 | },
1206 |
1207 | $show: function (elem, duration, callback)
1208 | {
1209 | displayElem(elem, 'show', duration, callback);
1210 | },
1211 |
1212 | $toggle: function (elem, duration, callback)
1213 | {
1214 | return mapcall(elem, function (elem)
1215 | {
1216 | $style.get(elem, 'display') === 'none' ?
1217 | $show(elem, duration, callback) :
1218 | $hide(elem, duration, callback);
1219 | });
1220 | },
1221 |
1222 | $animate: (function ()
1223 | {
1224 | // Use CSS3 native transition for animation as possible
1225 | var style = docElem.style;
1226 |
1227 | return (
1228 | style.webkitTransition !== undefined ||
1229 | style.MozTransition !== undefined ||
1230 | style.OTransition !== undefined ||
1231 | style.msTransition !== undefined ||
1232 | style.transition !== undefined
1233 | );
1234 | }()) ?
1235 | (function ()
1236 | {
1237 | var style = docElem.style,
1238 | prefix_name = style.webkitTransition !== undefined ? 'Webkit' :
1239 | style.MozTransition !== undefined ? 'Moz' :
1240 | style.OTransition !== undefined ? 'O' :
1241 | style.msTransition !== undefined ? 'ms' : '',
1242 | transition_name = prefix_name + 'Transition';
1243 |
1244 | return function (elem, properties, duration, callback)
1245 | {
1246 | return mapcall(elem, function (elem)
1247 | {
1248 | var css_value = [],
1249 | css_name = [],
1250 | unit = [],
1251 | css_style = [],
1252 | style = elem.style,
1253 | css, offset;
1254 |
1255 | duration = duration || 300;
1256 |
1257 | for (css in properties)
1258 | {
1259 | css_name[css] = $string.camelCase(css);
1260 | if (properties[css].from !== undefined)
1261 | {
1262 | properties[css].to = properties[css].to || 0;
1263 | css_value[css] = !$css.number[css] ? parseInt(properties[css].to, 10) : properties[css].to;
1264 | unit[css] = $css.unit(css, properties[css].to);
1265 | $style.set(elem, css_name[css], parseInt(properties[css].from, 10) + unit[css]);
1266 | }
1267 | else
1268 | {
1269 | css_value[css] = !$css.number[css] ? parseInt(properties[css], 10) : properties[css];
1270 | unit[css] = $css.unit(css, properties[css]);
1271 | $style.set(elem, css_name[css], $style.get(elem, css_name[css]));
1272 | }
1273 | css_style.push(css);
1274 | }
1275 |
1276 | setTimeout(function ()
1277 | {
1278 | style[transition_name] = 'all ' + duration + 'ms';
1279 |
1280 | $each(css_style, function (i, css)
1281 | {
1282 | style[css_name[css]] = css_value[css] + unit[css];
1283 | });
1284 | }, 15);
1285 |
1286 | // Animation completed
1287 | setTimeout(function ()
1288 | {
1289 | // Clear up CSS transition property
1290 | style[transition_name] = '';
1291 |
1292 | if (callback)
1293 | {
1294 | callback.call(elem);
1295 | }
1296 | }, duration);
1297 |
1298 | return elem;
1299 | });
1300 | }
1301 | })() :
1302 | function (elem, properties, duration, callback)
1303 | {
1304 | return mapcall(elem, function (elem)
1305 | {
1306 | var step = 0,
1307 | i = 0,
1308 | j = 0,
1309 | length = 0,
1310 | p = 30,
1311 | css_to_value = [],
1312 | css_from_value = [],
1313 | css_name = [],
1314 | css_unit = [],
1315 | css_style = [],
1316 | property_value, css, offset, timer;
1317 |
1318 | duration = duration || 300;
1319 |
1320 | for (css in properties)
1321 | {
1322 | css_name.push($string.camelCase(css));
1323 | if (properties[css].from !== undefined)
1324 | {
1325 | property_value = properties[css].to;
1326 | css_from_value.push(!$css.number[css] ? parseInt(properties[css].from, 10) : properties[css].from);
1327 | $style.set(elem, css_name[i], css_from_value[i] + $css.unit(css, property_value));
1328 | }
1329 | else
1330 | {
1331 | property_value = properties[css];
1332 | css_from_value.push(parseInt($style.get(elem, $string.camelCase(css)), 10));
1333 | }
1334 | css_to_value.push(!$css.number[css] ? parseInt(property_value, 10) : property_value);
1335 | css_unit.push($css.unit(css, property_value));
1336 | i++;
1337 | length++;
1338 | }
1339 | // Pre-calculation for CSS value
1340 | for (j = 0; j < p; j++)
1341 | {
1342 | css_style[j] = [];
1343 | for (i = 0; i < length; i++)
1344 | {
1345 | css_style[j][css_name[i]] =
1346 | (css_from_value[i] + (css_to_value[i] - css_from_value[i]) / p * j) +
1347 | (css_name[i] === 'opacity' ? '' : css_unit[i]);
1348 | }
1349 | }
1350 |
1351 | for (; i < p; i++)
1352 | {
1353 | timer = setTimeout(function ()
1354 | {
1355 | for (i = 0; i < length; i++)
1356 | {
1357 | $style.set(elem, css_name[i], css_style[step][css_name[i]]);
1358 | }
1359 | step++;
1360 | }, (duration / p) * i);
1361 | }
1362 |
1363 | setTimeout(function ()
1364 | {
1365 | for (i = 0; i < length; i++)
1366 | {
1367 | $style.set(elem, css_name[i], css_to_value[i] + css_unit[i]);
1368 | }
1369 | if (callback)
1370 | {
1371 | callback.call(elem);
1372 | }
1373 | }, duration);
1374 |
1375 | return elem;
1376 | });
1377 | },
1378 |
1379 | $fadeout: function (elem, duration, callback)
1380 | {
1381 | return mapcall(elem, function (elem)
1382 | {
1383 | $animate(elem, {
1384 | 'opacity': {
1385 | from: 1,
1386 | to: 0
1387 | }
1388 | }, duration || 500, callback);
1389 | });
1390 | },
1391 |
1392 | $fadein: function (elem, duration, callback)
1393 | {
1394 | return mapcall(elem, function (elem)
1395 | {
1396 | $animate(elem, {
1397 | 'opacity': {
1398 | from: 0,
1399 | to: 1
1400 | }
1401 | }, duration || 500, callback);
1402 | });
1403 | },
1404 |
1405 | $cookie: {
1406 | get: function (key)
1407 | {
1408 | var cookies = document.cookie.split('; '),
1409 | i = 0,
1410 | l = cookies.length,
1411 | temp, value;
1412 |
1413 | for (; i < l; i++)
1414 | {
1415 | temp = cookies[i].split('=');
1416 | if (temp[0] === key)
1417 | {
1418 | value = decodeURIComponent(temp[1]);
1419 |
1420 | return $json.isJSON(value) ? $json.decode(value) : value + '';
1421 | }
1422 | }
1423 |
1424 | return null;
1425 | },
1426 |
1427 | set: function (key, value, expires)
1428 | {
1429 | if (typeof key === 'object')
1430 | {
1431 | expires = value;
1432 |
1433 | return $each(key, function (name, value)
1434 | {
1435 | $cookie.set(name, value, expires);
1436 | });
1437 | }
1438 |
1439 | var today = new Date();
1440 |
1441 | today.setTime(today.getTime());
1442 | expires = expires ? ';expires=' + new Date(today.getTime() + expires * 86400000).toGMTString() : '';
1443 | value = typeof value === 'object' ? $json.encode(value) : value;
1444 |
1445 | return document.cookie = key + '=' + $url(value) + expires + ';path=/';
1446 | },
1447 |
1448 | remove: function ()
1449 | {
1450 | $each(arguments, function (i, key)
1451 | {
1452 | $cookie.set(key, '', -1);
1453 | });
1454 |
1455 | return true;
1456 | }
1457 | },
1458 |
1459 | $json: {
1460 | decode: window.JSON ?
1461 | function (data)
1462 | {
1463 | return $json.isJSON(data) ? JSON.parse($string.trim(data)) : false;
1464 | } :
1465 | function (data)
1466 | {
1467 | return $json.isJSON(data) ? (new Function('return ' + $string.trim(data)))() : false;
1468 | },
1469 |
1470 | encode: window.JSON ?
1471 | function (data)
1472 | {
1473 | return JSON.stringify(data);
1474 | } :
1475 | function (data)
1476 | {
1477 | function stringify(data)
1478 | {
1479 | var temp = [],
1480 | i, type, value, rvalue;
1481 |
1482 | for (i in data)
1483 | {
1484 | value = data[i];
1485 | type = typeof value;
1486 |
1487 | if (type === 'undefined')
1488 | {
1489 | return;
1490 | }
1491 |
1492 | if (type !== 'function')
1493 | {
1494 | switch (type)
1495 | {
1496 | case 'object':
1497 | rvalue = value === null ? value :
1498 | // For ISO date format
1499 | value.getDay ?
1500 | '"' + (1e3 - ~value.getUTCMonth() * 10 + value.toUTCString() + 1e3 + value / 1)
1501 | .replace(/1(..).*?(\d\d)\D+(\d+).(\S+).*(...)/, '$3-$1-$2T$4.$5Z') + '"' :
1502 | // For Array
1503 | value.length ? '[' + (function ()
1504 | {
1505 | var rdata = [];
1506 | $each(value, function (i, item)
1507 | {
1508 | rdata.push((typeof item === 'string' ? '"' + $string.slashes(item) + '"' : item));
1509 | });
1510 |
1511 | return rdata.join(',');
1512 | })() + ']' :
1513 | // For Object
1514 | $json.encode(value);
1515 | break;
1516 |
1517 | case 'number':
1518 | rvalue = !isFinite(value) ? null : value;
1519 | break;
1520 |
1521 | case 'boolean':
1522 | case 'null':
1523 | rvalue = value;
1524 | break;
1525 |
1526 | case 'string':
1527 | rvalue = '"' + $string.slashes(value) + '"';
1528 | break;
1529 | }
1530 | temp.push('"' + i + '"' + ':' + rvalue);
1531 | }
1532 | }
1533 |
1534 | return temp.join(',');
1535 | }
1536 |
1537 | return '{' + stringify(data) + '}';
1538 | },
1539 |
1540 | isJSON: function (string)
1541 | {
1542 | return typeof string === 'string' && $string.trim(string) !== '' ?
1543 | rvalidchars.test(string
1544 | .replace(rvalidescape, '@')
1545 | .replace(rvalidtokens, ']')
1546 | .replace(rvalidbraces, '')) :
1547 | false;
1548 | }
1549 | },
1550 |
1551 | $ajax: function (url, options)
1552 | {
1553 | if (typeof url === 'object')
1554 | {
1555 | options = url;
1556 | url = undefined;
1557 | }
1558 |
1559 | options = options || {};
1560 |
1561 | var request = window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest(),
1562 | url = url || options.url,
1563 | param = [],
1564 | response,
1565 | data;
1566 |
1567 | if (options.data)
1568 | {
1569 | $each(options.data, function (key, value)
1570 | {
1571 | param.push(addParam(key, value));
1572 | });
1573 | }
1574 | data = param.join('&').replace(/%20/g, '+');
1575 |
1576 | if (options.type === 'GET')
1577 | {
1578 | request.open('GET', url + (rquery.test(url) ? '&' : '?') + data, true);
1579 | data = null;
1580 | }
1581 | else
1582 | {
1583 | request.open(options.type || 'POST', url, true);
1584 | }
1585 |
1586 | request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
1587 |
1588 | if (options.header)
1589 | {
1590 | $each(options.header, function (key, value)
1591 | {
1592 | request.setRequestHeader(key, value);
1593 | });
1594 | }
1595 |
1596 | request.send(data);
1597 | request.onreadystatechange = function ()
1598 | {
1599 | if (request.readyState === 4)
1600 | {
1601 | if (request.status === 200 && options.success)
1602 | {
1603 | data = request.responseText;
1604 | options.success(data !== '' && $json.isJSON(data) ? $json.decode(data) : data);
1605 | }
1606 | else
1607 | {
1608 | if (options.error)
1609 | {
1610 | options.error(request.status);
1611 | }
1612 | }
1613 | }
1614 | };
1615 | },
1616 |
1617 | $require: function (context, callback)
1618 | {
1619 | var queue = [],
1620 | item;
1621 |
1622 | $each(context, function (i, src)
1623 | {
1624 | if (!require_loaded[src])
1625 | {
1626 | require_loaded[src] = true;
1627 | queue.push(src);
1628 | item = /\.css[^\.]*$/ig.test(src) ?
1629 |
1630 | $new('link', {
1631 | 'type': 'text/css',
1632 | 'rel': 'stylesheet',
1633 | 'href': src
1634 | }) :
1635 |
1636 | $new('script', {
1637 | 'type': 'text/javascript',
1638 | 'async': true,
1639 | 'src': src
1640 | });
1641 |
1642 | item.onload = item.onreadystatechange = function (event)
1643 | {
1644 | if (event.type === 'load' || (/loaded|complete/.test(item.readyState)))
1645 | {
1646 | item.onload = item.onreadystatechange = null;
1647 | queue.splice(queue.indexOf(src), 1);
1648 | if (queue.length === 0 && callback)
1649 | {
1650 | callback();
1651 | }
1652 | }
1653 | };
1654 | $append(document.head || $tag(document, 'head')[0] || docElem, item);
1655 | }
1656 | });
1657 | },
1658 |
1659 | $template: function (template, data)
1660 | {
1661 | var content = template_cache[template];
1662 |
1663 | if (!content)
1664 | {
1665 | content = "var s='';s+=\'" +
1666 | template.replace(/[\r\t\n]/g, " ")
1667 | .split("'").join("\\'")
1668 | .replace(/\{\{#([\w]*)\}\}(.*)\{\{\/(\1)\}\}/ig, function (match, $1, $2)
1669 | {
1670 | return "\';var i=0,l=data." + $1 + ".length,d=data." + $1 + ";for(;i -1;
1701 | }
1702 |
1703 | for (; i < 12; i++)
1704 | {
1705 | browser['msie' + i] = ua.indexOf('msie ' + i) > -1;
1706 | }
1707 |
1708 | browser.is = function (keyword)
1709 | {
1710 | return new RegExp(keyword, 'ig').test(ua);
1711 | };
1712 |
1713 | return browser;
1714 | }())
1715 | };
1716 |
1717 | // Expose Qatrix functions to global
1718 | for (var fn in Qatrix)
1719 | {
1720 | window[fn] = Qatrix[fn];
1721 | }
1722 |
1723 | Qatrix.version = version;
1724 | window.Qatrix = Qatrix;
1725 |
1726 | $ready(function ()
1727 | {
1728 | // For hack CSS selector
1729 | if (!document.querySelectorAll)
1730 | {
1731 | Qatrix.Qselector = $append(document.body, $new('style'));
1732 | }
1733 | // For hack storage
1734 | if (!window.localStorage)
1735 | {
1736 | Qatrix.storage = $append(document.body, $new('link', {
1737 | 'style': {
1738 | 'behavior': 'url(#default#userData)'
1739 | }
1740 | }));
1741 | }
1742 | });
1743 |
1744 | // Define Qatrix as an AMD module
1745 | if (typeof define === 'function' && define.amd)
1746 | {
1747 | define('qatrix', [], Qatrix);
1748 | }
1749 |
1750 | // Create a shortcut for compression
1751 | })(window, document);
--------------------------------------------------------------------------------