Upgrade to ExtJS 3.3.1 - Released 11/30/2010
[extjs.git] / pkgs / pkg-charts-debug.js
1 /*!
2  * Ext JS Library 3.3.1
3  * Copyright(c) 2006-2010 Sencha Inc.
4  * licensing@sencha.com
5  * http://www.sencha.com/license
6  */
7 /*! SWFObject v2.2 <http://code.google.com/p/swfobject/> 
8     is released under the MIT License <http://www.opensource.org/licenses/mit-license.php> 
9 */
10
11 var swfobject = function() {
12     
13     var UNDEF = "undefined",
14         OBJECT = "object",
15         SHOCKWAVE_FLASH = "Shockwave Flash",
16         SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash",
17         FLASH_MIME_TYPE = "application/x-shockwave-flash",
18         EXPRESS_INSTALL_ID = "SWFObjectExprInst",
19         ON_READY_STATE_CHANGE = "onreadystatechange",
20         
21         win = window,
22         doc = document,
23         nav = navigator,
24         
25         plugin = false,
26         domLoadFnArr = [main],
27         regObjArr = [],
28         objIdArr = [],
29         listenersArr = [],
30         storedAltContent,
31         storedAltContentId,
32         storedCallbackFn,
33         storedCallbackObj,
34         isDomLoaded = false,
35         isExpressInstallActive = false,
36         dynamicStylesheet,
37         dynamicStylesheetMedia,
38         autoHideShow = true,
39     
40     /* Centralized function for browser feature detection
41         - User agent string detection is only used when no good alternative is possible
42         - Is executed directly for optimal performance
43     */  
44     ua = function() {
45         var w3cdom = typeof doc.getElementById != UNDEF && typeof doc.getElementsByTagName != UNDEF && typeof doc.createElement != UNDEF,
46             u = nav.userAgent.toLowerCase(),
47             p = nav.platform.toLowerCase(),
48             windows = p ? (/win/).test(p) : /win/.test(u),
49             mac = p ? (/mac/).test(p) : /mac/.test(u),
50             webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, // returns either the webkit version or false if not webkit
51             ie = !+"\v1", // feature detection based on Andrea Giammarchi's solution: http://webreflection.blogspot.com/2009/01/32-bytes-to-know-if-your-browser-is-ie.html
52             playerVersion = [0,0,0],
53             d = null;
54         if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) {
55             d = nav.plugins[SHOCKWAVE_FLASH].description;
56             if (d && !(typeof nav.mimeTypes != UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) { // navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin indicates whether plug-ins are enabled or disabled in Safari 3+
57                 plugin = true;
58                 ie = false; // cascaded feature detection for Internet Explorer
59                 d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
60                 playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10);
61                 playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
62                 playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0;
63             }
64         }
65         else if (typeof win.ActiveXObject != UNDEF) {
66             try {
67                 var a = new ActiveXObject(SHOCKWAVE_FLASH_AX);
68                 if (a) { // a will return null when ActiveX is disabled
69                     d = a.GetVariable("$version");
70                     if (d) {
71                         ie = true; // cascaded feature detection for Internet Explorer
72                         d = d.split(" ")[1].split(",");
73                         playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
74                     }
75                 }
76             }
77             catch(e) {}
78         }
79         return { w3:w3cdom, pv:playerVersion, wk:webkit, ie:ie, win:windows, mac:mac };
80     }(),
81     
82     /* Cross-browser onDomLoad
83         - Will fire an event as soon as the DOM of a web page is loaded
84         - Internet Explorer workaround based on Diego Perini's solution: http://javascript.nwbox.com/IEContentLoaded/
85         - Regular onload serves as fallback
86     */ 
87     onDomLoad = function() {
88         if (!ua.w3) { return; }
89         if ((typeof doc.readyState != UNDEF && doc.readyState == "complete") || (typeof doc.readyState == UNDEF && (doc.getElementsByTagName("body")[0] || doc.body))) { // function is fired after onload, e.g. when script is inserted dynamically 
90             callDomLoadFunctions();
91         }
92         if (!isDomLoaded) {
93             if (typeof doc.addEventListener != UNDEF) {
94                 doc.addEventListener("DOMContentLoaded", callDomLoadFunctions, false);
95             }       
96             if (ua.ie && ua.win) {
97                 doc.attachEvent(ON_READY_STATE_CHANGE, function() {
98                     if (doc.readyState == "complete") {
99                         doc.detachEvent(ON_READY_STATE_CHANGE, arguments.callee);
100                         callDomLoadFunctions();
101                     }
102                 });
103                 if (win == top) { // if not inside an iframe
104                     (function(){
105                         if (isDomLoaded) { return; }
106                         try {
107                             doc.documentElement.doScroll("left");
108                         }
109                         catch(e) {
110                             setTimeout(arguments.callee, 0);
111                             return;
112                         }
113                         callDomLoadFunctions();
114                     })();
115                 }
116             }
117             if (ua.wk) {
118                 (function(){
119                     if (isDomLoaded) { return; }
120                     if (!(/loaded|complete/).test(doc.readyState)) {
121                         setTimeout(arguments.callee, 0);
122                         return;
123                     }
124                     callDomLoadFunctions();
125                 })();
126             }
127             addLoadEvent(callDomLoadFunctions);
128         }
129     }();
130     
131     function callDomLoadFunctions() {
132         if (isDomLoaded) { return; }
133         try { // test if we can really add/remove elements to/from the DOM; we don't want to fire it too early
134             var t = doc.getElementsByTagName("body")[0].appendChild(createElement("span"));
135             t.parentNode.removeChild(t);
136         }
137         catch (e) { return; }
138         isDomLoaded = true;
139         var dl = domLoadFnArr.length;
140         for (var i = 0; i < dl; i++) {
141             domLoadFnArr[i]();
142         }
143     }
144     
145     function addDomLoadEvent(fn) {
146         if (isDomLoaded) {
147             fn();
148         }
149         else { 
150             domLoadFnArr[domLoadFnArr.length] = fn; // Array.push() is only available in IE5.5+
151         }
152     }
153     
154     /* Cross-browser onload
155         - Based on James Edwards' solution: http://brothercake.com/site/resources/scripts/onload/
156         - Will fire an event as soon as a web page including all of its assets are loaded 
157      */
158     function addLoadEvent(fn) {
159         if (typeof win.addEventListener != UNDEF) {
160             win.addEventListener("load", fn, false);
161         }
162         else if (typeof doc.addEventListener != UNDEF) {
163             doc.addEventListener("load", fn, false);
164         }
165         else if (typeof win.attachEvent != UNDEF) {
166             addListener(win, "onload", fn);
167         }
168         else if (typeof win.onload == "function") {
169             var fnOld = win.onload;
170             win.onload = function() {
171                 fnOld();
172                 fn();
173             };
174         }
175         else {
176             win.onload = fn;
177         }
178     }
179     
180     /* Main function
181         - Will preferably execute onDomLoad, otherwise onload (as a fallback)
182     */
183     function main() { 
184         if (plugin) {
185             testPlayerVersion();
186         }
187         else {
188             matchVersions();
189         }
190     }
191     
192     /* Detect the Flash Player version for non-Internet Explorer browsers
193         - Detecting the plug-in version via the object element is more precise than using the plugins collection item's description:
194           a. Both release and build numbers can be detected
195           b. Avoid wrong descriptions by corrupt installers provided by Adobe
196           c. Avoid wrong descriptions by multiple Flash Player entries in the plugin Array, caused by incorrect browser imports
197         - Disadvantage of this method is that it depends on the availability of the DOM, while the plugins collection is immediately available
198     */
199     function testPlayerVersion() {
200         var b = doc.getElementsByTagName("body")[0];
201         var o = createElement(OBJECT);
202         o.setAttribute("type", FLASH_MIME_TYPE);
203         var t = b.appendChild(o);
204         if (t) {
205             var counter = 0;
206             (function(){
207                 if (typeof t.GetVariable != UNDEF) {
208                     var d = t.GetVariable("$version");
209                     if (d) {
210                         d = d.split(" ")[1].split(",");
211                         ua.pv = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
212                     }
213                 }
214                 else if (counter < 10) {
215                     counter++;
216                     setTimeout(arguments.callee, 10);
217                     return;
218                 }
219                 b.removeChild(o);
220                 t = null;
221                 matchVersions();
222             })();
223         }
224         else {
225             matchVersions();
226         }
227     }
228     
229     /* Perform Flash Player and SWF version matching; static publishing only
230     */
231     function matchVersions() {
232         var rl = regObjArr.length;
233         if (rl > 0) {
234             for (var i = 0; i < rl; i++) { // for each registered object element
235                 var id = regObjArr[i].id;
236                 var cb = regObjArr[i].callbackFn;
237                 var cbObj = {success:false, id:id};
238                 if (ua.pv[0] > 0) {
239                     var obj = getElementById(id);
240                     if (obj) {
241                         if (hasPlayerVersion(regObjArr[i].swfVersion) && !(ua.wk && ua.wk < 312)) { // Flash Player version >= published SWF version: Houston, we have a match!
242                             setVisibility(id, true);
243                             if (cb) {
244                                 cbObj.success = true;
245                                 cbObj.ref = getObjectById(id);
246                                 cb(cbObj);
247                             }
248                         }
249                         else if (regObjArr[i].expressInstall && canExpressInstall()) { // show the Adobe Express Install dialog if set by the web page author and if supported
250                             var att = {};
251                             att.data = regObjArr[i].expressInstall;
252                             att.width = obj.getAttribute("width") || "0";
253                             att.height = obj.getAttribute("height") || "0";
254                             if (obj.getAttribute("class")) { att.styleclass = obj.getAttribute("class"); }
255                             if (obj.getAttribute("align")) { att.align = obj.getAttribute("align"); }
256                             // parse HTML object param element's name-value pairs
257                             var par = {};
258                             var p = obj.getElementsByTagName("param");
259                             var pl = p.length;
260                             for (var j = 0; j < pl; j++) {
261                                 if (p[j].getAttribute("name").toLowerCase() != "movie") {
262                                     par[p[j].getAttribute("name")] = p[j].getAttribute("value");
263                                 }
264                             }
265                             showExpressInstall(att, par, id, cb);
266                         }
267                         else { // Flash Player and SWF version mismatch or an older Webkit engine that ignores the HTML object element's nested param elements: display alternative content instead of SWF
268                             displayAltContent(obj);
269                             if (cb) { cb(cbObj); }
270                         }
271                     }
272                 }
273                 else {  // if no Flash Player is installed or the fp version cannot be detected we let the HTML object element do its job (either show a SWF or alternative content)
274                     setVisibility(id, true);
275                     if (cb) {
276                         var o = getObjectById(id); // test whether there is an HTML object element or not
277                         if (o && typeof o.SetVariable != UNDEF) { 
278                             cbObj.success = true;
279                             cbObj.ref = o;
280                         }
281                         cb(cbObj);
282                     }
283                 }
284             }
285         }
286     }
287     
288     function getObjectById(objectIdStr) {
289         var r = null;
290         var o = getElementById(objectIdStr);
291         if (o && o.nodeName == "OBJECT") {
292             if (typeof o.SetVariable != UNDEF) {
293                 r = o;
294             }
295             else {
296                 var n = o.getElementsByTagName(OBJECT)[0];
297                 if (n) {
298                     r = n;
299                 }
300             }
301         }
302         return r;
303     }
304     
305     /* Requirements for Adobe Express Install
306         - only one instance can be active at a time
307         - fp 6.0.65 or higher
308         - Win/Mac OS only
309         - no Webkit engines older than version 312
310     */
311     function canExpressInstall() {
312         return !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac) && !(ua.wk && ua.wk < 312);
313     }
314     
315     /* Show the Adobe Express Install dialog
316         - Reference: http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=6a253b75
317     */
318     function showExpressInstall(att, par, replaceElemIdStr, callbackFn) {
319         isExpressInstallActive = true;
320         storedCallbackFn = callbackFn || null;
321         storedCallbackObj = {success:false, id:replaceElemIdStr};
322         var obj = getElementById(replaceElemIdStr);
323         if (obj) {
324             if (obj.nodeName == "OBJECT") { // static publishing
325                 storedAltContent = abstractAltContent(obj);
326                 storedAltContentId = null;
327             }
328             else { // dynamic publishing
329                 storedAltContent = obj;
330                 storedAltContentId = replaceElemIdStr;
331             }
332             att.id = EXPRESS_INSTALL_ID;
333             if (typeof att.width == UNDEF || (!(/%$/).test(att.width) && parseInt(att.width, 10) < 310)) {
334                 att.width = "310";
335             }
336             
337             if (typeof att.height == UNDEF || (!(/%$/).test(att.height) && parseInt(att.height, 10) < 137)) {
338                 att.height = "137";
339             }
340             doc.title = doc.title.slice(0, 47) + " - Flash Player Installation";
341             var pt = ua.ie && ua.win ? "ActiveX" : "PlugIn",
342                 fv = "MMredirectURL=" + win.location.toString().replace(/&/g,"%26") + "&MMplayerType=" + pt + "&MMdoctitle=" + doc.title;
343             if (typeof par.flashvars != UNDEF) {
344                 par.flashvars += "&" + fv;
345             }
346             else {
347                 par.flashvars = fv;
348             }
349             // IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it,
350             // because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work
351             if (ua.ie && ua.win && obj.readyState != 4) {
352                 var newObj = createElement("div");
353                 replaceElemIdStr += "SWFObjectNew";
354                 newObj.setAttribute("id", replaceElemIdStr);
355                 obj.parentNode.insertBefore(newObj, obj); // insert placeholder div that will be replaced by the object element that loads expressinstall.swf
356                 obj.style.display = "none";
357                 (function(){
358                     if (obj.readyState == 4) {
359                         obj.parentNode.removeChild(obj);
360                     }
361                     else {
362                         setTimeout(arguments.callee, 10);
363                     }
364                 })();
365             }
366             createSWF(att, par, replaceElemIdStr);
367         }
368     }
369     
370     /* Functions to abstract and display alternative content
371     */
372     function displayAltContent(obj) {
373         if (ua.ie && ua.win && obj.readyState != 4) {
374             // IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it,
375             // because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work
376             var el = createElement("div");
377             obj.parentNode.insertBefore(el, obj); // insert placeholder div that will be replaced by the alternative content
378             el.parentNode.replaceChild(abstractAltContent(obj), el);
379             obj.style.display = "none";
380             (function(){
381                 if (obj.readyState == 4) {
382                     obj.parentNode.removeChild(obj);
383                 }
384                 else {
385                     setTimeout(arguments.callee, 10);
386                 }
387             })();
388         }
389         else {
390             obj.parentNode.replaceChild(abstractAltContent(obj), obj);
391         }
392     } 
393
394     function abstractAltContent(obj) {
395         var ac = createElement("div");
396         if (ua.win && ua.ie) {
397             ac.innerHTML = obj.innerHTML;
398         }
399         else {
400             var nestedObj = obj.getElementsByTagName(OBJECT)[0];
401             if (nestedObj) {
402                 var c = nestedObj.childNodes;
403                 if (c) {
404                     var cl = c.length;
405                     for (var i = 0; i < cl; i++) {
406                         if (!(c[i].nodeType == 1 && c[i].nodeName == "PARAM") && !(c[i].nodeType == 8)) {
407                             ac.appendChild(c[i].cloneNode(true));
408                         }
409                     }
410                 }
411             }
412         }
413         return ac;
414     }
415     
416     /* Cross-browser dynamic SWF creation
417     */
418     function createSWF(attObj, parObj, id) {
419         var r, el = getElementById(id);
420         if (ua.wk && ua.wk < 312) { return r; }
421         if (el) {
422             if (typeof attObj.id == UNDEF) { // if no 'id' is defined for the object element, it will inherit the 'id' from the alternative content
423                 attObj.id = id;
424             }
425             if (ua.ie && ua.win) { // Internet Explorer + the HTML object element + W3C DOM methods do not combine: fall back to outerHTML
426                 var att = "";
427                 for (var i in attObj) {
428                     if (attObj[i] != Object.prototype[i]) { // filter out prototype additions from other potential libraries
429                         if (i.toLowerCase() == "data") {
430                             parObj.movie = attObj[i];
431                         }
432                         else if (i.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
433                             att += ' class="' + attObj[i] + '"';
434                         }
435                         else if (i.toLowerCase() != "classid") {
436                             att += ' ' + i + '="' + attObj[i] + '"';
437                         }
438                     }
439                 }
440                 var par = "";
441                 for (var j in parObj) {
442                     if (parObj[j] != Object.prototype[j]) { // filter out prototype additions from other potential libraries
443                         par += '<param name="' + j + '" value="' + parObj[j] + '" />';
444                     }
445                 }
446                 el.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + att + '>' + par + '</object>';
447                 objIdArr[objIdArr.length] = attObj.id; // stored to fix object 'leaks' on unload (dynamic publishing only)
448                 r = getElementById(attObj.id);  
449             }
450             else { // well-behaving browsers
451                 var o = createElement(OBJECT);
452                 o.setAttribute("type", FLASH_MIME_TYPE);
453                 for (var m in attObj) {
454                     if (attObj[m] != Object.prototype[m]) { // filter out prototype additions from other potential libraries
455                         if (m.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
456                             o.setAttribute("class", attObj[m]);
457                         }
458                         else if (m.toLowerCase() != "classid") { // filter out IE specific attribute
459                             o.setAttribute(m, attObj[m]);
460                         }
461                     }
462                 }
463                 for (var n in parObj) {
464                     if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie") { // filter out prototype additions from other potential libraries and IE specific param element
465                         createObjParam(o, n, parObj[n]);
466                     }
467                 }
468                 el.parentNode.replaceChild(o, el);
469                 r = o;
470             }
471         }
472         return r;
473     }
474     
475     function createObjParam(el, pName, pValue) {
476         var p = createElement("param");
477         p.setAttribute("name", pName);  
478         p.setAttribute("value", pValue);
479         el.appendChild(p);
480     }
481     
482     /* Cross-browser SWF removal
483         - Especially needed to safely and completely remove a SWF in Internet Explorer
484     */
485     function removeSWF(id) {
486         var obj = getElementById(id);
487         if (obj && obj.nodeName == "OBJECT") {
488             if (ua.ie && ua.win) {
489                 obj.style.display = "none";
490                 (function(){
491                     if (obj.readyState == 4) {
492                         removeObjectInIE(id);
493                     }
494                     else {
495                         setTimeout(arguments.callee, 10);
496                     }
497                 })();
498             }
499             else {
500                 obj.parentNode.removeChild(obj);
501             }
502         }
503     }
504     
505     function removeObjectInIE(id) {
506         var obj = getElementById(id);
507         if (obj) {
508             for (var i in obj) {
509                 if (typeof obj[i] == "function") {
510                     obj[i] = null;
511                 }
512             }
513             obj.parentNode.removeChild(obj);
514         }
515     }
516     
517     /* Functions to optimize JavaScript compression
518     */
519     function getElementById(id) {
520         var el = null;
521         try {
522             el = doc.getElementById(id);
523         }
524         catch (e) {}
525         return el;
526     }
527     
528     function createElement(el) {
529         return doc.createElement(el);
530     }
531     
532     /* Updated attachEvent function for Internet Explorer
533         - Stores attachEvent information in an Array, so on unload the detachEvent functions can be called to avoid memory leaks
534     */  
535     function addListener(target, eventType, fn) {
536         target.attachEvent(eventType, fn);
537         listenersArr[listenersArr.length] = [target, eventType, fn];
538     }
539     
540     /* Flash Player and SWF content version matching
541     */
542     function hasPlayerVersion(rv) {
543         var pv = ua.pv, v = rv.split(".");
544         v[0] = parseInt(v[0], 10);
545         v[1] = parseInt(v[1], 10) || 0; // supports short notation, e.g. "9" instead of "9.0.0"
546         v[2] = parseInt(v[2], 10) || 0;
547         return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false;
548     }
549     
550     /* Cross-browser dynamic CSS creation
551         - Based on Bobby van der Sluis' solution: http://www.bobbyvandersluis.com/articles/dynamicCSS.php
552     */  
553     function createCSS(sel, decl, media, newStyle) {
554         if (ua.ie && ua.mac) { return; }
555         var h = doc.getElementsByTagName("head")[0];
556         if (!h) { return; } // to also support badly authored HTML pages that lack a head element
557         var m = (media && typeof media == "string") ? media : "screen";
558         if (newStyle) {
559             dynamicStylesheet = null;
560             dynamicStylesheetMedia = null;
561         }
562         if (!dynamicStylesheet || dynamicStylesheetMedia != m) { 
563             // create dynamic stylesheet + get a global reference to it
564             var s = createElement("style");
565             s.setAttribute("type", "text/css");
566             s.setAttribute("media", m);
567             dynamicStylesheet = h.appendChild(s);
568             if (ua.ie && ua.win && typeof doc.styleSheets != UNDEF && doc.styleSheets.length > 0) {
569                 dynamicStylesheet = doc.styleSheets[doc.styleSheets.length - 1];
570             }
571             dynamicStylesheetMedia = m;
572         }
573         // add style rule
574         if (ua.ie && ua.win) {
575             if (dynamicStylesheet && typeof dynamicStylesheet.addRule == OBJECT) {
576                 dynamicStylesheet.addRule(sel, decl);
577             }
578         }
579         else {
580             if (dynamicStylesheet && typeof doc.createTextNode != UNDEF) {
581                 dynamicStylesheet.appendChild(doc.createTextNode(sel + " {" + decl + "}"));
582             }
583         }
584     }
585     
586     function setVisibility(id, isVisible) {
587         if (!autoHideShow) { return; }
588         var v = isVisible ? "visible" : "hidden";
589         if (isDomLoaded && getElementById(id)) {
590             getElementById(id).style.visibility = v;
591         }
592         else {
593             createCSS("#" + id, "visibility:" + v);
594         }
595     }
596
597     /* Filter to avoid XSS attacks
598     */
599     function urlEncodeIfNecessary(s) {
600         var regex = /[\\\"<>\.;]/;
601         var hasBadChars = regex.exec(s) != null;
602         return hasBadChars && typeof encodeURIComponent != UNDEF ? encodeURIComponent(s) : s;
603     }
604     
605     /* Release memory to avoid memory leaks caused by closures, fix hanging audio/video threads and force open sockets/NetConnections to disconnect (Internet Explorer only)
606     */
607     var cleanup = function() {
608         if (ua.ie && ua.win) {
609             window.attachEvent("onunload", function() {
610                 // remove listeners to avoid memory leaks
611                 var ll = listenersArr.length;
612                 for (var i = 0; i < ll; i++) {
613                     listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]);
614                 }
615                 // cleanup dynamically embedded objects to fix audio/video threads and force open sockets and NetConnections to disconnect
616                 var il = objIdArr.length;
617                 for (var j = 0; j < il; j++) {
618                     removeSWF(objIdArr[j]);
619                 }
620                 // cleanup library's main closures to avoid memory leaks
621                 for (var k in ua) {
622                     ua[k] = null;
623                 }
624                 ua = null;
625                 for (var l in swfobject) {
626                     swfobject[l] = null;
627                 }
628                 swfobject = null;
629             });
630         }
631     }();
632     
633     return {
634         /* Public API
635             - Reference: http://code.google.com/p/swfobject/wiki/documentation
636         */ 
637         registerObject: function(objectIdStr, swfVersionStr, xiSwfUrlStr, callbackFn) {
638             if (ua.w3 && objectIdStr && swfVersionStr) {
639                 var regObj = {};
640                 regObj.id = objectIdStr;
641                 regObj.swfVersion = swfVersionStr;
642                 regObj.expressInstall = xiSwfUrlStr;
643                 regObj.callbackFn = callbackFn;
644                 regObjArr[regObjArr.length] = regObj;
645                 setVisibility(objectIdStr, false);
646             }
647             else if (callbackFn) {
648                 callbackFn({success:false, id:objectIdStr});
649             }
650         },
651         
652         getObjectById: function(objectIdStr) {
653             if (ua.w3) {
654                 return getObjectById(objectIdStr);
655             }
656         },
657         
658         embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj, callbackFn) {
659             var callbackObj = {success:false, id:replaceElemIdStr};
660             if (ua.w3 && !(ua.wk && ua.wk < 312) && swfUrlStr && replaceElemIdStr && widthStr && heightStr && swfVersionStr) {
661                 setVisibility(replaceElemIdStr, false);
662                 addDomLoadEvent(function() {
663                     widthStr += ""; // auto-convert to string
664                     heightStr += "";
665                     var att = {};
666                     if (attObj && typeof attObj === OBJECT) {
667                         for (var i in attObj) { // copy object to avoid the use of references, because web authors often reuse attObj for multiple SWFs
668                             att[i] = attObj[i];
669                         }
670                     }
671                     att.data = swfUrlStr;
672                     att.width = widthStr;
673                     att.height = heightStr;
674                     var par = {}; 
675                     if (parObj && typeof parObj === OBJECT) {
676                         for (var j in parObj) { // copy object to avoid the use of references, because web authors often reuse parObj for multiple SWFs
677                             par[j] = parObj[j];
678                         }
679                     }
680                     if (flashvarsObj && typeof flashvarsObj === OBJECT) {
681                         for (var k in flashvarsObj) { // copy object to avoid the use of references, because web authors often reuse flashvarsObj for multiple SWFs
682                             if (typeof par.flashvars != UNDEF) {
683                                 par.flashvars += "&" + k + "=" + flashvarsObj[k];
684                             }
685                             else {
686                                 par.flashvars = k + "=" + flashvarsObj[k];
687                             }
688                         }
689                     }
690                     if (hasPlayerVersion(swfVersionStr)) { // create SWF
691                         var obj = createSWF(att, par, replaceElemIdStr);
692                         if (att.id == replaceElemIdStr) {
693                             setVisibility(replaceElemIdStr, true);
694                         }
695                         callbackObj.success = true;
696                         callbackObj.ref = obj;
697                     }
698                     else if (xiSwfUrlStr && canExpressInstall()) { // show Adobe Express Install
699                         att.data = xiSwfUrlStr;
700                         showExpressInstall(att, par, replaceElemIdStr, callbackFn);
701                         return;
702                     }
703                     else { // show alternative content
704                         setVisibility(replaceElemIdStr, true);
705                     }
706                     if (callbackFn) { callbackFn(callbackObj); }
707                 });
708             }
709             else if (callbackFn) { callbackFn(callbackObj); }
710         },
711         
712         switchOffAutoHideShow: function() {
713             autoHideShow = false;
714         },
715         
716         ua: ua,
717         
718         getFlashPlayerVersion: function() {
719             return { major:ua.pv[0], minor:ua.pv[1], release:ua.pv[2] };
720         },
721         
722         hasFlashPlayerVersion: hasPlayerVersion,
723         
724         createSWF: function(attObj, parObj, replaceElemIdStr) {
725             if (ua.w3) {
726                 return createSWF(attObj, parObj, replaceElemIdStr);
727             }
728             else {
729                 return undefined;
730             }
731         },
732         
733         showExpressInstall: function(att, par, replaceElemIdStr, callbackFn) {
734             if (ua.w3 && canExpressInstall()) {
735                 showExpressInstall(att, par, replaceElemIdStr, callbackFn);
736             }
737         },
738         
739         removeSWF: function(objElemIdStr) {
740             if (ua.w3) {
741                 removeSWF(objElemIdStr);
742             }
743         },
744         
745         createCSS: function(selStr, declStr, mediaStr, newStyleBoolean) {
746             if (ua.w3) {
747                 createCSS(selStr, declStr, mediaStr, newStyleBoolean);
748             }
749         },
750         
751         addDomLoadEvent: addDomLoadEvent,
752         
753         addLoadEvent: addLoadEvent,
754         
755         getQueryParamValue: function(param) {
756             var q = doc.location.search || doc.location.hash;
757             if (q) {
758                 if (/\?/.test(q)) { q = q.split("?")[1]; } // strip question mark
759                 if (param == null) {
760                     return urlEncodeIfNecessary(q);
761                 }
762                 var pairs = q.split("&");
763                 for (var i = 0; i < pairs.length; i++) {
764                     if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) {
765                         return urlEncodeIfNecessary(pairs[i].substring((pairs[i].indexOf("=") + 1)));
766                     }
767                 }
768             }
769             return "";
770         },
771         
772         // For internal usage only
773         expressInstallCallback: function() {
774             if (isExpressInstallActive) {
775                 var obj = getElementById(EXPRESS_INSTALL_ID);
776                 if (obj && storedAltContent) {
777                     obj.parentNode.replaceChild(storedAltContent, obj);
778                     if (storedAltContentId) {
779                         setVisibility(storedAltContentId, true);
780                         if (ua.ie && ua.win) { storedAltContent.style.display = "block"; }
781                     }
782                     if (storedCallbackFn) { storedCallbackFn(storedCallbackObj); }
783                 }
784                 isExpressInstallActive = false;
785             } 
786         }
787     };
788 }();
789 /**
790  * @class Ext.FlashComponent
791  * @extends Ext.BoxComponent
792  * @constructor
793  * @xtype flash
794  */
795 Ext.FlashComponent = Ext.extend(Ext.BoxComponent, {
796     /**
797      * @cfg {String} flashVersion
798      * Indicates the version the flash content was published for. Defaults to <tt>'9.0.115'</tt>.
799      */
800     flashVersion : '9.0.115',
801
802     /**
803      * @cfg {String} backgroundColor
804      * The background color of the chart. Defaults to <tt>'#ffffff'</tt>.
805      */
806     backgroundColor: '#ffffff',
807
808     /**
809      * @cfg {String} wmode
810      * The wmode of the flash object. This can be used to control layering. Defaults to <tt>'opaque'</tt>.
811      */
812     wmode: 'opaque',
813
814     /**
815      * @cfg {Object} flashVars
816      * A set of key value pairs to be passed to the flash object as flash variables. Defaults to <tt>undefined</tt>.
817      */
818     flashVars: undefined,
819
820     /**
821      * @cfg {Object} flashParams
822      * A set of key value pairs to be passed to the flash object as parameters. Possible parameters can be found here:
823      * http://kb2.adobe.com/cps/127/tn_12701.html Defaults to <tt>undefined</tt>.
824      */
825     flashParams: undefined,
826
827     /**
828      * @cfg {String} url
829      * The URL of the chart to include. Defaults to <tt>undefined</tt>.
830      */
831     url: undefined,
832     swfId : undefined,
833     swfWidth: '100%',
834     swfHeight: '100%',
835
836     /**
837      * @cfg {Boolean} expressInstall
838      * True to prompt the user to install flash if not installed. Note that this uses
839      * Ext.FlashComponent.EXPRESS_INSTALL_URL, which should be set to the local resource. Defaults to <tt>false</tt>.
840      */
841     expressInstall: false,
842
843     initComponent : function(){
844         Ext.FlashComponent.superclass.initComponent.call(this);
845
846         this.addEvents(
847             /**
848              * @event initialize
849              *
850              * @param {Chart} this
851              */
852             'initialize'
853         );
854     },
855
856     onRender : function(){
857         Ext.FlashComponent.superclass.onRender.apply(this, arguments);
858
859         var params = Ext.apply({
860             allowScriptAccess: 'always',
861             bgcolor: this.backgroundColor,
862             wmode: this.wmode
863         }, this.flashParams), vars = Ext.apply({
864             allowedDomain: document.location.hostname,
865             YUISwfId: this.getId(),
866             YUIBridgeCallback: 'Ext.FlashEventProxy.onEvent'
867         }, this.flashVars);
868
869         new swfobject.embedSWF(this.url, this.id, this.swfWidth, this.swfHeight, this.flashVersion,
870             this.expressInstall ? Ext.FlashComponent.EXPRESS_INSTALL_URL : undefined, vars, params);
871
872         this.swf = Ext.getDom(this.id);
873         this.el = Ext.get(this.swf);
874     },
875
876     getSwfId : function(){
877         return this.swfId || (this.swfId = "extswf" + (++Ext.Component.AUTO_ID));
878     },
879
880     getId : function(){
881         return this.id || (this.id = "extflashcmp" + (++Ext.Component.AUTO_ID));
882     },
883
884     onFlashEvent : function(e){
885         switch(e.type){
886             case "swfReady":
887                 this.initSwf();
888                 return;
889             case "log":
890                 return;
891         }
892         e.component = this;
893         this.fireEvent(e.type.toLowerCase().replace(/event$/, ''), e);
894     },
895
896     initSwf : function(){
897         this.onSwfReady(!!this.isInitialized);
898         this.isInitialized = true;
899         this.fireEvent('initialize', this);
900     },
901
902     beforeDestroy: function(){
903         if(this.rendered){
904             swfobject.removeSWF(this.swf.id);
905         }
906         Ext.FlashComponent.superclass.beforeDestroy.call(this);
907     },
908
909     onSwfReady : Ext.emptyFn
910 });
911
912 /**
913  * Sets the url for installing flash if it doesn't exist. This should be set to a local resource.
914  * @static
915  * @type String
916  */
917 Ext.FlashComponent.EXPRESS_INSTALL_URL = 'http:/' + '/swfobject.googlecode.com/svn/trunk/swfobject/expressInstall.swf';
918
919 Ext.reg('flash', Ext.FlashComponent);/**
920  * @class Ext.FlashProxy
921  * @singleton
922  */
923 Ext.FlashEventProxy = {
924     onEvent : function(id, e){
925         var fp = Ext.getCmp(id);
926         if(fp){
927             fp.onFlashEvent(e);
928         }else{
929             arguments.callee.defer(10, this, [id, e]);
930         }
931     }
932 };/**
933  * @class Ext.chart.Chart
934  * @extends Ext.FlashComponent
935  * The Ext.chart package provides the capability to visualize data with flash based charting.
936  * Each chart binds directly to an Ext.data.Store enabling automatic updates of the chart.
937  * To change the look and feel of a chart, see the {@link #chartStyle} and {@link #extraStyle} config options.
938  * @constructor
939  * @xtype chart
940  */
941
942  Ext.chart.Chart = Ext.extend(Ext.FlashComponent, {
943     refreshBuffer: 100,
944
945     /**
946      * @cfg {String} backgroundColor
947      * @hide
948      */
949
950     /**
951      * @cfg {Object} chartStyle
952      * Sets styles for this chart. This contains default styling, so modifying this property will <b>override</b>
953      * the built in styles of the chart. Use {@link #extraStyle} to add customizations to the default styling.
954      */
955     chartStyle: {
956         padding: 10,
957         animationEnabled: true,
958         font: {
959             name: 'Tahoma',
960             color: 0x444444,
961             size: 11
962         },
963         dataTip: {
964             padding: 5,
965             border: {
966                 color: 0x99bbe8,
967                 size:1
968             },
969             background: {
970                 color: 0xDAE7F6,
971                 alpha: .9
972             },
973             font: {
974                 name: 'Tahoma',
975                 color: 0x15428B,
976                 size: 10,
977                 bold: true
978             }
979         }
980     },
981
982     /**
983      * @cfg {String} url
984      * The url to load the chart from. This defaults to Ext.chart.Chart.CHART_URL, which should
985      * be modified to point to the local charts resource.
986      */
987
988     /**
989      * @cfg {Object} extraStyle
990      * Contains extra styles that will be added or overwritten to the default chartStyle. Defaults to <tt>null</tt>.
991      * For a detailed list of the options available, visit the YUI Charts site
992      * at <a href="http://developer.yahoo.com/yui/charts/#basicstyles">http://developer.yahoo.com/yui/charts/#basicstyles</a><br/>
993      * Some of the options availabe:<br />
994      * <ul style="padding:5px;padding-left:16px;list-style-type:inherit;">
995      * <li><b>padding</b> - The space around the edge of the chart's contents. Padding does not increase the size of the chart.</li>
996      * <li><b>animationEnabled</b> - A Boolean value that specifies whether marker animations are enabled or not. Enabled by default.</li>
997      * <li><b>font</b> - An Object defining the font style to be used in the chart. Defaults to <tt>{ name: 'Tahoma', color: 0x444444, size: 11 }</tt><br/>
998      *  <ul style="padding:5px;padding-left:26px;list-style-type:circle;">
999      *      <li><b>name</b> - font name</li>
1000      *      <li><b>color</b> - font color (hex code, ie: "#ff0000", "ff0000" or 0xff0000)</li>
1001      *      <li><b>size</b> - font size in points (numeric portion only, ie: 11)</li>
1002      *      <li><b>bold</b> - boolean</li>
1003      *      <li><b>italic</b> - boolean</li>
1004      *      <li><b>underline</b> - boolean</li>
1005      *  </ul>
1006      * </li>
1007      * <li><b>border</b> - An object defining the border style around the chart. The chart itself will decrease in dimensions to accomodate the border.<br/>
1008      *  <ul style="padding:5px;padding-left:26px;list-style-type:circle;">
1009      *      <li><b>color</b> - border color (hex code, ie: "#ff0000", "ff0000" or 0xff0000)</li>
1010      *      <li><b>size</b> - border size in pixels (numeric portion only, ie: 1)</li>
1011      *  </ul>
1012      * </li>
1013      * <li><b>background</b> - An object defining the background style of the chart.<br/>
1014      *  <ul style="padding:5px;padding-left:26px;list-style-type:circle;">
1015      *      <li><b>color</b> - border color (hex code, ie: "#ff0000", "ff0000" or 0xff0000)</li>
1016      *      <li><b>image</b> - an image URL. May be relative to the current document or absolute.</li>
1017      *  </ul>
1018      * </li>
1019      * <li><b>legend</b> - An object defining the legend style<br/>
1020      *  <ul style="padding:5px;padding-left:26px;list-style-type:circle;">
1021      *      <li><b>display</b> - location of the legend. Possible values are "none", "left", "right", "top", and "bottom".</li>
1022      *      <li><b>spacing</b> - an image URL. May be relative to the current document or absolute.</li>
1023      *      <li><b>padding, border, background, font</b> - same options as described above.</li>
1024      *  </ul></li>
1025      * <li><b>dataTip</b> - An object defining the style of the data tip (tooltip).<br/>
1026      *  <ul style="padding:5px;padding-left:26px;list-style-type:circle;">
1027      *      <li><b>padding, border, background, font</b> - same options as described above.</li>
1028      *  </ul></li>
1029      * <li><b>xAxis and yAxis</b> - An object defining the style of the style of either axis.<br/>
1030      *  <ul style="padding:5px;padding-left:26px;list-style-type:circle;">
1031      *      <li><b>color</b> - same option as described above.</li>
1032      *      <li><b>size</b> - same option as described above.</li>
1033      *      <li><b>showLabels</b> - boolean</li>
1034      *      <li><b>labelRotation</b> - a value in degrees from -90 through 90. Default is zero.</li>
1035      *  </ul></li>
1036      * <li><b>majorGridLines and minorGridLines</b> - An object defining the style of the style of the grid lines.<br/>
1037      *  <ul style="padding:5px;padding-left:26px;list-style-type:circle;">
1038      *      <li><b>color, size</b> - same options as described above.</li>
1039      *  </ul></li></li>
1040      * <li><b>zeroGridLine</b> - An object defining the style of the style of the zero grid line.<br/>
1041      *  <ul style="padding:5px;padding-left:26px;list-style-type:circle;">
1042      *      <li><b>color, size</b> - same options as described above.</li>
1043      *  </ul></li></li>
1044      * <li><b>majorTicks and minorTicks</b> - An object defining the style of the style of ticks in the chart.<br/>
1045      *  <ul style="padding:5px;padding-left:26px;list-style-type:circle;">
1046      *      <li><b>color, size</b> - same options as described above.</li>
1047      *      <li><b>length</b> - the length of each tick in pixels extending from the axis.</li>
1048      *      <li><b>display</b> - how the ticks are drawn. Possible values are "none", "inside", "outside", and "cross".</li>
1049      *  </ul></li></li>
1050      * </ul>
1051      */
1052     extraStyle: null,
1053
1054     /**
1055      * @cfg {Object} seriesStyles
1056      * Contains styles to apply to the series after a refresh. Defaults to <tt>null</tt>.
1057      */
1058     seriesStyles: null,
1059
1060     /**
1061      * @cfg {Boolean} disableCaching
1062      * True to add a "cache buster" to the end of the chart url. Defaults to true for Opera and IE.
1063      */
1064     disableCaching: Ext.isIE || Ext.isOpera,
1065     disableCacheParam: '_dc',
1066
1067     initComponent : function(){
1068         Ext.chart.Chart.superclass.initComponent.call(this);
1069         if(!this.url){
1070             this.url = Ext.chart.Chart.CHART_URL;
1071         }
1072         if(this.disableCaching){
1073             this.url = Ext.urlAppend(this.url, String.format('{0}={1}', this.disableCacheParam, new Date().getTime()));
1074         }
1075         this.addEvents(
1076             'itemmouseover',
1077             'itemmouseout',
1078             'itemclick',
1079             'itemdoubleclick',
1080             'itemdragstart',
1081             'itemdrag',
1082             'itemdragend',
1083             /**
1084              * @event beforerefresh
1085              * Fires before a refresh to the chart data is called.  If the beforerefresh handler returns
1086              * <tt>false</tt> the {@link #refresh} action will be cancelled.
1087              * @param {Chart} this
1088              */
1089             'beforerefresh',
1090             /**
1091              * @event refresh
1092              * Fires after the chart data has been refreshed.
1093              * @param {Chart} this
1094              */
1095             'refresh'
1096         );
1097         this.store = Ext.StoreMgr.lookup(this.store);
1098     },
1099
1100     /**
1101      * Sets a single style value on the Chart instance.
1102      *
1103      * @param name {String} Name of the Chart style value to change.
1104      * @param value {Object} New value to pass to the Chart style.
1105      */
1106      setStyle: function(name, value){
1107          this.swf.setStyle(name, Ext.encode(value));
1108      },
1109
1110     /**
1111      * Resets all styles on the Chart instance.
1112      *
1113      * @param styles {Object} Initializer for all Chart styles.
1114      */
1115     setStyles: function(styles){
1116         this.swf.setStyles(Ext.encode(styles));
1117     },
1118
1119     /**
1120      * Sets the styles on all series in the Chart.
1121      *
1122      * @param styles {Array} Initializer for all Chart series styles.
1123      */
1124     setSeriesStyles: function(styles){
1125         this.seriesStyles = styles;
1126         var s = [];
1127         Ext.each(styles, function(style){
1128             s.push(Ext.encode(style));
1129         });
1130         this.swf.setSeriesStyles(s);
1131     },
1132
1133     setCategoryNames : function(names){
1134         this.swf.setCategoryNames(names);
1135     },
1136
1137     setLegendRenderer : function(fn, scope){
1138         var chart = this;
1139         scope = scope || chart;
1140         chart.removeFnProxy(chart.legendFnName);
1141         chart.legendFnName = chart.createFnProxy(function(name){
1142             return fn.call(scope, name);
1143         });
1144         chart.swf.setLegendLabelFunction(chart.legendFnName);
1145     },
1146
1147     setTipRenderer : function(fn, scope){
1148         var chart = this;
1149         scope = scope || chart;
1150         chart.removeFnProxy(chart.tipFnName);
1151         chart.tipFnName = chart.createFnProxy(function(item, index, series){
1152             var record = chart.store.getAt(index);
1153             return fn.call(scope, chart, record, index, series);
1154         });
1155         chart.swf.setDataTipFunction(chart.tipFnName);
1156     },
1157
1158     setSeries : function(series){
1159         this.series = series;
1160         this.refresh();
1161     },
1162
1163     /**
1164      * Changes the data store bound to this chart and refreshes it.
1165      * @param {Store} store The store to bind to this chart
1166      */
1167     bindStore : function(store, initial){
1168         if(!initial && this.store){
1169             if(store !== this.store && this.store.autoDestroy){
1170                 this.store.destroy();
1171             }else{
1172                 this.store.un("datachanged", this.refresh, this);
1173                 this.store.un("add", this.delayRefresh, this);
1174                 this.store.un("remove", this.delayRefresh, this);
1175                 this.store.un("update", this.delayRefresh, this);
1176                 this.store.un("clear", this.refresh, this);
1177             }
1178         }
1179         if(store){
1180             store = Ext.StoreMgr.lookup(store);
1181             store.on({
1182                 scope: this,
1183                 datachanged: this.refresh,
1184                 add: this.delayRefresh,
1185                 remove: this.delayRefresh,
1186                 update: this.delayRefresh,
1187                 clear: this.refresh
1188             });
1189         }
1190         this.store = store;
1191         if(store && !initial){
1192             this.refresh();
1193         }
1194     },
1195
1196     onSwfReady : function(isReset){
1197         Ext.chart.Chart.superclass.onSwfReady.call(this, isReset);
1198         var ref;
1199         this.swf.setType(this.type);
1200
1201         if(this.chartStyle){
1202             this.setStyles(Ext.apply({}, this.extraStyle, this.chartStyle));
1203         }
1204
1205         if(this.categoryNames){
1206             this.setCategoryNames(this.categoryNames);
1207         }
1208
1209         if(this.tipRenderer){
1210             ref = this.getFunctionRef(this.tipRenderer);
1211             this.setTipRenderer(ref.fn, ref.scope);
1212         }
1213         if(this.legendRenderer){
1214             ref = this.getFunctionRef(this.legendRenderer);
1215             this.setLegendRenderer(ref.fn, ref.scope);
1216         }
1217         if(!isReset){
1218             this.bindStore(this.store, true);
1219         }
1220         this.refresh.defer(10, this);
1221     },
1222
1223     delayRefresh : function(){
1224         if(!this.refreshTask){
1225             this.refreshTask = new Ext.util.DelayedTask(this.refresh, this);
1226         }
1227         this.refreshTask.delay(this.refreshBuffer);
1228     },
1229
1230     refresh : function(){
1231         if(this.fireEvent('beforerefresh', this) !== false){
1232             var styleChanged = false;
1233             // convert the store data into something YUI charts can understand
1234             var data = [], rs = this.store.data.items;
1235             for(var j = 0, len = rs.length; j < len; j++){
1236                 data[j] = rs[j].data;
1237             }
1238             //make a copy of the series definitions so that we aren't
1239             //editing them directly.
1240             var dataProvider = [];
1241             var seriesCount = 0;
1242             var currentSeries = null;
1243             var i = 0;
1244             if(this.series){
1245                 seriesCount = this.series.length;
1246                 for(i = 0; i < seriesCount; i++){
1247                     currentSeries = this.series[i];
1248                     var clonedSeries = {};
1249                     for(var prop in currentSeries){
1250                         if(prop == "style" && currentSeries.style !== null){
1251                             clonedSeries.style = Ext.encode(currentSeries.style);
1252                             styleChanged = true;
1253                             //we don't want to modify the styles again next time
1254                             //so null out the style property.
1255                             // this causes issues
1256                             // currentSeries.style = null;
1257                         } else{
1258                             clonedSeries[prop] = currentSeries[prop];
1259                         }
1260                     }
1261                     dataProvider.push(clonedSeries);
1262                 }
1263             }
1264
1265             if(seriesCount > 0){
1266                 for(i = 0; i < seriesCount; i++){
1267                     currentSeries = dataProvider[i];
1268                     if(!currentSeries.type){
1269                         currentSeries.type = this.type;
1270                     }
1271                     currentSeries.dataProvider = data;
1272                 }
1273             } else{
1274                 dataProvider.push({type: this.type, dataProvider: data});
1275             }
1276             this.swf.setDataProvider(dataProvider);
1277             if(this.seriesStyles){
1278                 this.setSeriesStyles(this.seriesStyles);
1279             }
1280             this.fireEvent('refresh', this);
1281         }
1282     },
1283
1284     // private
1285     createFnProxy : function(fn){
1286         var fnName = 'extFnProxy' + (++Ext.chart.Chart.PROXY_FN_ID);
1287         Ext.chart.Chart.proxyFunction[fnName] = fn;
1288         return 'Ext.chart.Chart.proxyFunction.' + fnName;
1289     },
1290
1291     // private
1292     removeFnProxy : function(fn){
1293         if(!Ext.isEmpty(fn)){
1294             fn = fn.replace('Ext.chart.Chart.proxyFunction.', '');
1295             delete Ext.chart.Chart.proxyFunction[fn];
1296         }
1297     },
1298
1299     // private
1300     getFunctionRef : function(val){
1301         if(Ext.isFunction(val)){
1302             return {
1303                 fn: val,
1304                 scope: this
1305             };
1306         }else{
1307             return {
1308                 fn: val.fn,
1309                 scope: val.scope || this
1310             };
1311         }
1312     },
1313
1314     // private
1315     onDestroy: function(){
1316         if (this.refreshTask && this.refreshTask.cancel){
1317             this.refreshTask.cancel();
1318         }
1319         Ext.chart.Chart.superclass.onDestroy.call(this);
1320         this.bindStore(null);
1321         this.removeFnProxy(this.tipFnName);
1322         this.removeFnProxy(this.legendFnName);
1323     }
1324 });
1325 Ext.reg('chart', Ext.chart.Chart);
1326 Ext.chart.Chart.PROXY_FN_ID = 0;
1327 Ext.chart.Chart.proxyFunction = {};
1328
1329 /**
1330  * Sets the url to load the chart from. This should be set to a local resource.
1331  * @static
1332  * @type String
1333  */
1334 Ext.chart.Chart.CHART_URL = 'http:/' + '/yui.yahooapis.com/2.8.2/build/charts/assets/charts.swf';
1335
1336 /**
1337  * @class Ext.chart.PieChart
1338  * @extends Ext.chart.Chart
1339  * @constructor
1340  * @xtype piechart
1341  */
1342 Ext.chart.PieChart = Ext.extend(Ext.chart.Chart, {
1343     type: 'pie',
1344
1345     onSwfReady : function(isReset){
1346         Ext.chart.PieChart.superclass.onSwfReady.call(this, isReset);
1347
1348         this.setDataField(this.dataField);
1349         this.setCategoryField(this.categoryField);
1350     },
1351
1352     setDataField : function(field){
1353         this.dataField = field;
1354         this.swf.setDataField(field);
1355     },
1356
1357     setCategoryField : function(field){
1358         this.categoryField = field;
1359         this.swf.setCategoryField(field);
1360     }
1361 });
1362 Ext.reg('piechart', Ext.chart.PieChart);
1363
1364 /**
1365  * @class Ext.chart.CartesianChart
1366  * @extends Ext.chart.Chart
1367  * @constructor
1368  * @xtype cartesianchart
1369  */
1370 Ext.chart.CartesianChart = Ext.extend(Ext.chart.Chart, {
1371     onSwfReady : function(isReset){
1372         Ext.chart.CartesianChart.superclass.onSwfReady.call(this, isReset);
1373         this.labelFn = [];
1374         if(this.xField){
1375             this.setXField(this.xField);
1376         }
1377         if(this.yField){
1378             this.setYField(this.yField);
1379         }
1380         if(this.xAxis){
1381             this.setXAxis(this.xAxis);
1382         }
1383         if(this.xAxes){
1384             this.setXAxes(this.xAxes);
1385         }
1386         if(this.yAxis){
1387             this.setYAxis(this.yAxis);
1388         }
1389         if(this.yAxes){
1390             this.setYAxes(this.yAxes);
1391         }
1392         if(Ext.isDefined(this.constrainViewport)){
1393             this.swf.setConstrainViewport(this.constrainViewport);
1394         }
1395     },
1396
1397     setXField : function(value){
1398         this.xField = value;
1399         this.swf.setHorizontalField(value);
1400     },
1401
1402     setYField : function(value){
1403         this.yField = value;
1404         this.swf.setVerticalField(value);
1405     },
1406
1407     setXAxis : function(value){
1408         this.xAxis = this.createAxis('xAxis', value);
1409         this.swf.setHorizontalAxis(this.xAxis);
1410     },
1411
1412     setXAxes : function(value){
1413         var axis;
1414         for(var i = 0; i < value.length; i++) {
1415             axis = this.createAxis('xAxis' + i, value[i]);
1416             this.swf.setHorizontalAxis(axis);
1417         }
1418     },
1419
1420     setYAxis : function(value){
1421         this.yAxis = this.createAxis('yAxis', value);
1422         this.swf.setVerticalAxis(this.yAxis);
1423     },
1424
1425     setYAxes : function(value){
1426         var axis;
1427         for(var i = 0; i < value.length; i++) {
1428             axis = this.createAxis('yAxis' + i, value[i]);
1429             this.swf.setVerticalAxis(axis);
1430         }
1431     },
1432
1433     createAxis : function(axis, value){
1434         var o = Ext.apply({}, value),
1435             ref,
1436             old;
1437
1438         if(this[axis]){
1439             old = this[axis].labelFunction;
1440             this.removeFnProxy(old);
1441             this.labelFn.remove(old);
1442         }
1443         if(o.labelRenderer){
1444             ref = this.getFunctionRef(o.labelRenderer);
1445             o.labelFunction = this.createFnProxy(function(v){
1446                 return ref.fn.call(ref.scope, v);
1447             });
1448             delete o.labelRenderer;
1449             this.labelFn.push(o.labelFunction);
1450         }
1451         if(axis.indexOf('xAxis') > -1 && o.position == 'left'){
1452             o.position = 'bottom';
1453         }
1454         return o;
1455     },
1456
1457     onDestroy : function(){
1458         Ext.chart.CartesianChart.superclass.onDestroy.call(this);
1459         Ext.each(this.labelFn, function(fn){
1460             this.removeFnProxy(fn);
1461         }, this);
1462     }
1463 });
1464 Ext.reg('cartesianchart', Ext.chart.CartesianChart);
1465
1466 /**
1467  * @class Ext.chart.LineChart
1468  * @extends Ext.chart.CartesianChart
1469  * @constructor
1470  * @xtype linechart
1471  */
1472 Ext.chart.LineChart = Ext.extend(Ext.chart.CartesianChart, {
1473     type: 'line'
1474 });
1475 Ext.reg('linechart', Ext.chart.LineChart);
1476
1477 /**
1478  * @class Ext.chart.ColumnChart
1479  * @extends Ext.chart.CartesianChart
1480  * @constructor
1481  * @xtype columnchart
1482  */
1483 Ext.chart.ColumnChart = Ext.extend(Ext.chart.CartesianChart, {
1484     type: 'column'
1485 });
1486 Ext.reg('columnchart', Ext.chart.ColumnChart);
1487
1488 /**
1489  * @class Ext.chart.StackedColumnChart
1490  * @extends Ext.chart.CartesianChart
1491  * @constructor
1492  * @xtype stackedcolumnchart
1493  */
1494 Ext.chart.StackedColumnChart = Ext.extend(Ext.chart.CartesianChart, {
1495     type: 'stackcolumn'
1496 });
1497 Ext.reg('stackedcolumnchart', Ext.chart.StackedColumnChart);
1498
1499 /**
1500  * @class Ext.chart.BarChart
1501  * @extends Ext.chart.CartesianChart
1502  * @constructor
1503  * @xtype barchart
1504  */
1505 Ext.chart.BarChart = Ext.extend(Ext.chart.CartesianChart, {
1506     type: 'bar'
1507 });
1508 Ext.reg('barchart', Ext.chart.BarChart);
1509
1510 /**
1511  * @class Ext.chart.StackedBarChart
1512  * @extends Ext.chart.CartesianChart
1513  * @constructor
1514  * @xtype stackedbarchart
1515  */
1516 Ext.chart.StackedBarChart = Ext.extend(Ext.chart.CartesianChart, {
1517     type: 'stackbar'
1518 });
1519 Ext.reg('stackedbarchart', Ext.chart.StackedBarChart);
1520
1521
1522
1523 /**
1524  * @class Ext.chart.Axis
1525  * Defines a CartesianChart's vertical or horizontal axis.
1526  * @constructor
1527  */
1528 Ext.chart.Axis = function(config){
1529     Ext.apply(this, config);
1530 };
1531
1532 Ext.chart.Axis.prototype =
1533 {
1534     /**
1535      * The type of axis.
1536      *
1537      * @property type
1538      * @type String
1539      */
1540     type: null,
1541
1542     /**
1543      * The direction in which the axis is drawn. May be "horizontal" or "vertical".
1544      *
1545      * @property orientation
1546      * @type String
1547      */
1548     orientation: "horizontal",
1549
1550     /**
1551      * If true, the items on the axis will be drawn in opposite direction.
1552      *
1553      * @property reverse
1554      * @type Boolean
1555      */
1556     reverse: false,
1557
1558     /**
1559      * A string reference to the globally-accessible function that may be called to
1560      * determine each of the label values for this axis.
1561      *
1562      * @property labelFunction
1563      * @type String
1564      */
1565     labelFunction: null,
1566
1567     /**
1568      * If true, labels that overlap previously drawn labels on the axis will be hidden.
1569      *
1570      * @property hideOverlappingLabels
1571      * @type Boolean
1572      */
1573     hideOverlappingLabels: true,
1574
1575     /**
1576      * The space, in pixels, between labels on an axis.
1577      *
1578      * @property labelSpacing
1579      * @type Number
1580      */
1581     labelSpacing: 2
1582 };
1583
1584 /**
1585  * @class Ext.chart.NumericAxis
1586  * @extends Ext.chart.Axis
1587  * A type of axis whose units are measured in numeric values.
1588  * @constructor
1589  */
1590 Ext.chart.NumericAxis = Ext.extend(Ext.chart.Axis, {
1591     type: "numeric",
1592
1593     /**
1594      * The minimum value drawn by the axis. If not set explicitly, the axis
1595      * minimum will be calculated automatically.
1596      *
1597      * @property minimum
1598      * @type Number
1599      */
1600     minimum: NaN,
1601
1602     /**
1603      * The maximum value drawn by the axis. If not set explicitly, the axis
1604      * maximum will be calculated automatically.
1605      *
1606      * @property maximum
1607      * @type Number
1608      */
1609     maximum: NaN,
1610
1611     /**
1612      * The spacing between major intervals on this axis.
1613      *
1614      * @property majorUnit
1615      * @type Number
1616      */
1617     majorUnit: NaN,
1618
1619     /**
1620      * The spacing between minor intervals on this axis.
1621      *
1622      * @property minorUnit
1623      * @type Number
1624      */
1625     minorUnit: NaN,
1626
1627     /**
1628      * If true, the labels, ticks, gridlines, and other objects will snap to the
1629      * nearest major or minor unit. If false, their position will be based on
1630      * the minimum value.
1631      *
1632      * @property snapToUnits
1633      * @type Boolean
1634      */
1635     snapToUnits: true,
1636
1637     /**
1638      * If true, and the bounds are calculated automatically, either the minimum
1639      * or maximum will be set to zero.
1640      *
1641      * @property alwaysShowZero
1642      * @type Boolean
1643      */
1644     alwaysShowZero: true,
1645
1646     /**
1647      * The scaling algorithm to use on this axis. May be "linear" or
1648      * "logarithmic".
1649      *
1650      * @property scale
1651      * @type String
1652      */
1653     scale: "linear",
1654
1655     /**
1656      * Indicates whether to round the major unit.
1657      *
1658      * @property roundMajorUnit
1659      * @type Boolean
1660      */
1661     roundMajorUnit: true,
1662
1663     /**
1664      * Indicates whether to factor in the size of the labels when calculating a
1665      * major unit.
1666      *
1667      * @property calculateByLabelSize
1668      * @type Boolean
1669      */
1670     calculateByLabelSize: true,
1671
1672     /**
1673      * Indicates the position of the axis relative to the chart
1674      *
1675      * @property position
1676      * @type String
1677      */
1678     position: 'left',
1679
1680     /**
1681      * Indicates whether to extend maximum beyond data's maximum to the nearest
1682      * majorUnit.
1683      *
1684      * @property adjustMaximumByMajorUnit
1685      * @type Boolean
1686      */
1687     adjustMaximumByMajorUnit: true,
1688
1689     /**
1690      * Indicates whether to extend the minimum beyond data's minimum to the
1691      * nearest majorUnit.
1692      *
1693      * @property adjustMinimumByMajorUnit
1694      * @type Boolean
1695      */
1696     adjustMinimumByMajorUnit: true
1697
1698 });
1699
1700 /**
1701  * @class Ext.chart.TimeAxis
1702  * @extends Ext.chart.Axis
1703  * A type of axis whose units are measured in time-based values.
1704  * @constructor
1705  */
1706 Ext.chart.TimeAxis = Ext.extend(Ext.chart.Axis, {
1707     type: "time",
1708
1709     /**
1710      * The minimum value drawn by the axis. If not set explicitly, the axis
1711      * minimum will be calculated automatically.
1712      *
1713      * @property minimum
1714      * @type Date
1715      */
1716     minimum: null,
1717
1718     /**
1719      * The maximum value drawn by the axis. If not set explicitly, the axis
1720      * maximum will be calculated automatically.
1721      *
1722      * @property maximum
1723      * @type Number
1724      */
1725     maximum: null,
1726
1727     /**
1728      * The spacing between major intervals on this axis.
1729      *
1730      * @property majorUnit
1731      * @type Number
1732      */
1733     majorUnit: NaN,
1734
1735     /**
1736      * The time unit used by the majorUnit.
1737      *
1738      * @property majorTimeUnit
1739      * @type String
1740      */
1741     majorTimeUnit: null,
1742
1743     /**
1744      * The spacing between minor intervals on this axis.
1745      *
1746      * @property majorUnit
1747      * @type Number
1748      */
1749     minorUnit: NaN,
1750
1751     /**
1752      * The time unit used by the minorUnit.
1753      *
1754      * @property majorTimeUnit
1755      * @type String
1756      */
1757     minorTimeUnit: null,
1758
1759     /**
1760      * If true, the labels, ticks, gridlines, and other objects will snap to the
1761      * nearest major or minor unit. If false, their position will be based on
1762      * the minimum value.
1763      *
1764      * @property snapToUnits
1765      * @type Boolean
1766      */
1767     snapToUnits: true,
1768
1769     /**
1770      * Series that are stackable will only stack when this value is set to true.
1771      *
1772      * @property stackingEnabled
1773      * @type Boolean
1774      */
1775     stackingEnabled: false,
1776
1777     /**
1778      * Indicates whether to factor in the size of the labels when calculating a
1779      * major unit.
1780      *
1781      * @property calculateByLabelSize
1782      * @type Boolean
1783      */
1784     calculateByLabelSize: true
1785
1786 });
1787
1788 /**
1789  * @class Ext.chart.CategoryAxis
1790  * @extends Ext.chart.Axis
1791  * A type of axis that displays items in categories.
1792  * @constructor
1793  */
1794 Ext.chart.CategoryAxis = Ext.extend(Ext.chart.Axis, {
1795     type: "category",
1796
1797     /**
1798      * A list of category names to display along this axis.
1799      *
1800      * @property categoryNames
1801      * @type Array
1802      */
1803     categoryNames: null,
1804
1805     /**
1806      * Indicates whether or not to calculate the number of categories (ticks and
1807      * labels) when there is not enough room to display all labels on the axis.
1808      * If set to true, the axis will determine the number of categories to plot.
1809      * If not, all categories will be plotted.
1810      *
1811      * @property calculateCategoryCount
1812      * @type Boolean
1813      */
1814     calculateCategoryCount: false
1815
1816 });
1817
1818 /**
1819  * @class Ext.chart.Series
1820  * Series class for the charts widget.
1821  * @constructor
1822  */
1823 Ext.chart.Series = function(config) { Ext.apply(this, config); };
1824
1825 Ext.chart.Series.prototype =
1826 {
1827     /**
1828      * The type of series.
1829      *
1830      * @property type
1831      * @type String
1832      */
1833     type: null,
1834
1835     /**
1836      * The human-readable name of the series.
1837      *
1838      * @property displayName
1839      * @type String
1840      */
1841     displayName: null
1842 };
1843
1844 /**
1845  * @class Ext.chart.CartesianSeries
1846  * @extends Ext.chart.Series
1847  * CartesianSeries class for the charts widget.
1848  * @constructor
1849  */
1850 Ext.chart.CartesianSeries = Ext.extend(Ext.chart.Series, {
1851     /**
1852      * The field used to access the x-axis value from the items from the data
1853      * source.
1854      *
1855      * @property xField
1856      * @type String
1857      */
1858     xField: null,
1859
1860     /**
1861      * The field used to access the y-axis value from the items from the data
1862      * source.
1863      *
1864      * @property yField
1865      * @type String
1866      */
1867     yField: null,
1868
1869     /**
1870      * False to not show this series in the legend. Defaults to <tt>true</tt>.
1871      *
1872      * @property showInLegend
1873      * @type Boolean
1874      */
1875     showInLegend: true,
1876
1877     /**
1878      * Indicates which axis the series will bind to
1879      *
1880      * @property axis
1881      * @type String
1882      */
1883     axis: 'primary'
1884 });
1885
1886 /**
1887  * @class Ext.chart.ColumnSeries
1888  * @extends Ext.chart.CartesianSeries
1889  * ColumnSeries class for the charts widget.
1890  * @constructor
1891  */
1892 Ext.chart.ColumnSeries = Ext.extend(Ext.chart.CartesianSeries, {
1893     type: "column"
1894 });
1895
1896 /**
1897  * @class Ext.chart.LineSeries
1898  * @extends Ext.chart.CartesianSeries
1899  * LineSeries class for the charts widget.
1900  * @constructor
1901  */
1902 Ext.chart.LineSeries = Ext.extend(Ext.chart.CartesianSeries, {
1903     type: "line"
1904 });
1905
1906 /**
1907  * @class Ext.chart.BarSeries
1908  * @extends Ext.chart.CartesianSeries
1909  * BarSeries class for the charts widget.
1910  * @constructor
1911  */
1912 Ext.chart.BarSeries = Ext.extend(Ext.chart.CartesianSeries, {
1913     type: "bar"
1914 });
1915
1916
1917 /**
1918  * @class Ext.chart.PieSeries
1919  * @extends Ext.chart.Series
1920  * PieSeries class for the charts widget.
1921  * @constructor
1922  */
1923 Ext.chart.PieSeries = Ext.extend(Ext.chart.Series, {
1924     type: "pie",
1925     dataField: null,
1926     categoryField: null
1927 });