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