Upgrade to ExtJS 3.0.0 - Released 07/06/2009
[extjs.git] / docs / source / ext-air.html
1 <html>\r
2 <head>\r
3   <title>The source code</title>\r
4     <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />\r
5     <script type="text/javascript" src="../resources/prettify/prettify.js"></script>\r
6 </head>\r
7 <body  onload="prettyPrint();">\r
8     <pre class="prettyprint lang-js">/*\r
9  * Ext JS Library 2.0.1\r
10  * Copyright(c) 2006-2008, Ext JS, LLC.\r
11  * licensing@extjs.com\r
12  * \r
13  * http://extjs.com/license\r
14  */\r
15 \r
16 \r
17 Ext.namespace('Ext.air', 'Ext.sql');\r
18 \r
19 Ext.Template.prototype.compile = function() {\r
20         var fm = Ext.util.Format;\r
21         var useF = this.disableFormats !== true;\r
22         
23         var prevOffset = 0;\r
24         var arr = [];\r
25         var tpl = this;\r
26         var fn = function(m, name, format, args, offset, s){\r
27                 if (prevOffset != offset) {\r
28                         var action = {type: 1, value: s.substr(prevOffset, offset - prevOffset)};\r
29                         arr.push(action);\r
30                 }\r
31                 prevOffset = offset + m.length;\r
32                 if(format && useF){\r
33                                 if (args) {\r
34                                         var re = /^\s*['"](.*)["']\s*$/;\r
35                                         args = args.split(/,(?=(?:[^"]*"[^"]*")*(?![^"]*"))/);\r
36                                         for(var i = 0, len = args.length; i < len; i++){\r
37                                                 args[i] = args[i].replace(re, "$1");\r
38                                         }\r
39                                         args = [''].concat(args);\r
40                                 } else {\r
41                                                 args = [''];\r
42                                 }\r
43                         if(format.substr(0, 5) != "this."){\r
44                                 var action = {type: 3, value:name, format: fm[format], args: args, scope: fm};\r
45                                 arr.push(action);                                       \r
46                         }else{\r
47                                 var action = {type: 3, value:name, format:tpl[format.substr(5)], args:args, scope: tpl};\r
48                                 arr.push(action);                                       \r
49                         }\r
50                 }else{\r
51                         var action  = {type: 2, value: name};\r
52                         arr.push(action);                               \r
53                 }\r
54                 return m;\r
55         };\r
56         \r
57         var s = this.html.replace(this.re, fn);\r
58         if (prevOffset != (s.length - 1)) {\r
59                 var action = {type: 1, value: s.substr(prevOffset, s.length - prevOffset)};\r
60                 arr.push(action);\r
61         }\r
62 \r
63         this.compiled = function(values) {\r
64                 function applyValues(el) {\r
65                         switch (el.type) {\r
66                                         case 1:\r
67                                                         return el.value;\r
68                                         case 2:\r
69                                                         return (values[el.value] ? values[el.value] : '');\r
70                                         default:\r
71                                                         el.args[0] = values[el.value];\r
72                                                         return el.format.apply(el.scope, el.args);\r
73                         }\r
74                 }       \r
75                 return arr.map(applyValues).join('');\r
76         }\r
77         return this;\r
78 };\r
79 \r
80 Ext.Template.prototype.call = function(fnName, value, allValues){\r
81     return this[fnName](value, allValues);\r
82 }\r
83 \r
84 \r
85 Ext.DomQuery = function(){\r
86     var cache = {}, simpleCache = {}, valueCache = {};\r
87     var nonSpace = /\S/;\r
88     var trimRe = /^\s+|\s+$/g;\r
89     var tplRe = /\{(\d+)\}/g;\r
90     var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;\r
91     var tagTokenRe = /^(#)?([\w-\*]+)/;\r
92     var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;\r
93 \r
94     function child(p, index){\r
95         var i = 0;\r
96         var n = p.firstChild;\r
97         while(n){\r
98             if(n.nodeType == 1){\r
99                if(++i == index){\r
100                    return n;\r
101                }\r
102             }\r
103             n = n.nextSibling;\r
104         }\r
105         return null;\r
106     };\r
107 \r
108     function next(n){\r
109         while((n = n.nextSibling) && n.nodeType != 1);\r
110         return n;\r
111     };\r
112 \r
113     function prev(n){\r
114         while((n = n.previousSibling) && n.nodeType != 1);\r
115         return n;\r
116     };\r
117 \r
118     function children(d){\r
119         var n = d.firstChild, ni = -1;\r
120             while(n){\r
121                 var nx = n.nextSibling;\r
122                 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){\r
123                     d.removeChild(n);\r
124                 }else{\r
125                     n.nodeIndex = ++ni;\r
126                 }\r
127                 n = nx;\r
128             }\r
129             return this;\r
130         };\r
131 \r
132     function byClassName(c, a, v){\r
133         if(!v){\r
134             return c;\r
135         }\r
136         var r = [], ri = -1, cn;\r
137         for(var i = 0, ci; ci = c[i]; i++){\r
138             if((' '+ci.className+' ').indexOf(v) != -1){\r
139                 r[++ri] = ci;\r
140             }\r
141         }\r
142         return r;\r
143     };\r
144 \r
145     function attrValue(n, attr){\r
146         if(!n.tagName && typeof n.length != "undefined"){\r
147             n = n[0];\r
148         }\r
149         if(!n){\r
150             return null;\r
151         }\r
152         if(attr == "for"){\r
153             return n.htmlFor;\r
154         }\r
155         if(attr == "class" || attr == "className"){\r
156             return n.className;\r
157         }\r
158         return n.getAttribute(attr) || n[attr];\r
159 \r
160     };\r
161 \r
162     function getNodes(ns, mode, tagName){\r
163         var result = [], ri = -1, cs;\r
164         if(!ns){\r
165             return result;\r
166         }\r
167         tagName = tagName || "*";\r
168         if(typeof ns.getElementsByTagName != "undefined"){\r
169             ns = [ns];\r
170         }\r
171         if(!mode){\r
172             for(var i = 0, ni; ni = ns[i]; i++){\r
173                 cs = ni.getElementsByTagName(tagName);\r
174                 for(var j = 0, ci; ci = cs[j]; j++){\r
175                     result[++ri] = ci;\r
176                 }\r
177             }\r
178         }else if(mode == "/" || mode == ">"){\r
179             var utag = tagName.toUpperCase();\r
180             for(var i = 0, ni, cn; ni = ns[i]; i++){\r
181                 cn = ni.children || ni.childNodes;\r
182                 for(var j = 0, cj; cj = cn[j]; j++){\r
183                     if(cj.nodeName == utag || cj.nodeName == tagName  || tagName == '*'){\r
184                         result[++ri] = cj;\r
185                     }\r
186                 }\r
187             }\r
188         }else if(mode == "+"){\r
189             var utag = tagName.toUpperCase();\r
190             for(var i = 0, n; n = ns[i]; i++){\r
191                 while((n = n.nextSibling) && n.nodeType != 1);\r
192                 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){\r
193                     result[++ri] = n;\r
194                 }\r
195             }\r
196         }else if(mode == "~"){\r
197             for(var i = 0, n; n = ns[i]; i++){\r
198                 while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));\r
199                 if(n){\r
200                     result[++ri] = n;\r
201                 }\r
202             }\r
203         }\r
204         return result;\r
205     };\r
206 \r
207     function concat(a, b){\r
208         if(b.slice){\r
209             return a.concat(b);\r
210         }\r
211         for(var i = 0, l = b.length; i < l; i++){\r
212             a[a.length] = b[i];\r
213         }\r
214         return a;\r
215     }\r
216 \r
217     function byTag(cs, tagName){\r
218         if(cs.tagName || cs == document){\r
219             cs = [cs];\r
220         }\r
221         if(!tagName){\r
222             return cs;\r
223         }\r
224         var r = [], ri = -1;\r
225         tagName = tagName.toLowerCase();\r
226         for(var i = 0, ci; ci = cs[i]; i++){\r
227             if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){\r
228                 r[++ri] = ci;\r
229             }\r
230         }\r
231         return r;\r
232     };\r
233 \r
234     function byId(cs, attr, id){\r
235         if(cs.tagName || cs == document){\r
236             cs = [cs];\r
237         }\r
238         if(!id){\r
239             return cs;\r
240         }\r
241         var r = [], ri = -1;\r
242         for(var i = 0,ci; ci = cs[i]; i++){\r
243             if(ci && ci.id == id){\r
244                 r[++ri] = ci;\r
245                 return r;\r
246             }\r
247         }\r
248         return r;\r
249     };\r
250 \r
251     function byAttribute(cs, attr, value, op, custom){\r
252         var r = [], ri = -1, st = custom=="{";\r
253         var f = Ext.DomQuery.operators[op];\r
254         for(var i = 0, ci; ci = cs[i]; i++){\r
255             var a;\r
256             if(st){\r
257                 a = Ext.DomQuery.getStyle(ci, attr);\r
258             }\r
259             else if(attr == "class" || attr == "className"){\r
260                 a = ci.className;\r
261             }else if(attr == "for"){\r
262                 a = ci.htmlFor;\r
263             }else if(attr == "href"){\r
264                 a = ci.getAttribute("href", 2);\r
265             }else{\r
266                 a = ci.getAttribute(attr);\r
267             }\r
268             if((f && f(a, value)) || (!f && a)){\r
269                 r[++ri] = ci;\r
270             }\r
271         }\r
272         return r;\r
273     };\r
274 \r
275     function byPseudo(cs, name, value){\r
276         return Ext.DomQuery.pseudos[name](cs, value);\r
277     };\r
278 \r
279  \r
280     
281     
282     eval("var batch = 30803;");\r
283 \r
284     var key = 30803;\r
285 \r
286     function nodup(cs){\r
287         if(!cs){\r
288             return [];\r
289         }\r
290         var len = cs.length, c, i, r = cs, cj, ri = -1;\r
291         if(!len || typeof cs.nodeType != "undefined" || len == 1){\r
292             return cs;\r
293         }\r
294         var d = ++key;\r
295         cs[0]._nodup = d;\r
296         for(i = 1; c = cs[i]; i++){\r
297             if(c._nodup != d){\r
298                 c._nodup = d;\r
299             }else{\r
300                 r = [];\r
301                 for(var j = 0; j < i; j++){\r
302                     r[++ri] = cs[j];\r
303                 }\r
304                 for(j = i+1; cj = cs[j]; j++){\r
305                     if(cj._nodup != d){\r
306                         cj._nodup = d;\r
307                         r[++ri] = cj;\r
308                     }\r
309                 }\r
310                 return r;\r
311             }\r
312         }\r
313         return r;\r
314     }\r
315 \r
316     function quickDiff(c1, c2){\r
317         var len1 = c1.length;\r
318         if(!len1){\r
319             return c2;\r
320         }\r
321         var d = ++key;\r
322         for(var i = 0; i < len1; i++){\r
323             c1[i]._qdiff = d;\r
324         }\r
325         var r = [];\r
326         for(var i = 0, len = c2.length; i < len; i++){\r
327             if(c2[i]._qdiff != d){\r
328                 r[r.length] = c2[i];\r
329             }\r
330         }\r
331         return r;\r
332     }\r
333 \r
334     function quickId(ns, mode, root, id){\r
335         if(ns == root){\r
336            var d = root.ownerDocument || root;\r
337            return d.getElementById(id);\r
338         }\r
339         ns = getNodes(ns, mode, "*");\r
340             return byId(ns, null, id);\r
341     }\r
342 \r
343        function search(path, root, type) {\r
344                     type = type || "select";\r
345             
346             var n = root || document;\r
347             
348             var q = path, mode, lq;\r
349             var tk = Ext.DomQuery.matchers;\r
350             var tklen = tk.length;\r
351             var mm;\r
352 \r
353             var lmode = q.match(modeRe);\r
354             if(lmode && lmode[1]){\r
355                 mode=lmode[1].replace(trimRe, "");\r
356                 q = q.replace(lmode[1], "");\r
357             }\r
358             while(path.substr(0, 1)=="/"){\r
359                 path = path.substr(1);\r
360             }\r
361             while(q && lq != q){\r
362                 lq = q;\r
363                 var tm = q.match(tagTokenRe);\r
364                 if(type == "select"){\r
365                     if(tm){\r
366                         if(tm[1] == "#"){\r
367                             n = quickId(n, mode, root, tm[2]);\r
368                         }else{\r
369                             n = getNodes(n, mode, tm[2]);\r
370                         }\r
371                         q = q.replace(tm[0], "");\r
372                     }else if(q.substr(0, 1) != '@'){\r
373                         n = getNodes(n, mode, "*");\r
374                     }\r
375                 }else{\r
376                     if(tm){\r
377                         if(tm[1] == "#"){\r
378                             n = byId(n, null, tm[2]);\r
379                         }else{\r
380                             n = byTag(n, tm[2]);\r
381                         }\r
382                         q = q.replace(tm[0], "");\r
383                     }\r
384                 }\r
385                 while(!(mm = q.match(modeRe))){\r
386                     var matched = false;\r
387                     for(var j = 0; j < tklen; j++){\r
388                         var t = tk[j];\r
389                         var m = q.match(t.re);\r
390                         if(m){\r
391                             switch(j) {\r
392                                 case 0:\r
393                                     n = byClassName(n, null, " " + m[1] +" ");\r
394                                     break;\r
395                                 case 1:\r
396                                     n = byPseudo(n, m[1], m[2]);\r
397                                     break;\r
398                                 case 2:\r
399                                     n = byAttribute(n, m[2], m[4], m[3], m[1]);\r
400                                     break;\r
401                                 case 3:\r
402                                     n = byId(n, null, m[1]);\r
403                                     break;\r
404                                 case 4:\r
405                                     return {firstChild:{nodeValue:attrValue(n, m[1])}};\r
406                                     \r
407                             }\r
408                             q = q.replace(m[0], "");\r
409                             matched = true;\r
410                             break;\r
411                         }\r
412                     }\r
413 \r
414                     if(!matched){\r
415                         throw 'Error parsing selector, parsing failed at "' + q + '"';\r
416                     }\r
417                 }\r
418                 if(mm[1]){\r
419                     mode=mm[1].replace(trimRe, "");\r
420                     q = q.replace(mm[1], "");\r
421                 }\r
422             }\r
423             return nodup(n);\r
424         }               \r
425 \r
426      return {\r
427         getStyle : function(el, name){\r
428              return Ext.fly(el).getStyle(name);\r
429         },\r
430                 \r
431                 compile: function(path, type) {\r
432                         return function(root) {\r
433                                         return search(path, root, type);\r
434                         }\r
435                 },\r
436 \r
437         \r
438         select : function(path, root, type){\r
439             if(!root || root == document){\r
440                 root = document;\r
441             }\r
442             if(typeof root == "string"){\r
443                 root = document.getElementById(root);\r
444             }\r
445             var paths = path.split(",");\r
446             var results = [];\r
447             for(var i = 0, len = paths.length; i < len; i++){\r
448                 var p = paths[i].replace(trimRe, "");\r
449                 if(!cache[p]){\r
450                     cache[p] = Ext.DomQuery.compile(p);\r
451                     if(!cache[p]){\r
452                         throw p + " is not a valid selector";\r
453                     }\r
454                 }\r
455                 var result = cache[p](root);\r
456                 if(result && result != document){\r
457                     results = results.concat(result);\r
458                 }\r
459             }\r
460             if(paths.length > 1){\r
461                 return nodup(results);\r
462             }\r
463             return results;\r
464         },\r
465 \r
466         \r
467         selectNode : function(path, root){\r
468             return Ext.DomQuery.select(path, root)[0];\r
469         },\r
470 \r
471         \r
472         selectValue : function(path, root, defaultValue){\r
473             path = path.replace(trimRe, "");\r
474             if(!valueCache[path]){\r
475                 valueCache[path] = Ext.DomQuery.compile(path, "select");\r
476             }\r
477             var n = valueCache[path](root);\r
478             n = n[0] ? n[0] : n;\r
479             var v = (n && n.firstChild ? n.firstChild.nodeValue : null);\r
480             return ((v === null||v === undefined||v==='') ? defaultValue : v);\r
481         },\r
482 \r
483         \r
484         selectNumber : function(path, root, defaultValue){\r
485             var v = Ext.DomQuery.selectValue(path, root, defaultValue || 0);\r
486             return parseFloat(v);\r
487         },\r
488 \r
489         \r
490         is : function(el, ss){\r
491             if(typeof el == "string"){\r
492                 el = document.getElementById(el);\r
493             }\r
494             var isArray = Ext.isArray(el);\r
495             var result = Ext.DomQuery.filter(isArray ? el : [el], ss);\r
496             return isArray ? (result.length == el.length) : (result.length > 0);\r
497         },\r
498 \r
499         \r
500         filter : function(els, ss, nonMatches){\r
501             ss = ss.replace(trimRe, "");\r
502             if(!simpleCache[ss]){\r
503                 simpleCache[ss] = Ext.DomQuery.compile(ss, "simple");\r
504             }\r
505             var result = simpleCache[ss](els);\r
506             return nonMatches ? quickDiff(result, els) : result;\r
507         },\r
508 \r
509         \r
510         matchers : [{\r
511                 re: /^\.([\w-]+)/,\r
512                 select: 'n = byClassName(n, null, " {1} ");'\r
513             }, {\r
514                 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,\r
515                 select: 'n = byPseudo(n, "{1}", "{2}");'\r
516             },{\r
517                 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,\r
518                 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'\r
519             }, {\r
520                 re: /^#([\w-]+)/,\r
521                 select: 'n = byId(n, null, "{1}");'\r
522             },{\r
523                 re: /^@([\w-]+)/,\r
524                 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'\r
525             }\r
526         ],\r
527 \r
528         \r
529         operators : {\r
530             "=" : function(a, v){\r
531                 return a == v;\r
532             },\r
533             "!=" : function(a, v){\r
534                 return a != v;\r
535             },\r
536             "^=" : function(a, v){\r
537                 return a && a.substr(0, v.length) == v;\r
538             },\r
539             "$=" : function(a, v){\r
540                 return a && a.substr(a.length-v.length) == v;\r
541             },\r
542             "*=" : function(a, v){\r
543                 return a && a.indexOf(v) !== -1;\r
544             },\r
545             "%=" : function(a, v){\r
546                 return (a % v) == 0;\r
547             },\r
548             "|=" : function(a, v){\r
549                 return a && (a == v || a.substr(0, v.length+1) == v+'-');\r
550             },\r
551             "~=" : function(a, v){\r
552                 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;\r
553             }\r
554         },\r
555 \r
556         \r
557         pseudos : {\r
558             "first-child" : function(c){\r
559                 var r = [], ri = -1, n;\r
560                 for(var i = 0, ci; ci = n = c[i]; i++){\r
561                     while((n = n.previousSibling) && n.nodeType != 1);\r
562                     if(!n){\r
563                         r[++ri] = ci;\r
564                     }\r
565                 }\r
566                 return r;\r
567             },\r
568 \r
569             "last-child" : function(c){\r
570                 var r = [], ri = -1, n;\r
571                 for(var i = 0, ci; ci = n = c[i]; i++){\r
572                     while((n = n.nextSibling) && n.nodeType != 1);\r
573                     if(!n){\r
574                         r[++ri] = ci;\r
575                     }\r
576                 }\r
577                 return r;\r
578             },\r
579 \r
580             "nth-child" : function(c, a) {\r
581                 var r = [], ri = -1;\r
582                 var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);\r
583                 var f = (m[1] || 1) - 0, l = m[2] - 0;\r
584                 for(var i = 0, n; n = c[i]; i++){\r
585                     var pn = n.parentNode;\r
586                     if (batch != pn._batch) {\r
587                         var j = 0;\r
588                         for(var cn = pn.firstChild; cn; cn = cn.nextSibling){\r
589                             if(cn.nodeType == 1){\r
590                                cn.nodeIndex = ++j;\r
591                             }\r
592                         }\r
593                         pn._batch = batch;\r
594                     }\r
595                     if (f == 1) {\r
596                         if (l == 0 || n.nodeIndex == l){\r
597                             r[++ri] = n;\r
598                         }\r
599                     } else if ((n.nodeIndex + l) % f == 0){\r
600                         r[++ri] = n;\r
601                     }\r
602                 }\r
603 \r
604                 return r;\r
605             },\r
606 \r
607             "only-child" : function(c){\r
608                 var r = [], ri = -1;;\r
609                 for(var i = 0, ci; ci = c[i]; i++){\r
610                     if(!prev(ci) && !next(ci)){\r
611                         r[++ri] = ci;\r
612                     }\r
613                 }\r
614                 return r;\r
615             },\r
616 \r
617             "empty" : function(c){\r
618                 var r = [], ri = -1;\r
619                 for(var i = 0, ci; ci = c[i]; i++){\r
620                     var cns = ci.childNodes, j = 0, cn, empty = true;\r
621                     while(cn = cns[j]){\r
622                         ++j;\r
623                         if(cn.nodeType == 1 || cn.nodeType == 3){\r
624                             empty = false;\r
625                             break;\r
626                         }\r
627                     }\r
628                     if(empty){\r
629                         r[++ri] = ci;\r
630                     }\r
631                 }\r
632                 return r;\r
633             },\r
634 \r
635             "contains" : function(c, v){\r
636                 var r = [], ri = -1;\r
637                 for(var i = 0, ci; ci = c[i]; i++){\r
638                     if((ci.textContent||ci.innerText||'').indexOf(v) != -1){\r
639                         r[++ri] = ci;\r
640                     }\r
641                 }\r
642                 return r;\r
643             },\r
644 \r
645             "nodeValue" : function(c, v){\r
646                 var r = [], ri = -1;\r
647                 for(var i = 0, ci; ci = c[i]; i++){\r
648                     if(ci.firstChild && ci.firstChild.nodeValue == v){\r
649                         r[++ri] = ci;\r
650                     }\r
651                 }\r
652                 return r;\r
653             },\r
654 \r
655             "checked" : function(c){\r
656                 var r = [], ri = -1;\r
657                 for(var i = 0, ci; ci = c[i]; i++){\r
658                     if(ci.checked == true){\r
659                         r[++ri] = ci;\r
660                     }\r
661                 }\r
662                 return r;\r
663             },\r
664 \r
665             "not" : function(c, ss){\r
666                 return Ext.DomQuery.filter(c, ss, true);\r
667             },\r
668 \r
669             "any" : function(c, selectors){\r
670                 var ss = selectors.split('|');\r
671                 var r = [], ri = -1, s;\r
672                 for(var i = 0, ci; ci = c[i]; i++){\r
673                     for(var j = 0; s = ss[j]; j++){\r
674                         if(Ext.DomQuery.is(ci, s)){\r
675                             r[++ri] = ci;\r
676                             break;\r
677                         }\r
678                     }\r
679                 }\r
680                 return r;\r
681             },\r
682 \r
683             "odd" : function(c){\r
684                 return this["nth-child"](c, "odd");\r
685             },\r
686 \r
687             "even" : function(c){\r
688                 return this["nth-child"](c, "even");\r
689             },\r
690 \r
691             "nth" : function(c, a){\r
692                 return c[a-1] || [];\r
693             },\r
694 \r
695             "first" : function(c){\r
696                 return c[0] || [];\r
697             },\r
698 \r
699             "last" : function(c){\r
700                 return c[c.length-1] || [];\r
701             },\r
702 \r
703             "has" : function(c, ss){\r
704                 var s = Ext.DomQuery.select;\r
705                 var r = [], ri = -1;\r
706                 for(var i = 0, ci; ci = c[i]; i++){\r
707                     if(s(ss, ci).length > 0){\r
708                         r[++ri] = ci;\r
709                     }\r
710                 }\r
711                 return r;\r
712             },\r
713 \r
714             "next" : function(c, ss){\r
715                 var is = Ext.DomQuery.is;\r
716                 var r = [], ri = -1;\r
717                 for(var i = 0, ci; ci = c[i]; i++){\r
718                     var n = next(ci);\r
719                     if(n && is(n, ss)){\r
720                         r[++ri] = ci;\r
721                     }\r
722                 }\r
723                 return r;\r
724             },\r
725 \r
726             "prev" : function(c, ss){\r
727                 var is = Ext.DomQuery.is;\r
728                 var r = [], ri = -1;\r
729                 for(var i = 0, ci; ci = c[i]; i++){\r
730                     var n = prev(ci);\r
731                     if(n && is(n, ss)){\r
732                         r[++ri] = ci;\r
733                     }\r
734                 }\r
735                 return r;\r
736             }\r
737         }\r
738     };\r
739 }();\r
740 \r
741 Ext.query = Ext.DomQuery.select;\r
742 \r
743 Date.precompileFormats = function(s){\r
744         var formats = s.split('|');\r
745         for(var i = 0, len = formats.length;i < len;i++){\r
746                 Date.createNewFormat(formats[i]);\r
747                 Date.createParser(formats[i]);\r
748         }\r
749 }\r
750 \r
751 Date.precompileFormats("D n/j/Y|n/j/Y|n/j/y|m/j/y|n/d/y|m/j/Y|n/d/Y|YmdHis|F d, Y|l, F d, Y|H:i:s|g:i A|g:ia|g:iA|g:i a|g:i A|h:i|g:i|H:i|ga|ha|gA|h a|g a|g A|gi|hi|gia|hia|g|H|m/d/y|m/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d|Y-m-d|Y-m-d H:i:s|d/m/y|d/m/Y|d-m-y|d-m-Y|d/m|d-m|dm|dmy|dmY|Y-m-d|l|D m/d|D m/d/Y|m/d/Y");\r
752 \r
753
754 Ext.ColorPalette.prototype.tpl = new Ext.XTemplate(\r
755     '<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>'\r
756 );\r
757 \r
758 \r
759 \r
760 \r
761 \r
762
763 \r
764 Ext.air.FileProvider = function(config){\r
765     Ext.air.FileProvider.superclass.constructor.call(this);\r
766         \r
767         this.defaultState = {\r
768                 mainWindow : {\r
769                         width:780,\r
770                         height:580,\r
771                         x:10,\r
772                         y:10\r
773                 }\r
774         };\r
775         \r
776     Ext.apply(this, config);\r
777     this.state = this.readState();\r
778         \r
779         var provider = this;\r
780         air.NativeApplication.nativeApplication.addEventListener('exiting', function(){\r
781                 provider.saveState();\r
782         });\r
783 };\r
784 \r
785 Ext.extend(Ext.air.FileProvider, Ext.state.Provider, {\r
786         file: 'extstate.data',\r
787         \r
788         
789     readState : function(){\r
790                 var stateFile = air.File.applicationStorageDirectory.resolvePath(this.file);\r
791                 if(!stateFile.exists){\r
792                         return this.defaultState || {};\r
793                 }\r
794                 \r
795                 var stream = new air.FileStream();\r
796                 stream.open(stateFile, air.FileMode.READ);\r
797                 \r
798                 var stateData = stream.readObject();\r
799                 stream.close();\r
800                 \r
801                 return stateData || this.defaultState || {};\r
802     },\r
803 \r
804     
805     saveState : function(name, value){\r
806         var stateFile = air.File.applicationStorageDirectory.resolvePath(this.file);\r
807                 var stream = new air.FileStream();\r
808                 stream.open(stateFile, air.FileMode.WRITE);\r
809                 stream.writeObject(this.state);\r
810                 stream.close();\r
811     }\r
812 });
813 Ext.air.NativeObservable = Ext.extend(Ext.util.Observable, {\r
814         addListener : function(name){\r
815                 this.proxiedEvents = this.proxiedEvents || {};\r
816                 if(!this.proxiedEvents[name]){\r
817                         var instance = this;\r
818                         var f = function(){\r
819                                 var args = Array.prototype.slice.call(arguments, 0);\r
820                                 args.unshift(name);\r
821                                 instance.fireEvent.apply(instance, args);\r
822                         };\r
823                         this.proxiedEvents[name] = f;\r
824                         this.getNative().addEventListener(name, f);\r
825                 }\r
826                 Ext.air.NativeObservable.superclass.addListener.apply(this, arguments);\r
827         }\r
828 });\r
829 \r
830 Ext.air.NativeObservable.prototype.on = Ext.air.NativeObservable.prototype.addListener;
831 \r
832 Ext.air.NativeWindow = function(config){\r
833         Ext.apply(this, config);\r
834         \r
835         this.id = this.id || Ext.uniqueId();\r
836         \r
837         this.addEvents(\r
838                 'close', \r
839                 'closing',\r
840                 'move',\r
841                 'moving',\r
842                 'resize',\r
843                 'resizing',\r
844                 'displayStateChange',\r
845                 'displayStateChanging'\r
846         );\r
847         \r
848         Ext.air.NativeWindow.superclass.constructor.call(this);\r
849         \r
850         if(!this.instance){\r
851                 var options = new air.NativeWindowInitOptions();\r
852                 options.systemChrome = this.chrome;\r
853                 options.type = this.type;\r
854                 options.resizable = this.resizable;\r
855                 options.minimizable = this.minimizable;\r
856                 options.maximizable = this.maximizable;\r
857                 options.transparent = this.transparent;\r
858                 \r
859                 this.loader = window.runtime.flash.html.HTMLLoader.createRootWindow(false, options, false);\r
860                 this.loader.load(new air.URLRequest(this.file));\r
861         \r
862                 this.instance = this.loader.window.nativeWindow;\r
863         }else{\r
864                 this.loader = this.instance.stage.getChildAt(0);\r
865         }\r
866         \r
867         var provider = Ext.state.Manager;\r
868         var b = air.Screen.mainScreen.visibleBounds;\r
869         \r
870         var state = provider.get(this.id) || {};\r
871         provider.set(this.id, state);\r
872                 \r
873         var win = this.instance;\r
874         \r
875         var width = Math.max(state.width || this.width, 100);\r
876         var height = Math.max(state.height || this.height, 100);\r
877         \r
878         var centerX = b.x + ((b.width/2)-(width/2));\r
879         var centerY = b.y + ((b.height/2)-(height/2));\r
880         \r
881         var x = !Ext.isEmpty(state.x, false) ? state.x : (!Ext.isEmpty(this.x, false) ? this.x : centerX);\r
882         var y = !Ext.isEmpty(state.y, false) ? state.y : (!Ext.isEmpty(this.y, false) ? this.y : centerY);\r
883         \r
884         win.width = width;\r
885         win.height = height;\r
886         win.x = x;\r
887         win.y = y;\r
888         \r
889         win.addEventListener('move', function(){\r
890                 if(win.displayState != air.NativeWindowDisplayState.MINIMIZED && win.width > 100 && win.height > 100) {\r
891                         state.x = win.x;\r
892                         state.y = win.y;\r
893                 }\r
894         });     \r
895         win.addEventListener('resize', function(){\r
896                 if (win.displayState != air.NativeWindowDisplayState.MINIMIZED && win.width > 100 && win.height > 100) {\r
897                         state.width = win.width;\r
898                         state.height = win.height;\r
899                 }\r
900         });\r
901         \r
902         Ext.air.NativeWindowManager.register(this);\r
903         this.on('close', this.unregister, this);\r
904         \r
905         if(this.minimizeToTray){\r
906                 this.initMinimizeToTray(this.trayIcon, this.trayMenu);\r
907         }\r
908         \r
909 };\r
910 \r
911 Ext.extend(Ext.air.NativeWindow, Ext.air.NativeObservable, {\r
912         chrome: 'standard', 
913         type: 'normal', 
914         width:600,\r
915         height:400,\r
916         resizable: true,\r
917         minimizable: true,\r
918         maximizable: true,\r
919         transparent: false,\r
920         \r
921         getNative : function(){\r
922                 return this.instance;\r
923         },\r
924         \r
925         getCenterXY : function(){\r
926                 var b = air.Screen.mainScreen.visibleBounds;\r
927                 return {\r
928                         x: b.x + ((b.width/2)-(this.width/2)),\r
929                         y: b.y + ((b.height/2)-(this.height/2))\r
930                 };\r
931         },\r
932         \r
933         show :function(){\r
934                 if(this.trayed){\r
935                         Ext.air.SystemTray.hideIcon();\r
936                         this.trayed = false;\r
937                 }\r
938                 this.instance.visible = true;\r
939         },\r
940         \r
941         activate : function(){\r
942                 this.show();\r
943                 this.instance.activate();\r
944         },\r
945         \r
946         hide :function(){\r
947                 this.instance.visible = false;\r
948         },\r
949         \r
950         close : function(){\r
951                 this.instance.close();  \r
952         },\r
953         \r
954         isMinimized :function(){\r
955                 return this.instance.displayState == air.NativeWindowDisplayState.MINIMIZED;\r
956         },\r
957         \r
958         isMaximized :function(){\r
959                 return this.instance.displayState == air.NativeWindowDisplayState.MAXIMIZED;\r
960         },\r
961         \r
962         moveTo : function(x, y){\r
963                 this.x = this.instance.x = x;\r
964                 this.y = this.instance.y = y;   \r
965         },\r
966         \r
967         resize : function(width, height){\r
968                 this.width = this.instance.width = width;\r
969                 this.height = this.instance.height = height;    \r
970         },\r
971         \r
972         unregister : function(){\r
973                 Ext.air.NativeWindowManager.unregister(this);\r
974         },\r
975         \r
976         initMinimizeToTray : function(icon, menu){\r
977                 var tray = Ext.air.SystemTray;\r
978                 tray.setIcon(icon, this.trayTip);\r
979                 this.on('displayStateChanging', function(e){\r
980                         if(e.afterDisplayState == 'minimized'){\r
981                                 e.preventDefault();\r
982                                 this.hide();\r
983                                 tray.showIcon();\r
984                                 this.trayed = true;\r
985                         }\r
986                 }, this);\r
987                 \r
988                 tray.on('click', function(){\r
989                         this.activate();\r
990                 }, this);\r
991                 \r
992                 if(menu){\r
993                         tray.setMenu(menu);\r
994                 }\r
995         }\r
996 });\r
997 \r
998 Ext.air.NativeWindow.getRootWindow = function(){\r
999         return air.NativeApplication.nativeApplication.openedWindows[0];\r
1000 };\r
1001 \r
1002 Ext.air.NativeWindow.getRootHtmlWindow = function(){\r
1003         return Ext.air.NativeWindow.getRootWindow().stage.getChildAt(0).window;\r
1004 };\r
1005 \r
1006 Ext.air.NativeWindowGroup = function(){\r
1007     var list = {};\r
1008 \r
1009     return {\r
1010         register : function(win){\r
1011             list[win.id] = win;\r
1012         },\r
1013 \r
1014         unregister : function(win){\r
1015             delete list[win.id];\r
1016         },\r
1017 \r
1018         get : function(id){\r
1019             return list[id];\r
1020         },\r
1021 \r
1022         closeAll : function(){\r
1023             for(var id in list){\r
1024                 if(list.hasOwnProperty(id)){\r
1025                     list[id].close();\r
1026                 }\r
1027             }\r
1028         },\r
1029 \r
1030         \r
1031         each : function(fn, scope){\r
1032             for(var id in list){\r
1033                 if(list.hasOwnProperty(id)){\r
1034                     if(fn.call(scope || list[id], list[id]) === false){\r
1035                         return;\r
1036                     }\r
1037                 }\r
1038             }\r
1039         }\r
1040     };\r
1041 };\r
1042 \r
1043 \r
1044 Ext.air.NativeWindowManager = new Ext.air.NativeWindowGroup();
1045
1046 Ext.sql.Connection = function(config){\r
1047         Ext.apply(this, config);\r
1048         Ext.sql.Connection.superclass.constructor.call(this);\r
1049 \r
1050         this.addEvents({\r
1051                 open : true,\r
1052                 close: true\r
1053         });\r
1054 };\r
1055 \r
1056 Ext.extend(Ext.sql.Connection, Ext.util.Observable, {\r
1057         maxResults: 10000,\r
1058         openState : false,\r
1059 \r
1060     
1061     open : function(file){\r
1062         },\r
1063 \r
1064         close : function(){\r
1065         },\r
1066 \r
1067     exec : function(sql){\r
1068         },\r
1069 \r
1070         execBy : function(sql, args){\r
1071         },\r
1072 \r
1073         query : function(sql){\r
1074         },\r
1075 \r
1076         queryBy : function(sql, args){\r
1077         },\r
1078 \r
1079     
1080     isOpen : function(){\r
1081                 return this.openState;\r
1082         },\r
1083 \r
1084         getTable : function(name, keyName){\r
1085                 return new Ext.sql.Table(this, name, keyName);\r
1086         },\r
1087 \r
1088         createTable : function(o){\r
1089                 var tableName = o.name;\r
1090                 var keyName = o.key;\r
1091                 var fs = o.fields;\r
1092                 if(!Ext.isArray(fs)){ 
1093                         fs = fs.items;\r
1094                 }\r
1095                 var buf = [];\r
1096                 for(var i = 0, len = fs.length; i < len; i++){\r
1097                         var f = fs[i], s = f.name;\r
1098                         switch(f.type){\r
1099                     case "int":\r
1100                     case "bool":\r
1101                     case "boolean":\r
1102                         s += ' INTEGER';\r
1103                         break;\r
1104                     case "float":\r
1105                         s += ' REAL';\r
1106                         break;\r
1107                     default:\r
1108                         s += ' TEXT';\r
1109                 }\r
1110                 if(f.allowNull === false || f.name == keyName){\r
1111                         s += ' NOT NULL';\r
1112                 }\r
1113                 if(f.name == keyName){\r
1114                         s += ' PRIMARY KEY';\r
1115                 }\r
1116                 if(f.unique === true){\r
1117                         s += ' UNIQUE';\r
1118                 }\r
1119 \r
1120                 buf[buf.length] = s;\r
1121             }\r
1122             var sql = ['CREATE TABLE IF NOT EXISTS ', tableName, ' (', buf.join(','), ')'].join('');\r
1123         this.exec(sql);\r
1124         }\r
1125 });\r
1126 \r
1127 \r
1128 Ext.sql.Connection.getInstance = function(db, config){\r
1129     if(Ext.isAir){ 
1130         return new Ext.sql.AirConnection(config);\r
1131     } else { 
1132         return new Ext.sql.GearsConnection(config);\r
1133     }\r
1134 };
1135 Ext.sql.Table = function(conn, name, keyName){\r
1136         this.conn = conn;\r
1137         this.name = name;\r
1138         this.keyName = keyName;\r
1139 };\r
1140 \r
1141 Ext.sql.Table.prototype = {\r
1142         update : function(o){\r
1143                 var clause = this.keyName + " = ?";\r
1144                 return this.updateBy(o, clause, [o[this.keyName]]);\r
1145         },\r
1146 \r
1147         updateBy : function(o, clause, args){\r
1148                 var sql = "UPDATE " + this.name + " set ";\r
1149                 var fs = [], a = [];\r
1150                 for(var key in o){\r
1151                         if(o.hasOwnProperty(key)){\r
1152                                 fs[fs.length] = key + ' = ?';\r
1153                                 a[a.length] = o[key];\r
1154                         }\r
1155                 }\r
1156                 for(var key in args){\r
1157                         if(args.hasOwnProperty(key)){\r
1158                                 a[a.length] = args[key];\r
1159                         }\r
1160                 }\r
1161                 sql = [sql, fs.join(','), ' WHERE ', clause].join('');\r
1162                 return this.conn.execBy(sql, a);\r
1163         },\r
1164 \r
1165         insert : function(o){\r
1166                 var sql = "INSERT into " + this.name + " ";\r
1167                 var fs = [], vs = [], a = [];\r
1168                 for(var key in o){\r
1169                         if(o.hasOwnProperty(key)){\r
1170                                 fs[fs.length] = key;\r
1171                                 vs[vs.length] = '?';\r
1172                                 a[a.length] = o[key];\r
1173                         }\r
1174                 }\r
1175                 sql = [sql, '(', fs.join(','), ') VALUES (', vs.join(','), ')'].join('');\r
1176         return this.conn.execBy(sql, a);\r
1177     },\r
1178 \r
1179         lookup : function(id){\r
1180                 return this.selectBy('where ' + this.keyName + " = ?", [id])[0] || null;\r
1181         },\r
1182 \r
1183         exists : function(id){\r
1184                 return !!this.lookup(id);\r
1185         },\r
1186 \r
1187         save : function(o){\r
1188                 if(this.exists(o[this.keyName])){\r
1189             this.update(o);\r
1190         }else{\r
1191             this.insert(o);\r
1192         }\r
1193         },\r
1194 \r
1195         select : function(clause){\r
1196                 return this.selectBy(clause, null);\r
1197         },\r
1198 \r
1199         selectBy : function(clause, args){\r
1200                 var sql = "select * from " + this.name;\r
1201                 if(clause){\r
1202                         sql += ' ' + clause;\r
1203                 }\r
1204                 args = args || {};\r
1205                 return this.conn.queryBy(sql, args);\r
1206         },\r
1207 \r
1208         remove : function(clause){\r
1209                 this.deleteBy(clause, null);\r
1210         },\r
1211 \r
1212         removeBy : function(clause, args){\r
1213                 var sql = "delete from " + this.name;\r
1214                 if(clause){\r
1215                         sql += ' where ' + clause;\r
1216                 }\r
1217                 args = args || {};\r
1218                 this.conn.execBy(sql, args);\r
1219         }\r
1220 };
1221 Ext.sql.Proxy = function(conn, table, keyName, store, readonly){\r
1222     Ext.sql.Proxy.superclass.constructor.call(this);\r
1223     this.conn = conn;\r
1224     this.table = this.conn.getTable(table, keyName);\r
1225     this.store = store;\r
1226 \r
1227         if (readonly !== true) {\r
1228                 this.store.on('add', this.onAdd, this);\r
1229                 this.store.on('update', this.onUpdate, this);\r
1230                 this.store.on('remove', this.onRemove, this);\r
1231         }\r
1232 };\r
1233 \r
1234 Ext.sql.Proxy.DATE_FORMAT = 'Y-m-d H:i:s';\r
1235 \r
1236 Ext.extend(Ext.sql.Proxy, Ext.data.DataProxy, {\r
1237     load : function(params, reader, callback, scope, arg){\r
1238         if(!this.conn.isOpen()){ 
1239                 this.conn.on('open', function(){\r
1240                         this.load(params, reader, callback, scope, arg);\r
1241                 }, this, {single:true});\r
1242                 return;\r
1243         };\r
1244         if(this.fireEvent("beforeload", this, params, reader, callback, scope, arg) !== false){\r
1245                         var clause = params.where || '';\r
1246                         var args = params.args || [];\r
1247                         var group = params.groupBy;\r
1248                         var sort = params.sort;\r
1249                         var dir = params.dir;\r
1250 \r
1251                         if(group || sort){\r
1252                                 clause += ' ORDER BY ';\r
1253                                 if(group && group != sort){\r
1254                                         clause += group + ' ASC, ';\r
1255                                 }\r
1256                                 clause += sort + ' ' + (dir || 'ASC');\r
1257                         }\r
1258 \r
1259                         var rs = this.table.selectBy(clause, args);\r
1260                         this.onLoad({callback:callback, scope:scope, arg:arg, reader: reader}, rs);\r
1261         }else{\r
1262             callback.call(scope||this, null, arg, false);\r
1263         }\r
1264     },\r
1265 \r
1266     onLoad : function(trans, rs, e, stmt){\r
1267         if(rs === false){\r
1268                 this.fireEvent("loadexception", this, null, trans.arg, e);\r
1269             trans.callback.call(trans.scope||window, null, trans.arg, false);\r
1270             return;\r
1271         }\r
1272         var result = trans.reader.readRecords(rs);\r
1273         this.fireEvent("load", this, rs, trans.arg);\r
1274         trans.callback.call(trans.scope||window, result, trans.arg, true);\r
1275     },\r
1276 \r
1277     processData : function(o){\r
1278         var fs = this.store.fields;\r
1279         var r = {};\r
1280         for(var key in o){\r
1281                 var f = fs.key(key), v = o[key];\r
1282                         if(f){\r
1283                                 if(f.type == 'date'){\r
1284                                         r[key] = v ? v.format(Ext.sql.Proxy.DATE_FORMAT,10) : '';\r
1285                                 }else if(f.type == 'boolean'){\r
1286                                         r[key] = v ? 1 : 0;\r
1287                                 }else{\r
1288                                         r[key] = v;\r
1289                                 }\r
1290                         }\r
1291                 }\r
1292                 return r;\r
1293     },\r
1294 \r
1295     onUpdate : function(ds, record){\r
1296         var changes = record.getChanges();\r
1297         var kn = this.table.keyName;\r
1298         this.table.updateBy(this.processData(changes), kn + ' = ?', [record.data[kn]]);\r
1299         record.commit(true);\r
1300     },\r
1301 \r
1302     onAdd : function(ds, records, index){\r
1303         for(var i = 0, len = records.length; i < len; i++){\r
1304                 this.table.insert(this.processData(records[i].data));\r
1305         }\r
1306     },\r
1307 \r
1308     onRemove : function(ds, record, index){\r
1309                 var kn = this.table.keyName;\r
1310         this.table.removeBy(kn + ' = ?', [record.data[kn]]);\r
1311     }\r
1312 });
1313  Ext.sql.AirConnection = Ext.extend(Ext.sql.Connection, {\r
1314         
1315     open : function(db){\r
1316         this.conn = new air.SQLConnection();\r
1317                 var file = air.File.applicationDirectory.resolvePath(db);\r
1318                 this.conn.open(file);\r
1319         this.openState = true;\r
1320                 this.fireEvent('open', this);\r
1321     },\r
1322 \r
1323         close : function(){\r
1324         this.conn.close();\r
1325         this.fireEvent('close', this);\r
1326     },\r
1327 \r
1328         createStatement : function(type){\r
1329                 var stmt = new air.SQLStatement();\r
1330                 stmt.sqlConnection = this.conn;\r
1331                 return stmt;\r
1332         },\r
1333 \r
1334     exec : function(sql){\r
1335         var stmt = this.createStatement('exec');\r
1336                 stmt.text = sql;\r
1337                 stmt.execute();\r
1338     },\r
1339 \r
1340         execBy : function(sql, args){\r
1341                 var stmt = this.createStatement('exec');\r
1342                 stmt.text = sql;\r
1343                 this.addParams(stmt, args);\r
1344                 stmt.execute();\r
1345         },\r
1346 \r
1347         query : function(sql){\r
1348                 var stmt = this.createStatement('query');\r
1349                 stmt.text = sql;\r
1350                 stmt.execute(this.maxResults);\r
1351                 return this.readResults(stmt.getResult());\r
1352         },\r
1353 \r
1354         queryBy : function(sql, args){\r
1355                 var stmt = this.createStatement('query');\r
1356                 stmt.text = sql;\r
1357                 this.addParams(stmt, args);\r
1358                 stmt.execute(this.maxResults);\r
1359                 return this.readResults(stmt.getResult());\r
1360         },\r
1361 \r
1362     addParams : function(stmt, args){\r
1363                 if(!args){ return; }\r
1364                 for(var key in args){\r
1365                         if(args.hasOwnProperty(key)){\r
1366                                 if(!isNaN(key)){\r
1367                                         var v = args[key];\r
1368                                         if(Ext.isDate(v)){\r
1369                                                 v = v.format(Ext.sql.Proxy.DATE_FORMAT);\r
1370                                         }\r
1371                                         stmt.parameters[parseInt(key)] = v;\r
1372                                 }else{\r
1373                                         stmt.parameters[':' + key] = args[key];\r
1374                                 }\r
1375                         }\r
1376                 }\r
1377                 return stmt;\r
1378         },\r
1379 \r
1380     readResults : function(rs){\r
1381         var r = [];\r
1382         if(rs && rs.data){\r
1383                     var len = rs.data.length;\r
1384                 for(var i = 0; i < len; i++) {\r
1385                     r[r.length] = rs.data[i];\r
1386                 }\r
1387         }\r
1388         return r;\r
1389     }\r
1390 });
1391 Ext.air.SystemTray = function(){\r
1392         var app = air.NativeApplication.nativeApplication;\r
1393         var icon, isWindows = false, bitmaps;\r
1394         \r
1395         
1396         if(air.NativeApplication.supportsSystemTrayIcon) {\r
1397         icon = app.icon;\r
1398                 isWindows = true;\r
1399     }\r
1400     \r
1401         
1402     if(air.NativeApplication.supportsDockIcon) {\r
1403                 icon = app.icon;\r
1404     }\r
1405         \r
1406         return {\r
1407                 \r
1408                 setIcon : function(icon, tooltip, initWithIcon){\r
1409                         if(!icon){ 
1410                                 return;\r
1411                         }\r
1412                         var loader = new air.Loader();\r
1413                         loader.contentLoaderInfo.addEventListener(air.Event.COMPLETE, function(e){\r
1414                                 bitmaps = new runtime.Array(e.target.content.bitmapData);\r
1415                                 if (initWithIcon) {\r
1416                                         icon.bitmaps = bitmaps;\r
1417                                 }\r
1418                         });\r
1419                 loader.load(new air.URLRequest(icon));\r
1420                         if(tooltip && air.NativeApplication.supportsSystemTrayIcon) {\r
1421                                 app.icon.tooltip = tooltip;\r
1422                         }\r
1423                 },\r
1424                 \r
1425                 bounce : function(priority){\r
1426                         icon.bounce(priority);\r
1427                 },\r
1428                 \r
1429                 on : function(eventName, fn, scope){\r
1430                         icon.addEventListener(eventName, function(){\r
1431                                 fn.apply(scope || this, arguments);\r
1432                         });\r
1433                 },\r
1434                 \r
1435                 hideIcon : function(){\r
1436                         if(!icon){ 
1437                                 return;\r
1438                         }\r
1439                         icon.bitmaps = [];\r
1440                 },\r
1441                 \r
1442                 showIcon : function(){\r
1443                         if(!icon){ 
1444                                 return;\r
1445                         }\r
1446                         icon.bitmaps = bitmaps;\r
1447                 },\r
1448                 \r
1449                 setMenu: function(actions, _parentMenu){\r
1450                         if(!icon){ 
1451                                 return;\r
1452                         }\r
1453                         var menu = new air.NativeMenu();\r
1454                         \r
1455                         for (var i = 0, len = actions.length; i < len; i++) {\r
1456                                 var a = actions[i];\r
1457                                 if(a == '-'){\r
1458                                         menu.addItem(new air.NativeMenuItem("", true));\r
1459                                 }else{\r
1460                                         var item = menu.addItem(Ext.air.MenuItem(a));\r
1461                                         if(a.menu || (a.initialConfig && a.initialConfig.menu)){\r
1462                                                 item.submenu = Ext.air.SystemTray.setMenu(a.menu || a.initialConfig.menu, menu);\r
1463                                         }\r
1464                                 }\r
1465                                 \r
1466                                 if(!_parentMenu){\r
1467                                         icon.menu = menu;\r
1468                                 }\r
1469                         }\r
1470                         \r
1471                         return menu;\r
1472                 }\r
1473         };      \r
1474 }();
1475
1476 \r
1477 Ext.air.DragType = {\r
1478         TEXT : 'text/plain',\r
1479         HTML : 'text/html',\r
1480         URL : 'text/uri-list',\r
1481         BITMAP : 'image/x-vnd.adobe.air.bitmap',\r
1482         FILES : 'application/x-vnd.adobe.air.file-list'\r
1483 };\r
1484 \r
1485 Ext.apply(Ext.EventObjectImpl.prototype, {\r
1486         hasFormat : function(format){\r
1487                 if (this.browserEvent.dataTransfer) {\r
1488                         for (var i = 0, len = this.browserEvent.dataTransfer.types.length; i < len; i++) {\r
1489                                 if(this.browserEvent.dataTransfer.types[i] == format) {\r
1490                                         return true;\r
1491                                 }\r
1492                         }\r
1493                 }\r
1494                 return false;\r
1495         },\r
1496         \r
1497         getData : function(type){\r
1498                 return this.browserEvent.dataTransfer.getData(type);\r
1499         }\r
1500 });\r
1501 \r
1502 \r
1503
1504 Ext.air.Sound = {\r
1505         play : function(file, startAt){\r
1506                 var soundFile = air.File.applicationDirectory.resolvePath(file);\r
1507                 var sound = new air.Sound();\r
1508                 sound.load(new air.URLRequest(soundFile.url));\r
1509                 sound.play(startAt);\r
1510         }\r
1511 };\r
1512
1513
1514 Ext.air.SystemMenu = function(){\r
1515         var menu;\r
1516         
1517         if(air.NativeWindow.supportsMenu && nativeWindow.systemChrome != air.NativeWindowSystemChrome.NONE) {\r
1518         menu = new air.NativeMenu();\r
1519         nativeWindow.menu = menu;\r
1520     }\r
1521     \r
1522         
1523     if(air.NativeApplication.supportsMenu) {\r
1524                 menu = air.NativeApplication.nativeApplication.menu;\r
1525     }\r
1526 \r
1527     function find(menu, text){\r
1528         for(var i = 0, len = menu.items.length; i < len; i++){\r
1529             if(menu.items[i]['label'] == text){\r
1530                 return menu.items[i];\r
1531             }\r
1532         }\r
1533         return null;\r
1534     }\r
1535 \r
1536     return {\r
1537                 add: function(text, actions, mindex){\r
1538 \r
1539             var item = find(menu, text);\r
1540             if(!item){\r
1541                 item = menu.addItem(new air.NativeMenuItem(text));\r
1542                 item.mnemonicIndex = mindex || 0;\r
1543 \r
1544                 item.submenu = new air.NativeMenu();\r
1545                         }\r
1546                         for (var i = 0, len = actions.length; i < len; i++) {\r
1547                                 item.submenu.addItem(actions[i] == '-' ? new air.NativeMenuItem("", true) : Ext.air.MenuItem(actions[i]));\r
1548                         }\r
1549             return item.submenu;\r
1550         },\r
1551                 \r
1552                 get : function(){\r
1553                         return menu;\r
1554                 }\r
1555         };      \r
1556 }();\r
1557 \r
1558
1559 Ext.air.MenuItem = function(action){\r
1560         if(!action.isAction){\r
1561                 action = new Ext.Action(action);\r
1562         }\r
1563         var cfg = action.initialConfig;\r
1564         var nativeItem = new air.NativeMenuItem(cfg.itemText || cfg.text);\r
1565         \r
1566         nativeItem.enabled = !cfg.disabled;\r
1567 \r
1568     if(!Ext.isEmpty(cfg.checked)){\r
1569         nativeItem.checked = cfg.checked;\r
1570     }\r
1571 \r
1572     var handler = cfg.handler;\r
1573         var scope = cfg.scope;\r
1574         \r
1575         nativeItem.addEventListener(air.Event.SELECT, function(){\r
1576                 handler.call(scope || window, cfg);\r
1577         });\r
1578         \r
1579         action.addComponent({\r
1580                 setDisabled : function(v){\r
1581                         nativeItem.enabled = !v;\r
1582                 },\r
1583                 \r
1584                 setText : function(v){\r
1585                         nativeItem.label = v;\r
1586                 },\r
1587                 \r
1588                 setVisible : function(v){\r
1589                         
1590                         nativeItem.enabled = !v;\r
1591                 },\r
1592                 \r
1593                 setHandler : function(newHandler, newScope){\r
1594                         handler = newHandler;\r
1595                         scope = newScope;\r
1596                 },\r
1597                 
1598                 on : function(){}\r
1599         });\r
1600         \r
1601         return nativeItem;\r
1602 }\r
1603
1604 </pre>    \r
1605 </body>\r
1606 </html>