function jsTracer()
{
    jsTracer.prototype.write = function(message, messageType, css)
    {
        // throw it away
    };
}
var jstracer = new jsTracer();

/**
 * jsTracer object added to the window object for convenience. */
window.jstracer = jstracer;

Ext.log = function(str) {
//    console.log(str);
};


/**
 * @name AnyChart
 * @projectDescription AnyChart JavaScript Integration Library
 * 
 * @version 2.7
 * 
 */

var com = {};
com.anychart = {};

/**
 * BrowserTypeInformation class
 * @static
 * @class BrowserTypeInformation
 * Brower information
 */
var BrowserTypeInformation = function(){};

/**
 * Is browser Internet Explorer?
 * @static
 * @field {Boolean}
 */
BrowserTypeInformation.isIE = /(msie|internet explorer)/i.test(navigator.userAgent);

/**
 * Is browser Apple Sarari?
 * @static
 * @field {Boolean}
 */
BrowserTypeInformation.isSafari = /safari/i.test(navigator.userAgent);

/**
 * Is browser Opera?
 * @static
 * @field {Boolean}
 */
BrowserTypeInformation.isOpera = (window.opera != undefined);

//---------------------------------------------------------------------
//
//						AnyChart class
//
//---------------------------------------------------------------------

/**
 * AnyChart class
 * 
 * @class AnyChart
 * @alias com.anychart.AnyChart
 * @param {String} [swfPath] path to chart swf file
 * @param {String} [preloaderSWFPath] path to chart preloader swf file
 */
com.anychart.AnyChart = function(){
	switch (arguments.length) {
		case 0:
			this.constructor();
			break;
		case 1:
			this.constructor(arguments[0]);
			break;
		case 2:
			this.constructor(arguments[0],arguments[1]);
			break;
	}
};
var AnyChart = com.anychart.AnyChart;

AnyChart._charts = {};

AnyChart.prototype = {

    //------------------------------------
    //			html wrapper
    //------------------------------------

    /**
    * chart id
    * @field {String}
    */
    id: null,

    /**
    * chart width
    * @see AnyChart.width
    * @field {String}
    */
    width: NaN,

    /**
    * chart height
    * @see AnyChart.height
    * @field {String}
    */
    height: NaN,

    quality: "high",

    /**
    * Flash movie background html color
    * @field {String}
    */
    bgColor: "#FFFFFF",

    /**
    * Path to swf file
    * @field {String}
    */
    swfFile: null,

    /**
    * Path to preloader swf file
    * @field {String}
    */
    preloaderSWFFile: null,

    /**
    * embed (or object) DOM element with chart
    * @field {Object}
    */
    flashObject: null,

    _containerNode: null,
    _containerId: null,

    _isWrited: false,

    /**
    * Text to be shown on preloader initilization
    * @field {String}
    */
    preloaderInitText: null,

    /**
    * Text to be shown while AnyChart is loading  AnyChart.Swf
    * @field {String}
    */
    preloaderLoadingText: null,

    /**
    * Text to be shownwhile AnyChart   is initializing
    * @field {String}
    */
    initText: null,

    /**
    * Text to be shown while AnyChart is loading  XML Data.
    * @field {String}
    */
    xmlLoadingText: null,

    /**
    * Text to be shown while AnyChart is loading  resources (images, etc.)
    * @field {String}
    */
    resourcesLoadingText: null,

    /**
    * Text to be shown when AnyChart gets chart without data.
    * @field {String}
    */
    noDataText: null,

    /**
    * Text to be shown when AnyChart gets no data source (neither XMLFile nor XMLText is set to chart)
    * @field {String}
    */
    waitingForDataText: null,

    /**
    * Text to be shown while AnyChart is loading chart templates
    * @field {String}
    */
    templatesLoadingText: null,

    /**
    * Sets the Window Mode property of the SWF file for transparency, layering, and 
    * positioning in the browser. Valid values of wmode are window, opaque, and transparent.
    * Set to <code>window</code> to play the SWF in its own rectangular window on a web page.
    * Set to <code>opaque</code> to hide everything on the page behind it.
    * Set to <code>transparent</code> so that the background of the HTML page shows through all transparent portions of the SWF file.
    * @field {String}
    */
    wMode: null,

    dispatchMouseEvents: true,

    _canDispatchEvent: false,
    _nonDispatcedEvents: null,
    _protocol: "http",

    constructor: function() {
        //jstracer.write('AnyChart::constructor()');
        //check protocol
        if (location.protocol == 'https:')
            this._protocol = 'https';
        else
            this._protocol = 'http';

        this.id = AnyChart.getUniqueChartId();
        switch (arguments.length) {
            case 0:
                this.swfFile = AnyChart.swfFile;
                this.preloaderSWFFile = AnyChart.preloaderSWFFile;
                break;
            case 1:
                this.swfFile = arguments[0];
                this.preloaderSWFFile = AnyChart.preloaderSWFFile;
                break;
            case 2:
                this.swfFile = arguments[0];
                this.preloaderSWFFile = arguments[1];
                break;
        }
        this.width = AnyChart.width;
        this.height = AnyChart.height;
        this.quality = 'high';
        this.bgColor = '#FFFFFF';
        this._xmlFile = null;
        this.loaded = false;
        this._listeners = new Array();
        this._loaded = false;
        this._created = false;
        this._canDispatchEvent = false;
        this._nonDispatcedEvents = new Array();
        this.wMode = null;
        this.dispatchMouseEvents = true;
        var ths = this;
        this.addEventListener('create', function(e) {
            ths._onChartLoad();
        });
        this.addEventListener('draw', function(e) {
            ths._onChartDraw();
        });
        this._xmlSource = null;
        this._isWrited = false;
        this._containerId = null;
        this._containerNode = null;

        this.preloaderInitText = AnyChart.preloaderInitText;
        this.preloaderLoadingText = AnyChart.preloaderLoadingText;
        this.initText = AnyChart.initText;
        this.xmlLoadingText = AnyChart.xmlLoadingText;
        this.resourcesLoadingText = AnyChart.resourcesLoadingText;
        this.noDataText = AnyChart.noDataText;
        this.waitingForDataText = AnyChart.waitingForDataText;
        this.templatesLoadingText = AnyChart.templatesLoadingText;

        this._enableMouseEvents = false;

        AnyChart._registerChart(this);
    },

    /**
    * Write anychart html code into page<br />
    * if target not specified - Directly write to the current window
    * else if target is String - Write to element in the current window by its id
    * else write to element in the current window by its reference
    * @method
    * @param {Object} [target]
    */
    write: function() {
        if (!this._checkPlayerVersion()) return;
        if (this._isWrited) return;
        var htmlCode = this._getFlashObjectHTML();
        if (arguments[0] == undefined) {
            this._writeToCurrentWindow(htmlCode);
        } else {
            var target = arguments[0];
            if (!BrowserTypeInformation.isIE && (!BrowserTypeInformation.isSafari && !BrowserTypeInformation.isOpera && target instanceof Window)) {
                this._writeToWindow(target, htmlCode);
            } else if (typeof (target) == 'string' || (!BrowserTypeInformation.isSafari && target instanceof String)) {
                this._writeToHTMLTarget(target, htmlCode);
            } else if (BrowserTypeInformation.isIE && target.innerHTML == undefined) {
                this._writeToWindow(target, htmlCode);
            } else {
                this._writeToHTMLTarget(target, htmlCode);
            }
        }
        this._canDispatchEvent = true;
        for (var i = 0; i < this._nonDispatcedEvents.length; i++) {
            this.dispatchEvent(this._nonDispatcedEvents[i]);
        }
        this._isWrited = true;
    },

    _writeToCurrentWindow: function(htmlCode) {
        this._writeToWindow(window, htmlCode);
    },

    _writeToWindow: function(w, htmlCode) {
        this._initFlashObject(w, htmlCode, false);
        if (w != window) {
            w.AnyChart = AnyChart;
        }
    },

    _writeToHTMLTarget: function(target, htmlCode) {
        if (typeof (target) == 'string' || (!BrowserTypeInformation.isSafari && target instanceof String)) {
            target = document.getElementById(String(target));
        }
        this._initFlashObject(target, htmlCode, true);
    },

    _createContainer: function() {
        this._containerId = AnyChart._getUniqueContainerId(this.id);
        var container = document.createElement('div');
        container.setAttribute('id', this._containerId);
        this._initPrint();
        return container;
    },

    _initFlashObject: function(htmlTarget, htmlCode, useInnerHTML) {
        var target = (BrowserTypeInformation.isIE) ? htmlTarget : this._createContainer();

        if (BrowserTypeInformation.isIE) {
            try {
                var path = document;
                var obj = target;
                var hasErrorsInTree = false;
                if (obj != undefined) {
                    obj = obj.parentNode;
                    while (obj != undefined && obj != null) {
                        if (obj.nodeName != null && obj.nodeName.toLowerCase() == 'form') {
                            if (obj.name == undefined || obj.name == null || obj.name.length == 0) {
                                hasErrorsInTree = true;
                                break;
                            } else {
                                path = path.forms[obj.name];
                            }
                        }
                        obj = obj.parentNode;
                    }
                }
            } catch (e) { }

            if (!hasErrorsInTree) {
                window[this.id] = new Object();
                window[this.id].SetReturnValue = function() { };
                try {
                    if (useInnerHTML) {
                        target.innerHTML = htmlCode;
                    } else {
                        target.document.write(htmlCode);
                    }
                } catch (e) { }
                window[this.id].SetReturnValue = null;
                var fncts = {};
                for (var j in window[this.id]) {
                    if (typeof (window[this.id][j]) == 'function')
                        fncts[j] = window[this.id][j];
                }
                window[this.id] = path[this.id];

                this.flashObject = window[this.id];
                for (var j in fncts) {
                    this._rebuildExternalInterfaceFunction(this.flashObject, j);
                }
                this._onHTMLCreate();
            }
        } else {
            target.innerHTML = htmlCode;
            this._createImage(target);
            if (useInnerHTML) {
                htmlTarget.innerHTML = '';
                htmlTarget.appendChild(target);
            } else {
                htmlTarget.document.getElementsByTagName('body')[0].appendChild(target);
            }

            this.flashObject = document.getElementById(this.id);
            this._containerNode = this.flashObject.parentNode;
            this._onHTMLCreate();
        }
    },

    _rebuildExternalInterfaceFunction: function(obj, functionName) {
        eval('obj[functionName] = function(){return eval(this.CallFunction("<invoke name=\\"' + functionName + '\\" returntype=\\"javascript\\">" + __flash__argumentsToXML(arguments,0) + "</invoke>"));}');
    },

    _getFlashObjectHTML: function() {
        return BrowserTypeInformation.isIE ? this._getObjectHTML() : this._getEmbedHTML();
    },

    _buildFlashVars: function() {
        var res = new String();
        res += '__externalObjId=' + this.id;
        if (this._xmlFile != null)
            res += '&XMLFile=' + this._xmlFile;
        if (this.preloaderSWFFile != null) {
            res += '&swffile=' + this.swfFile;
            if (this.preloaderInitText != null)
                res += '&preloaderInitText=' + this.preloaderInitText;
            if (this.preloaderLoadingText != null)
                res += '&preloaderLoadingText=' + this.preloaderLoadingText;
        }
        if (this.initText != null)
            res += '&initText=' + this.initText;
        if (this.xmlLoadingText != null)
            res += '&xmlLoadingText=' + this.xmlLoadingText;
        if (this.resourcesLoadingText != null)
            res += '&resourcesLoadingText=' + this.resourcesLoadingText;
        if (this.waitingForDataText != null)
            res += '&waitingForDataText=' + this.waitingForDataText;
        if (this.templatesLoadingText != null)
            res += '&templatesLoadingText=' + this.templatesLoadingText;
        if (this.noDataText != null)
            res += '&nodatatext=' + this.noDataText;
        if (this._enableMouseEvents)
            res += '&__enableevents=1';
        return res;
    },

    updateSize: function(width, height) {
        this.flashObject.setAttribute('width', width);
        this.flashObject.setAttribute('height', height);
    },

    _getMoviePath: function() {
        return this.preloaderSWFFile != null ? this.preloaderSWFFile : this.swfFile;
    },

    _getObjectHTML: function() {
        var source = '<obj' + 'ect id="' + this.id + '" name="' + this.id + '" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="' + this.width + '" height="' + this.height + '" codebase="' + this._protocol + '://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">';
        source += '<param name="movie" value="' + this._getMoviePath() + '" />';
        source += '<param name="bgcolor" value="' + this.bgColor + '" />';
        source += '<param name="allowScriptAccess" value="always" />';
        source += '<param name="FlashVars" value="' + this._buildFlashVars() + '" />';
        if (this.wMode != null)
            source += '<param name="wmode" value="' + this.wMode + '" />';
        source += '</obj' + 'ect>';
        return source;
    },

    _getEmbedHTML: function() {
        var source = '<embed type="application/x-shockwave-flash" pluginspage="' + this._protocol + '://www.adobe.com/go/getflashplayer" ';
        source += 'src="' + this._getMoviePath() + '" ';
        source += 'width="' + this.width + '" ';
        source += 'height="' + this.height + '" ';
        source += 'id="' + this.id + '" ';
        source += 'name="' + this.id + '" ';
        source += 'bgColor="' + this.bgColor + '" ';
        source += 'allowScriptAccess="always" ';
        if (this.wMode != null)
            source += 'wmode="' + this.wMode + '" ';
        source += 'flashvars="' + this._buildFlashVars() + '" />';
        return source;
    },

    //------------------------------------
    //			Printing
    //------------------------------------

    _onChartDraw: function() {
        //jstracer.write('AnyChart::_onChartDraw()');
        
        if (!BrowserTypeInformation.isIE) {
            this._setPrintImage();
        } else {
            this._initIEPrinting();
        }
    },

    _initIEPrinting: function() {

        var obj = this.flashObject;
        if (obj == null) return;

        window.attachEvent("onbeforeprint", function(e) {
            obj.setAttribute("tmpW", obj.width);
            obj.setAttribute("tmpH", obj.height);

            obj.width = (obj.getWidth != undefined) ? obj.getWidth() : obj.width;
            obj.height = (obj.getHeight != undefined) ? obj.getHeight() : obj.height;

            if (obj.getAttribute("tmpW").indexOf("%") != -1 ||
			    obj.getAttribute("tmpH").indexOf("%") != -1) {
                //ie percent width or height hack
                obj.focus();
            }
        });
        window.attachEvent("onafterprint", function() {
            obj.width = obj.getAttribute("tmpW");
            obj.height = obj.getAttribute("tmpH");
        });
    },

    _createNormalCSS: function() {
        var head = document.getElementsByTagName('head');
        head = ((head.length != 1) ? null : head[0]);

        if (head == null)
            return false;

        if (this._containerId == null)
            return false;

        //crete style node
        var style = document.createElement('style');
        style.setAttribute('type', 'text/css');
        style.setAttribute('media', 'screen');
        //write normal style
        var objDescriptor = 'div#' + this._containerId;
        var imgDescriptor = objDescriptor + ' img';
        var objRule = "width: " + this.width + ";\n" +
					  "height: " + this.height + ";" +
					  "padding: 0;\n" +
					  "margin: 0;";
        var imgRule = "display: none;\n" +
					  "width: " + this.width + ";" +
					  "height: " + this.height + ";";
        style.appendChild(document.createTextNode(objDescriptor + '{' + objRule + "}\n"));
        style.appendChild(document.createTextNode(imgDescriptor + '{' + imgRule + '}'));
        //add style to head
        head.appendChild(style);

        return true;
    },

    _createPrintCSS: function() {
        var head = document.getElementsByTagName('head');
        head = ((head.length != 1) ? null : head[0]);

        if (this._containerId == null)
            return false;

        //create image style node for print
        var style = document.createElement('style');
        style.setAttribute('type', 'text/css');
        style.setAttribute('media', 'print');
        //write image style
        var imgDescriptor = '#' + this._containerId + ' img';
        var imgRule = 'display: block;';
        if (this.flashObject != null &&
			this.flashObject.getWidth != undefined &&
			this.flashObject.getHeight != undefined) {
            imgRule += 'width: ' + this.flashObject.getWidth() + 'px;';
            imgRule += 'height: ' + this.flashObject.getHeight() + 'px;';
        }
        style.appendChild(document.createTextNode(imgDescriptor + '{' + imgRule + '}'));
        //write object style
        var objDescriptor = '#' + this._containerId + ' embed';
        var objRule = 'display: none;';
        style.appendChild(document.createTextNode(objDescriptor + '{' + objRule + '}'));
        //add style to head
        head.appendChild(style);
        return true;
    },

    _initPrint: function() {
        this._createNormalCSS();
        this._createPrintCSS();
    },

    _createImage: function(target) {
        var img = document.createElement('img');
        target.appendChild(img);
    },

    _setPrintImage: function() {
        var img = this._containerNode.getElementsByTagName('img');
        if (img.length != 1) return;
        img = img[0];
	var pngData = this.getPng();
	if (pngData != null)
	        img.src = 'data:image/png;base64,' + pngData;
    },

    //------------------------------------
    //			resize
    //------------------------------------

    _resizeChart: function() {
        if (this.flashObject.ResizeChart != undefined)
            this.flashObject.ResizeChart();
    },

    //------------------------------------
    //			data
    //------------------------------------

    _xmlSource: null,

    /**
    * Set chart data	 
    * @method
    * @param {Object} data
    */
    setData: function(data) {
        if (typeof (data) == 'string' || (!BrowserTypeInformation.isSafari && data instanceof String)) {
            if (!this._loaded || !this._created)
                this._xmlSource = data;
            else
                this.setXMLDataFromString(data);
            return;
        }
    },

    setJSData: function(data) {
        var xmlData = JSONConverter.toXML(data);
        this.setData(xmlData);
    },

    updateData: function(path, data) {
        if (this.flashObject != null && this.flashObject.UpdateData != null)
            this.flashObject.UpdateData(path, data);
    },

    updatePointData: function(groupName, pointName, data) {
        if (this.flashObject != null && this.flashObject.UpdatePointData != null)
            this.flashObject.UpdatePointData(groupName, pointName, data);
    },

    //--------------------------------------
    // data manipulation
    //--------------------------------------

    setPlotCustomAttribute: function(attributeName, attributeValue) {
        if (this.flashObject != null && this.flashObject.SetPlotCustomAttribute != null)
            this.flashObject.SetPlotCustomAttribute(attributeName, attributeValue);
    },

    addSeries: function(seriesData) {
        if (this.flashObject != null && this.flashObject.AddSeries != null)
            this.flashObject.AddSeries(seriesData);
    },

    removeSeries: function(seriesId) {
        if (this.flashObject != null && this.flashObject.RemoveSeries != null)
            this.flashObject.RemoveSeries(seriesId);
    },

    addSeriesAt: function(index, seriesData) {
        if (this.flashObject != null && this.flashObject.AddSeriesAt != null)
            this.flashObject.AddSeriesAt(seriesId);
    },

    updateSeries: function(seriesId, seriesData) {
        if (this.flashObject != null && this.flashObject.UpdateSeries != null)
            this.flashObject.UpdateSeries(seriesId, seriesData);
    },

    showSeries: function(seriesId, seriesData) {
        if (this.flashObject != null && this.flashObject.ShowSeries != null)
            this.flashObject.ShowSeries(seriesId, seriesData);
    },

    addPoint: function(seriesId, pointData) {
        if (this.flashObject != null && this.flashObject.AddPoint != null)
            this.flashObject.AddPoint(seriesId, pointData);
    },

    addPointAt: function(seriesId, pointIndex, pointData) {
        if (this.flashObject != null && this.flashObject.AddPointAt != null)
            this.flashObject.AddPointAt(seriesId, pointIndex, pointData);
    },

    removePoint: function(seriesId, pointId) {
        if (this.flashObject != null && this.flashObject.RemovePoint != null)
            this.flashObject.RemovePoint(seriesId, pointId);
    },

    updatePoint: function(seriesId, pointId, pointData) {
        if (this.flashObject != null && this.flashObject.UpdatePoint != null)
            this.flashObject.UpdatePoint(seriesId, pointId, pointData);
    },

    clear: function() {
        if (this.flashObject != null && this.flashObject.Clear != null)
            this.flashObject.Clear();
    },

    refresh: function() {
        if (this.flashObject != null && this.flashObject.Refresh != null)
            this.flashObject.Refresh();
    },

    highlightSeries: function(seriesId, highlighted) {
        if (this.flashObject != null && this.flashObject.HighlightSeries != null)
            this.flashObject.HighlightSeries(seriesId, highlighted);
    },

    highlightPoint: function(seriesId, pointId, highlighted) {
        if (this.flashObject != null && this.flashObject.HighlightPoint != null)
            this.flashObject.HighlightPoint(seriesId, pointId, highlighted);
    },

    highlightCategory: function(categoryName, highlighted) {
        if (this.flashObject != null && this.flashObject.HighlightCategory != null)
            this.flashObject.HighlightCategory(categoryName, highlighted);
    },

    selectPoint: function(seriesId, pointId, selected) {
        if (this.flashObject != null && this.flashObject.SelectPoint != null)
            this.flashObject.SelectPoint(seriesId, pointId, selected);
    },

    view_highlightSeries: function(seriesId, highlighted) {
        if (this.flashObject != null && this.flashObject.View_HighlightSeries != null)
            this.flashObject.View_HighlightSeries(viewId, seriesId, highlighted);
    },

    view_highlightPoint: function(seriesId, pointId, highlighted) {
        if (this.flashObject != null && this.flashObject.View_HighlightPoint != null)
            this.flashObject.View_HighlightPoint(viewId, seriesId, pointId, highlighted);
    },

    view_highlightCategory: function(categoryName, highlighted) {
        if (this.flashObject != null && this.flashObject.View_HighlightCategory != null)
            this.flashObject.View_HighlightCategory(viewId, categoryName, highlighted);
    },

    view_selectPoint: function(seriesId, pointId, selected) {
        if (this.flashObject != null && this.flashObject.View_SelectPoint != null)
            this.flashObject.View_SelectPoint(viewId, seriesId, pointId, selected);
    },
    
    //--------------------------------------
    // dashboard data manipulation
    //--------------------------------------

    view_setPlotCustomAttribute: function(viewId, attributeName, attributeValue) {
        if (this.flashObject != null && this.flashObject.View_SetPlotCustomAttribute != null)
            this.flashObject.View_SetPlotCustomAttribute(viewId, attributeName, attributeValue);
    },

    view_addSeries: function(viewId, seriesData) {
        if (this.flashObject != null && this.flashObject.View_AddSeries != null)
            this.flashObject.View_AddSeries(viewId, seriesData);
    },

    view_removeSeries: function(viewId, seriesId) {
        if (this.flashObject != null && this.flashObject.View_RemoveSeries != null)
            this.flashObject.View_RemoveSeries(viewId, seriesId);
    },

    view_addSeriesAt: function(viewId, index, seriesData) {
        if (this.flashObject != null && this.flashObject.View_AddSeriesAt != null)
            this.flashObject.View_AddSeriesAt(viewId, seriesId);
    },

    view_updateSeries: function(viewId, seriesId, seriesData) {
        if (this.flashObject != null && this.flashObject.View_UpdateSeries != null)
            this.flashObject.View_UpdateSeries(viewId, seriesId, seriesData);
    },

    view_showSeries: function(viewId, seriesId, seriesData) {
        if (this.flashObject != null && this.flashObject.View_ShowSeries != null)
            this.flashObject.View_ShowSeries(viewId, seriesId, seriesData);
    },

    view_addPoint: function(viewId, seriesId, pointData) {
        if (this.flashObject != null && this.flashObject.View_AddPoint != null)
            this.flashObject.View_AddPoint(viewId, seriesId, pointData);
    },

    view_addPointAt: function(viewId, seriesId, pointIndex, pointData) {
        if (this.flashObject != null && this.flashObject.View_AddPointAt != null)
            this.flashObject.View_AddPointAt(viewId, seriesId, pointIndex, pointData);
    },

    view_removePoint: function(viewId, seriesId, pointId) {
        if (this.flashObject != null && this.flashObject.View_RemovePoint != null)
            this.flashObject.View_RemovePoint(viewId, seriesId, pointId);
    },

    view_updatePoint: function(seriesId, pointId, pointData) {
        if (this.flashObject != null && this.flashObject.View_UpdatePoint != null)
            this.flashObject.View_UpdatePoint(viewId, seriesId, pointId, pointData);
    },

    view_clear: function(viewId) {
        if (this.flashObject != null && this.flashObject.View_Clear != null)
            this.flashObject.View_Clear(viewId);
    },

    view_refresh: function(viewId) {
        if (this.flashObject != null && this.flashObject.View_Refresh != null)
            this.flashObject.View_Refresh(viewId);
    },

    //--------------------------------------
    // end of data manipulation
    //--------------------------------------

    updateViewPointData: function(viewName, groupName, pointName, data) {
        if (this.flashObject != null && this.flashObject.UpdateViewPointData != null)
            this.flashObject.UpdateViewPointData(groupName, pointName, data);
    },

    _checkPath: function(path) {
        var currentHost = location.host;
        var currentPath = location.pathname;
        if (location.protocol == "file:")
            return path;
        var protocol = location.protocol;
        currentHost = protocol + "//" + currentHost;
        currentPath = currentHost + currentPath.substr(0, currentPath.lastIndexOf("/") + 1);
        if ((path.charAt(0) + path.charAt(1)) == './') {
            return currentPath + path;
        } else if (path.charAt(0) == '/') {
            return currentHost + path;
        }
        return path;
    },

    /**
    * Set chart data file path
    * @method
    * @param {String} path
    */
    setXMLFile: function(path) {
        path = this._checkPath(path);
        if (this._created || this._loaded)
            this.setXMLDataFromURL(path);
        else
            this._xmlFile = path;
    },

    _checkPresetXMLSource: function() {
        //jstracer.write('AnyChart::_checkPresetXMLSource()');
        //jstracer.write('AnyChart::_checkPresetXMLSource() this._xmlSource = ' + this._xmlSource);
        if (this._xmlSource != null && this._created && this._loaded) {
            //jstracer.write('AnyChart::_checkPresetXMLSource() 100');
            var ths = this;
            setTimeout(function() {
                ths.setXMLDataFromString(ths._xmlSource);
            }, 1);
        }
    },

    //------------------------------------
    //			events
    //------------------------------------

    _onChartLoad: function() {
        //jstracer.write('AnyChart::_onChartLoad()');
        this._loaded = true;
        this._checkPresetXMLSource();
    },

    _onHTMLCreate: function() {
        //jstracer.write('AnyChart::_onHTMLCreate()');
        this._created = true;
        this._checkPresetXMLSource();
    },

    _created: false,
    _loaded: false,

    _listeners: null,
    _enableMouseEvents: false,

    /**
    * Add listener to the event
    * 
    * @param {String} event - the type of the event
    * @param {Function} callback - function called when an event occurs
    */
    addEventListener: function(event, callback) {
        this._listeners.push({ type: event, call: callback });
        if (event.indexOf("point") == 0) {
            this._enableMouseEvents = true;
            if (this._loaded && this.flashObject != null && this.flashObject.EnableEvents != null)
                this.flashObject.EnableEvents();
        }
    },

    removeEventListener: function(type) {
        var newIndexes = [];
        var i;
        for (i = 0; i < this._listeners.length; i++) {
            if (this._listeners[i].type != type)
                newIndexes.push(this._listeners[i]);
        }
        this._listeners = newIndexes;
    },

    dispatchEvent: function(event) {
        if (!this._canDispatchEvent) {
            this._nonDispatcedEvents.push(event);
        };
        var type = event.type;
        event.target = this;
        for (var i = 0; i < this._listeners.length; i++) {
            if (this._listeners[i].type == type) {
                this._listeners[i].call(event);
            }
        }
    },

    //------------------------------------
    //			actions
    //------------------------------------

    setXMLDataFromString: function(data) {
        if (this.flashObject != null &&
			this.flashObject.SetXMLDataFromString != null)
            this.flashObject.SetXMLDataFromString(data.toString());
    },

    setXMLDataFromURL: function(url) {
        if (this.flashObject != null &&
			this.flashObject.SetXMLDataFromURL != null) {
            this.flashObject.SetXMLDataFromURL(url);
        }
    },

    /**
    * Sets XML path to the certain view in dashboard.
    * @param {String} viewId view id
    * @param {String} xmlPath path to XML file 
    */
    setViewXMLFile: function(viewId, url) {
        if (this.flashObject != null &&
			this.flashObject.UpdateViewFromURL != null)
            this.flashObject.UpdateViewFromURL(viewId, url);
    },

    /**
    * Sets XML string to the certain view in dashboard.
    * @param {String} viewId view id
    * @param {String} data string with XML
    */
    setViewData: function(viewId, data) {
        if (this.flashObject != null &&
			this.flashObject.UpdateViewFromString != null)
            this.flashObject.UpdateViewFromString(viewId, data);
    },

    /**
    * Displays loading message
    * 
    * dashboard:
    * setLoading(viewId, messageText)
    * 
    * global:
    * setLoading(messageText)
    * 
    * @param {String} messageTextOrViewId message text or view id
    * @param {String} messageText message text
    */
    setLoading: function() {
        if (this.flashObject == null || this.flashObject.SetLoading == null) return;
        switch (arguments.length) {
            case 1:
                this.flashObject.SetLoading(null, arguments[0]);
                break;
            case 2:
                this.flashObject.SetLoading(arguments[0], arguments[1]);
                break;
        }
    },

    /**
    * Gets base64 encoded png chart screenshot
    * @return {String}
    */
    getPng: function() {
        return this.flashObject.GetPngScreen();
    },

    /**
    * Gets base64 encoded jpeg chart screenshot
    * @return {String}
    */
    getJpeg: function() {
        return this.flashObject.GetJPEGScreen();
    },

    /**
    * Runs chart printing dialog
    */
    printChart: function() {
        this.flashObject.PrintChart();
    },

    /**
    * Runs image saving dialog
    */
    saveAsImage: function() {
        this.flashObject.SaveAsImage();
    },

    /**
    * Runs pdf saving dialog
    */
    saveAsPDF: function() {
        this.flashObject.SaveAsPDF();
    },

    /**
    * Gets information
    * @return {Object}
    */
    getInformation: function() {
        return this.flashObject.GetInformation();
    },

    scrollXTo: function(xValue) {
        if (this.flashObject != null && this.flashObject.ScrollXTo != null)
            this.flashObject.ScrollXTo(xValue);
    },

    scrollYTo: function(yValue) {
        if (this.flashObject != null && this.flashObject.ScrollYTo != null)
            this.flashObject.ScrollYTo(yValue);
    },

    scrollTo: function(xValue, yValue) {
        if (this.flashObject != null && this.flashObject.ScrollTo != null)
            this.flashObject.ScrollTo(xValue, yValue);
    },

    viewScrollXTo: function(viewName, xValue) {
        if (this.flashObject != null && this.flashObject.ViewScrollXTo != null)
            this.flashObject.ViewScrollXTo(viewName, xValue);
    },

    viewScrollYTo: function(viewName, yValue) {
        if (this.flashObject != null && this.flashObject.ViewScrollXTo != null)
            this.flashObject.ViewScrollYTo(viewName, yValue);
    },

    viewScrollTo: function(viewName, xValue, yValue) {
        if (this.flashObject != null && this.flashObject.ViewScrollTo != null)
            this.flashObject.ViewScrollTo(viewName, xValue, yValue);
    },

    setXZoom: function(settings) {
        if (this.flashObject != null && this.flashObject.SetXZoom != null)
            this.flashObject.SetXZoom(settings);
    },

    setYZoom: function(settings) {
        if (this.flashObject != null && this.flashObject.SetYZoom != null)
            this.flashObject.SetYZoom(settings);
    },

    setZoom: function(xZoomSettings, yZoomSettings) {
        if (this.flashObject != null && this.flashObject.SetZoom != null)
            this.flashObject.SetZoom(xZoomSettings, yZoomSettings);
    },

    setViewXZoom: function(viewName, settings) {
        if (this.flashObject != null && this.flashObject.SetViewXZoom != null)
            this.flashObject.SetViewXZoom(viewName, settings);
    },

    setViewYZoom: function(viewName, settings) {
        if (this.flashObject != null && this.flashObject.SetViewYZoom != null)
            this.flashObject.SetViewYZoom(viewName, settings);
    },

    setViewZoom: function(viewName, xZoomSettings, yZoomSettings) {
        if (this.flashObject != null && this.flashObject.SetViewZoom != null)
            this.flashObject.SetViewZoom(viewName, xZoomSettings, yZoomSettings);
    },

    getXScrollInfo: function() {
        if (this.flashObject != null && this.flashObject.GetXScrollInfo != null)
            return this.flashObject.GetXScrollInfo();
    },

    getYScrollInfo: function() {
        if (this.flashObject != null && this.flashObject.GetYScrollInfo != null)
            return this.flashObject.GetYScrollInfo();
    },

    getViewXScrollInfo: function(viewName) {
        if (this.flashObject != null && this.flashObject.GetViewXScrollInfo != null)
            return this.flashObject.GetViewXScrollInfo(viewName);
    },

    getViewYScrollInfo: function(viewName) {
        if (this.flashObject != null && this.flashObject.GetViewYScrollInfo != null)
            return this.flashObject.GetViewYScrollInfo(viewName);
    },

    //------------------------------------
    //			player version
    //------------------------------------

    _checkPlayerVersion: function() {
        var version = this._getFlashPlayerVersion();
        if (version == null) return false;
        if (version.major < 9) return false;
        return true;
    },

    _getFlashPlayerVersion: function() {

        if (navigator.plugins != null && navigator.mimeTypes.length > 0) {
            var flashPlugin = navigator.plugins["Shockwave Flash"];
            if (flashPlugin != null && flashPlugin.description != null) {
                var versionInfo = flashPlugin.description.replace(/([a-zA-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split(".");
                return { major: versionInfo[0], minor: versionInfo[1], rev: versionInfo[2] };
            }
            return null;
        }

        var activeX = null;

        if (navigator.userAgent != null && navigator.userAgent.indexOf("Windows CE") != -1) {
            var versionIndex = 4;

            while (true) {
                try {
                    activeX = new ActiveXObject("ShockwaveFlash.ShockwaveFlash." + versionIndex);
                    versionIndex++;
                } catch (e) {
                    break;
                }
            }

            if (activeX == null) return null;
            return { major: versionIndex, minor: 0, rev: 0 };

        }

        var version = null;

        try {
            activeX = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
        } catch (e) {
            try {
                activeX = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
                version = { major: 6, minor: 0, rev: 21 };
                activeX.AllowScriptAccess = "always";
            } catch (e) {
                if (version != null && version.major == 6) return version;
            }
            try {
                activeX = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
            } catch (e) { /* do nothing */ }
        }
        if (activeX == null) return null;
        var versionInfo = activeX.GetVariable("$version").split(" ")[1].split(",");
        return { major: versionInfo[0], minor: versionInfo[1], rev: versionInfo[2] };
    }
};

/**
 * Get chart by its id
 * 
 * @static
 * @method
 * @param {String} id chart id
 * @return {AnyChart} chart
 * 
 */
AnyChart.getChartById = function(id) {
	return AnyChart._charts[id];
};

AnyChart._chartsCount = 0;

AnyChart._registerChart = function(chart) {
	AnyChart._charts[chart.id] = chart;
	AnyChart._chartsCount ++;
};

/**
 * Default AnyChart swf file
 * @static
 * @field {String}
 */
AnyChart.swfFile = null;

/**
 * Default AnyChart preloader swf file
 * @static
 * @field {String}
 */
AnyChart.preloaderSWFFile = null;

/**
 * Default chart width
 * @static
 * @field
 */
AnyChart.width = 550;

/**
 * Default chart height
 * @static
 * @field
 */
AnyChart.height = 400;

/**
 * Default text to be shown on preloader initilization
 * @static
 * @field {String}
 */
AnyChart.preloaderInitText = "Initializing...";

/**
 * Default text to be shown when preloader loads AnyChart.Swf
 * @static
 * @field {String}
 */
AnyChart.preloaderLoadingText = "Loading... ";

/**
 * Default text to be shown when AnyChart is initializing
 * @static
 * @field {String}
 */
AnyChart.initText = "Initializing...";

/**
 * Default text to be shown when AnyChart loads XML Data.
 * @static
 * @field {String}
 */
AnyChart.xmlLoadingText = "Loading xml...";

/**
 * Default text to be shown when AnyChart loads resources (images, etc.)
 * @static
 * @field {String}
 */
AnyChart.resourcesLoadingText  = "Loading resources...";

/**
 * Default text to be shown when AnyChart gets chart without data
 * @static
 * @field {String}
 */
AnyChart.noDataText = "No Data";

/**
 * Text to be shown when AnyChart gets no data source (neither XMLFile nor XMLText is set to chart) 
 * @static
 * @field {String}
 */
AnyChart.waitingForDataText = "Waiting for data...";

/**
 * Text to be shown while AnyChart is loading chart templates.
 * @static
 * @field {String}
 */
AnyChart.templatesLoadingText = "Loading templates...";

AnyChart._replaceInfo = new Array();

/**
 * Generate unique chart id
 * @static
 * @method
 * @return {String}
 */
AnyChart.getUniqueChartId = function() {
	return 'chart__'+AnyChart._chartsCount;
}

AnyChart._getUniqueContainerId = function(chartId) {
	return '___CONTAINER___N'+chartId;
}

var JSONConverter = {};
JSONConverter.toXML = function(data) {	
	return JSONConverter.createNode("anychart",data);
}
JSONConverter.isAttribute = function(prop) {
	return (typeof(prop) == "string" || typeof(prop) == "number" || typeof(prop) == "boolean");	
}
JSONConverter.isCollection = function(prop) {
	return (prop instanceof Array);	
}
JSONConverter.createNode = function(nodeName, data) {
	var res = "<"+nodeName;
	for (var j in data) {
		if (j != "format" && j != "text" && JSONConverter.isAttribute(data[j])) {
			res += " "+j+"=\""+data[j]+"\"";
		}
	}
	res += ">";
	for (var j in data) {
		if (j == "format" || j == "text") {
			res += "<"+j+"><![CDATA["+data[j]+"]]></"+j+">";
		}else if (JSONConverter.isCollection(data[j])) {
			var nodes = data[j];
			for (var i = 0;i<nodes.length;i++) {
				res += JSONConverter.createNode(j,nodes[i]);
			}
		}else if (!JSONConverter.isAttribute(data[j])) {
			res += JSONConverter.createNode(j,data[j]);
		}
	}
	res += "</"+nodeName+">";
	return res;
}

AnyChart._removeSWF = function() {
    var objects = document.getElementsByTagName("OBJECT");
    for (var i = objects.length - 1; i >= 0; i--) {
        objects[i].style.display = 'none';
        for (var x in objects[i]) {
            if (typeof objects[i][x] == 'function') {
                objects[i][x] = function() { };
            }
        }
    }
}

if (BrowserTypeInformation.isIE && !AnyChart._unload) {
    AnyChart._unloadHandler = function() {
        __flash_unloadHandler = function() { };
        __flash_savedUnloadHandler = function() { };
        window.attachEvent("onunload", AnyChart._removeSWF);
    }
    window.attachEvent("onbeforeunload", AnyChart._unloadHandler);
    AnyChart._unload = true;
}

Ext.namespace("Ext.ux.plugins");

Ext.ux.plugins.GroupHeaderGrid = function(config) {
	Ext.apply(this, config);
};

Ext.extend(Ext.ux.plugins.GroupHeaderGrid, Ext.util.Observable, {
	init: function(grid) {
		var v = grid.getView();
		v.beforeMethod('initTemplates', this.initTemplates);
		v.renderHeaders = this.renderHeaders.createDelegate(v, [v.renderHeaders]);
        v.afterMethod('onColumnWidthUpdated', this.updateGroupStyles);
        v.afterMethod('onAllColumnWidthsUpdated', this.updateGroupStyles);
		v.afterMethod('onColumnHiddenUpdated', this.updateGroupStyles);
		v.getHeaderCell = this.getHeaderCell;
		v.updateSortIcon = this.updateSortIcon;
		v.getGroupStyle = this.getGroupStyle;
	},

	initTemplates: function() {
		var ts = this.templates || {};
		if (!ts.gcell) {
			ts.gcell = new Ext.Template(
				'<td class="x-grid3-hd {cls} x-grid3-td-{id}" style="{style}">',
				'<div {tooltip} class="x-grid3-hd-inner x-grid3-hd-{id}" unselectable="on" style="{istyle}">{value}</div>',
				'</td>'
			);
		}
		this.templates = ts;
	},

	renderHeaders: function(renderHeaders) {
		var ts = this.templates, rows = [], tw = this.getTotalWidth();
		for (var i = 0; i < this.cm.rows.length; i++) {
			var r = this.cm.rows[i], cells = [], col = 0;
			for (var j = 0; j < r.length; j++) {
				var c = r[j];
				c.colspan = c.colspan || 1;
				c.col = col;
				col += c.colspan;
				var gs = this.getGroupStyle(c);
				cells[j] = ts.gcell.apply({
					id: c.id || i + '-' + col,
					cls: c.header ? 'ux-grid-hd-group-cell' : 'ux-grid-hd-nogroup-cell',
					style: 'width:' + gs.width + ';' + (gs.hidden ? 'display:none;' : '') + (c.align ? 'text-align:' + c.align + ';' : ''),
					tooltip: c.tooltip ? (Ext.QuickTips.isEnabled() ? 'ext:qtip' : 'title') + '="' + c.tooltip + '"' : '',
					value: c.header || '&#160;',
					istyle: c.align == 'right' ? 'padding-right:16px' : ''
				});
			}
			rows[i] = ts.header.apply({
				tstyle: 'width:' + tw + ';',
				cells: cells.join('')
			});
		}
		rows[rows.length] = renderHeaders.call(this);
		return rows.join('');
	},

	getGroupStyle: function(c) {
		var w = 0, h = true;
		for (var i = c.col; i < c.col + c.colspan; i++) {
			if (!this.cm.isHidden(i)) {
				var cw = this.cm.getColumnWidth(i);
				if(typeof cw == 'number'){
					w += cw;
				}
				h = false;
			}
		}
		return {
			width: (Ext.isBorderBox ? w : Math.max(w - this.borderWidth, 0)) + 'px',
			hidden: h
		}
	},

	updateGroupStyles: function(col) {
		var tables = this.mainHd.query('.x-grid3-header-offset > table'), tw = this.getTotalWidth();
		for (var i = 0; i < tables.length; i++) {
			tables[i].style.width = tw;
			if (i < this.cm.rows.length) {
				var cells = tables[i].firstChild.firstChild.childNodes;
				for (var j = 0; j < cells.length; j++) {
					var c = this.cm.rows[i][j];
					if ((typeof col != 'number') || (col >= c.col && col < c.col + c.colspan)) {
						var gs = this.getGroupStyle(c);
						cells[j].style.width = gs.width;
						cells[j].style.display = gs.hidden ? 'none' : '';
					}
				}
			}
		}
	},

	getHeaderCell : function(index){
		return this.mainHd.query('td.x-grid3-cell')[index];
	},

	updateSortIcon : function(col, dir){
		var sc = this.sortClasses;
		var hds = this.mainHd.select('td.x-grid3-cell').removeClass(sc);
		hds.item(col).addClass(sc[dir == "DESC" ? 1 : 0]);
	}
});


// from http://www.extjs.com/forum/showthread.php?p=365560
//Ext.override(Ext.form.BasicForm, {
//    /**
//     * @cfg {Object/Boolean} submitOnEnter
//     * If set, this causes the form to be submitted when the Enter key is pressed when an item
//     * of this form is focused. If the value of the <code>submitOnEnter</code> config is an object,
//     * it is passed as the options parameter to the {@link #submit} method.
//     */
//
//    initEl : function(el){
//        this.el = Ext.get(el);
//        this.id = this.el.id || Ext.id();
//
////      If submitOnEnter wanted, add a non-focusable, offscreen <input type="submit">
//        if (this.submitOnEnter) {
//            this.submitInput = this.el.createChild({
//                tag: 'input',
//                type: 'submit',
//                style: {
//                    position: 'absolute',
//                    top: '-10000px',
//                    left: '-10000px'
//                },
//                tabIndex: -1
//            });
//        }
//
//        if(!this.standardSubmit){
////          Trap the submit input and invoke the submit method
//            if (this.submitInput) {
//                this.submitInput.on("click", function() {
//                    this.submit(Ext.isObject(this.submitOnEnter) ? this.submitOnEnter : undefined);
//                }, this);
//            }
//            this.el.on('submit', this.onSubmit, this);
//        }
//        this.el.addClass('x-form');
//    }
//});

// //=========================================================
// // From http://extjs.com/forum/showthread.php?t=54243
// // 
// // Likely not needed in ext 3.0
// // 
// /**
//  * Sets observability on the passed class constructor.<p>
//  * <p>This makes any event fired on any instance of the passed class also fire a single event through
//  * the <i>class</i> allowing for central handling of events on many instances at once.</p>
//  * <p>Usage:</p><pre><code>
// Ext.util.Observable.observeClass(Ext.data.Connection);
// Ext.data.Connection.on('beforerequest', function(con, options) {
//     console.log("Ajax request made to " + options.url);
// });</code></pre>
//  * @param {Function} c The class constructor to make observable.
//  * @member Ext.util.Observable
//  * @method observeClass
//  * @static
//  */
// Ext.util.Observable.observeClass = function(c) {
//     Ext.apply(c, new Ext.util.Observable());
//     c.prototype.fireEvent = function() {
//         return (c.fireEvent.apply(c, arguments) !== false) &&
//             (Ext.util.Observable.prototype.fireEvent.apply(this, arguments) !== false);
//     };
// };
// 
// Ext.override(Ext.util.Observable, {
//     addListener: Ext.util.Observable.prototype.addListener.createInterceptor(function() {
//         if (!this.events) {
//             this.events = {};
//         }
//     })
// });
// Ext.util.Observable.prototype.on = Ext.util.Observable.prototype.addListener;
// 
// //=========================================================
// 
// 
// 
// // Ext.Ajax.on('beforerequest', function() {
// //         alert('doing ajax request');
// //     }
// // );
// 
// function requestExceptionHandler(conn, response, options) {
//     jstracer.write('requestExceptionHandler()');
//     var data = Ext.util.JSON.decode(response.responseText);
//     if(data.redirect_url) {
//         jstracer.write('got data.redirect_url');
//         (function() {
//             document.location.href = data.redirect_url;
//         }).defer(10);
//     }
// }
// 
// function beforeRequestHandler(conn, options) {
//     jstracer.write('beforeRequestHandler() headers = ' + options.headers);
// }
// 
// Ext.util.Observable.observeClass(Ext.data.Connection);
// 
// Ext.data.Connection.on('requestexception', requestExceptionHandler);
// Ext.Ajax.on('requestexception', requestExceptionHandler);
// 
// Ext.data.Connection.on('beforerequest', beforeRequestHandler);
// Ext.Ajax.on('beforerequest', beforeRequestHandler);

// Ext.Ajax.on('requestcomplete', this.hideSpinner, this);


//Ext.override(Ext.menu.Menu, {
//    show: function(el, pos, parentMenu) {
//        if (this.floating) {
//            this.parentMenu = parentMenu;
//            if (!this.el) {
//                this.render();
//                this.doLayout(false, true);
//            }
//            //if(this.fireEvent('beforeshow', this) !== false){
//            this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign, this.defaultOffsets), parentMenu, false);
//            //}
//        } else {
//            Ext.menu.Menu.superclass.show.call(this);
//        }
//    },
//    showAt: function(xy, parentMenu, _e) {
//        if (this.fireEvent('beforeshow', this) !== false) {
//            this.parentMenu = parentMenu;
//            if (!this.el) {
//                this.render();
//            }
//            if (_e !== false) {
//                xy = this.el.adjustForConstraints(xy);
//            }
//            this.el.setXY(xy);
//            if (this.enableScrolling) {
//                this.constrainScroll(xy[1]);
//            }
//            this.el.show();
//            Ext.menu.Menu.superclass.onShow.call(this);
//            if (Ext.isIE) {
//                this.layout.doAutoSize();
//                if (!Ext.isIE8) {
//                    this.el.repaint();
//                }
//            }
//            this.hidden = false;
//            this.focus();
//            this.fireEvent("show", this);
//        }
//    }
//});


// custom Vtype for vtype:'minutes'

function requestExceptionHandler(conn, response, options) {
//    jstracer.write('requestExceptionHandler()');
    var data = Ext.util.JSON.decode(response.responseText);
    if(data) {
        if(data.redirect_url) {
//            jstracer.write('got data.redirect_url');
            (function() {
                document.location.href = data.redirect_url;
            }).defer(10);
        }
    }
}

Ext.Ajax.on('requestexception', requestExceptionHandler); 


var default_headers = {
  'X-2way-Is-App': 'true'
};

Ext.data.Connection.defaultHeaders = default_headers;
Ext.Ajax.defaultHeaders = default_headers;


// overrides from http://extjs.com/forum/showthread.php?t=58177&page=9
//Ext.override(Ext.Container, {
//    add : function(comp){
//        if(!this.items){
//            this.initItems();
//        }
//        var a = arguments, len = a.length;
//        if(len > 1){
//            for(var i = 0; i < len; i++) {
//                this.add(a[i]);
//            }
//            return;
//        }
//        var c = this.lookupComponent(this.applyDefaults(comp));
//        var pos = this.items.length;
//        if(this.fireEvent('beforeadd', this, c, pos) !== false && this.onBeforeAdd(c) !== false){
//            this.items.add(c);
//            c.ownerCt = this;
//            this.onAdd(this, c);
//            this.fireEvent('add', this, c, pos);
//        }
//        return c;
//    },
//
//    insert : function(index, comp){
//        if(!this.items){
//            this.initItems();
//        }
//        var a = arguments, len = a.length;
//        if(len > 2){
//            for(var i = len-1; i >= 1; --i) {
//                this.insert(index, a[i]);
//            }
//            return;
//        }
//        var c = this.lookupComponent(this.applyDefaults(comp));
//
//        if(c.ownerCt == this && this.items.indexOf(c) < index){
//            --index;
//        }
//
//        if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
//            this.items.insert(index, c);
//            c.ownerCt = this;
//            this.onAdd(this, c);
//            this.fireEvent('add', this, c, index);
//        }
//        return c;
//    },
//
//    remove : function(comp, autoDestroy){
//        var c = this.getComponent(comp);
//        if(c && this.fireEvent('beforeremove', this, c) !== false){
//            this.items.remove(c);
//            delete c.ownerCt;
//            if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){
//                c.destroy();
//            }
//            if(this.layout && this.layout.activeItem == c){
//                delete this.layout.activeItem;
//            }
//            this.onRemove(this, c);
//            this.fireEvent('remove', this, c);
//        }
//        return c;
//    },
//
////  private
////  Inform all ancestor Containers of an addition to their Component tree
//    onAdd: function() {
//        if (this.ownerCt && this.ownerCt.onAdd) {
//            this.ownerCt.onAdd.apply(this.ownerCt, arguments);
//        }
//    },
//
////  private
////  Inform all ancestor Containers of a removal from their Component tree
//    onRemove: function() {
//        if (this.ownerCt && this.ownerCt.onRemove) {
//            this.ownerCt.onRemove.apply(this.ownerCt, arguments);
//        }
//    }
//});

//Ext.override(Ext.FormPanel, {
////  Determine if a Component is usable as a form Field.
//    isField: function(c) {
//        return !!c.setValue && !!c.getValue && !!c.markInvalid && !!c.clearInvalid;
//    },
//
//    onAdd : function(ct, c) {
//        Ext.form.FormPanel.superclass.onAdd.apply(this, arguments);
////      If a single form Field, add it
//        if (this.isField(c)) {
//            this.form.add(c);
//
////      If a Container, add any Fields it might contain
//        } else if (c.findBy) {
//            this.form.add.apply(this.form, c.findBy(this.isField));
//        }
//    },
//
//    onRemove : function(ct, c) {
//        Ext.form.FormPanel.superclass.onRemove.apply(this, arguments);
////      If a single form Field, remove it
//        if (this.isField(c)) {
//            Ext.destroy(c.container.up('.x-form-item'));
//            this.form.remove(c);
//
////      If a Container, remove any Fields it might contain
//        } else if (c.findByType) {
//            Ext.each(c.findBy(this.isField), this.form.remove, this.form);
//        }
//    }
//});

//Ext.override(Ext.TabPanel, {
//    initEvents : function(){
//        Ext.TabPanel.superclass.initEvents.call(this);
//        this.strip.on('mousedown', this.onStripMouseDown, this);
//        this.strip.on('contextmenu', this.onStripContextMenu, this);
//        if(this.enableTabScroll){
//            this.strip.on('mousewheel', this.onWheel, this);
//        }
//    },
//
//    onAdd : function(tp, item, index){
//        if (this.rendered) {
//            this.initTab(item, index);
//            if(this.items.getCount() == 1){
//                this.syncSize();
//            }
//            this.delegateUpdates();
//        }
//        Ext.TabPanel.superclass.onAdd.apply(this, arguments);
//    },
//
//    onRemove : function(tp, item){
//        Ext.destroy(Ext.get(this.getTabEl(item)));
//        this.stack.remove(item);
//        item.un('disable', this.onItemDisabled, this);
//        item.un('enable', this.onItemEnabled, this);
//        item.un('titlechange', this.onItemTitleChanged, this);
//        item.un('iconchange', this.onItemIconChanged, this);
//        item.un('beforeshow', this.onBeforeShowItem, this);
//        if(item == this.activeTab){
//            var next = this.stack.next();
//            if(next){
//                this.setActiveTab(next);
//            }else if(this.items.getCount() > 0){
//                this.setActiveTab(0);
//            }else{
//                this.activeTab = null;
//            }
//        }
//        this.delegateUpdates();
//        Ext.TabPanel.superclass.onRemove.apply(this, arguments);
//    }
//});

//Ext.override(Ext.data.MemoryProxy, {
//    doRequest : function(action, rs, params, reader, callback, scope, arg) {
//        params = params || {};
//        var result;
//        try {
//            result = reader.readRecords(this.data);
//        }catch(e){
//            this.fireEvent("loadexception", this, arg, null, e);
//            callback.call(scope, null, arg, false);
//            return;
//        }
//        callback.call(scope, result, arg, true);
//    }
//});


Ext.namespace('twowayfitness');

twowayfitness.FieldCreator = Ext.extend(Object, {
    constructor: function(config) {
        Ext.apply(this, config);
        twowayfitness.FieldCreator.superclass.constructor([config]);
    },
    updateField: function(field) {
        field.setValue(this.data[field.name]);
    },
    updateFieldByName: function(attribute_name) {
        var name = this.object_name + '[' + attribute_name + ']';
        var comp = this.container.find('name', name)[0];
        this.updateField(comp);
    },    
    field_params: function(attribute_name, label, config) {
        var name_for_value = this.object_name ? (this.object_name + '[' + attribute_name + ']') : attribute_name;
        var submission_name = this.submission_object_name ? this.submission_object_name : this.object_name;
        var field_name = submission_name + '[' + attribute_name + ']';
        
        Ext.log('field_params attribute_name = ' + attribute_name + ' field_name = ' + field_name);
        
        Ext.log('name_for_value = ' + name_for_value);
        var value = this.data ? this.data[name_for_value] : '';
        Ext.log('value = ' + value);
        
        var ret = {
            // id: name,
            name: field_name,
            fieldLabel: label,
            value: value
        };

        if(config) {
            Ext.apply(ret, config);
        }
        
        return ret;
    },
    checkbox_params: function(attribute_name, label, config) {
        // bit of non DRYness here WRT field_params
        var name = this.object_name + '[' + attribute_name + ']';
        var value = this.data ? this.data[name] : false;
        
        var ret = {
            // id: name,
            xtype: 'checkbox',
            name: name,
            boxLabel: label,
            checked: value
        };

        if(config) {
            Ext.apply(ret, config);
        }
        
        return ret;
    },
    text_area: function(attribute_name, label, config) {
        return new Ext.form.TextArea(
                this.field_params(attribute_name, label, config)
            );
    },
    text_field: function(attribute_name, label, config) {
        return new Ext.form.TextField(this.field_params(attribute_name, label, config));
    },
    simple_date_field: function(attribute_name, label, options) {
        var year_data = [];
        for(var i3 = 0; i3 < 100; ++i3) {
            year_data[i3] = [ 1910 + i3 ];
        }

        var years_store = new Ext.data.SimpleStore({
            fields: [ 'year' ],
            data : year_data
        });

        var params = this.field_params(attribute_name + '[year]', 'Year', {
//            tpl: '<tpl for="."><div class="x-combo-list-item">{type}: {unit}</div></tpl>',
            store: years_store,
//             value: self.data ? self.data['metric[units]'] : '',
//            value: self.data ? self.data.units : '',
//            disabled: self.data ? true : false, // once units are set for a benchmark, they cannot be changed.
            displayField: 'year',
            fieldLabel: 'Year',
            typeAhead: true,
            mode: 'local',
            triggerAction: 'all',
            width: 65,
            emptyText:'year',
            editable: false,
            selectOnFocus:true
        });
        params.hiddenName = params.name;
        var year_combo = new Ext.form.ComboBox(params);

        var month_data = [];
        for(var i = 0; i < 12; ++i) {
            month_data[i] = [ i+1, Date.monthNames[i] ];
        }

        var months_store = new Ext.data.SimpleStore({
            fields: [ 'index', 'name' ],
            data : month_data
        });

        params = this.field_params(attribute_name + '[month]', 'Month', {
//            tpl: '<tpl for="."><div class="x-combo-list-item">{type}: {unit}</div></tpl>',
            store: months_store,
//             value: self.data ? self.data['metric[units]'] : '',
//            value: self.data ? self.data.units : '',
//            disabled: self.data ? true : false, // once units are set for a benchmark, they cannot be changed.
            displayField: 'name',
            valueField: 'index',
            fieldLabel: 'Month',
            typeAhead: true,
            mode: 'local',
            triggerAction: 'all',
            emptyText:'month',
            width: 90,
            editable: false,
            selectOnFocus:true
        });
        params.hiddenName = params.name;
        var month_combo = new Ext.form.ComboBox(params);

        var day_data = [];
        for(var i2 = 1; i2 <= 31; ++i2) {
            day_data[i2-1] = [ i2 ];
        }

        var days_store = new Ext.data.SimpleStore({
            fields: [ 'day' ],
            data : day_data
        });

        params = this.field_params(attribute_name + '[day]', 'Day', {
//            tpl: '<tpl for="."><div class="x-combo-list-item">{type}: {unit}</div></tpl>',
            store: days_store,
//             value: self.data ? self.data['metric[units]'] : '',
//            value: self.data ? self.data.units : '',
//            disabled: self.data ? true : false, // once units are set for a benchmark, they cannot be changed.
            displayField: 'day',
            fieldLabel: 'Day',
            typeAhead: true,
            mode: 'local',
            triggerAction: 'all',
            emptyText:'day',
            width: 50,
            editable: false,
            selectOnFocus:true
        });
        params.hiddenName = params.name;
        var day_combo = new Ext.form.ComboBox(params);

        var config =  {
            fieldLabel: 'Date of Birth',
            border: false,
            name: 'exercise_diary_entry[duration]',
            layout: 'hbox',
            items: [
                month_combo,
                day_combo,
                year_combo
            ]
        };

        Ext.apply(config, options);

        return new Ext.Panel(config);
    },
    date_field: function(attribute_name, label, config) {
        var params = this.field_params(attribute_name, label, config);
        var date_value = params.value;
        Ext.log('date_value = ' + date_value);

        Ext.applyIf(params, {
            format: 'Y-m-d',
            allowBlank: true,
            readOnly: true
        });
        var ret = new Ext.form.DateField(params);

        var date = undefined;

        Ext.log('date_field 300');
        if(date_value) {
            Ext.log('date_field 310');
            date = (date_value == '' ? new Date() : new Date(date_value));
        } else {
            Ext.log('date_field 320');

            if(date_value == '') {
                Ext.log('date_field 330');
               date = new Date();
            }
        }

        if(date) {
            Ext.log('date_field 350');
            ret.setValue(date);
        }
        return ret;
    }
    
});

twowayfitness.open_link_in_new_window = function(path) {
    // 
    //  the following does not work on safari for some reason. Popups being blocked perhaps?
    // 
    // var progressBox = Ext.Msg.wait("Opening link in new browser window");
    // (function() {
    //     jstracer.write('inside function');
    //     window.open(path);
    //     jstracer.write('inside function 100');
    //     progressBox.hide();
    //     jstracer.write('inside function 200');
    // }).defer(2000);

    window.open(path);
};


twowayfitness.handle_form_submission_failure = function(form, action) {
    var msg = 'Your requested operation failed. Please fix any errors and try again.';
    switch (action.response.status) {
        case 404: {
            msg = 'An item that you attempted to modify no longer exists. Perhaps you have deleted it.';
            break;
        }
        case 500: {
            msg = "Our apologies, but we're having trouble handling that request. Please try again later. Our operators have been informed of the problem and will investigate.";
            break;

        }
    }

    twowayfitness.showPlainMessage(msg, { title: 'Operation Failed'});
};


Ext.namespace('Ext.ux.form');

/**
  * Ext.ux.form.DateTime Extension Class for Ext 2.x Library
  *
  * @author    Ing. Jozef Sakalos, adjusted for ext_scaffold by Martin Rehfeld
  * @copyright (c) 2008, Ing. Jozef Sakalos
  *
  * @class Ext.ux.form.DateTime
  * @extends Ext.form.Field
  */
Ext.ux.form.DateTime = Ext.extend(Ext.form.Field, {
     defaultAutoCreate:{tag:'input', type:'hidden'}
    ,timeWidth:100
    ,dtSeparator:' '
    ,hiddenFormat:'Y/m/d H:i:s O'
    ,isFormField:true

    ,initComponent:function() {
        // call parent initComponent
        Ext.ux.form.DateTime.superclass.initComponent.call(this);

        // create DateField
        var dateConfig = Ext.apply({}, {
             id:this.id + '-date'
            ,format:this.dateFormat
						,allowBlank:true
            ,width:this.timeWidth
            ,listeners:{
                 blur:{scope:this, fn:this.onBlur}
            }
        }, this.dateConfig);
        this.df = new Ext.form.DateField(dateConfig);
        delete(this.dateFormat);

        // create TimeField
        var timeConfig = Ext.apply({}, {
             id:this.id + '-time'
            ,format:this.timeFormat
						,allowBlank:true
            ,width:this.timeWidth
            ,listeners:{
                 blur:{scope:this, fn:this.onBlur}
            }
        }, this.timeConfig);
        this.tf = new Ext.form.TimeField(timeConfig);
        delete(this.timeFormat);

        // relay events
        this.relayEvents(this.df, ['focus', 'change', 'specialkey', 'invalid', 'valid']);
        this.relayEvents(this.tf, ['focus', 'change', 'specialkey', 'invalid', 'valid']);

    } // end of function initComponent

    ,onRender:function(ct, position) {

        // render underlying field
        Ext.ux.form.DateTime.superclass.onRender.call(this, ct, position);

        // render DateField and TimeField
        // create bounding table
        var t = Ext.DomHelper.append(ct, {tag:'table',style:'border-collapse:collapse',children:[
            {tag:'tr',children:[
                {tag:'td',style:'padding-right:4px'},{tag:'td'}
            ]}
        ]}, true);

        this.tableEl = t;

        // render DateField
        var td = t.child('td');
        this.df.render(td);

        // render TimeField
        var td = td.next('td');
        this.tf.render(td);

        if(Ext.isIE && Ext.isStrict) {
            t.select('input').applyStyles({top:0});
        }

        this.on('specialkey', this.onSpecialKey, this);

        this.df.el.swallowEvent(['keydown', 'keypress']);
        this.tf.el.swallowEvent(['keydown', 'keypress']);

        this.rendered = true;

    } // end of function onRender

    ,onSpecialKey:function(t, e) {
        if(e.getKey() == e.TAB) {
            if(t === this.df && !e.shiftKey) {
                e.stopEvent();
                this.tf.focus();
            }
            if(t === this.tf && e.shiftKey) {
                e.stopEvent();
                this.df.focus();
            }
        }
    } // end of function onSpecialKey

    ,setSize:function(w, h) {
        if(!w) {
            return;
        }
        this.df.setSize(w - this.timeWidth - 4, h);
        this.tf.setSize(this.timeWidth, h);

        if(Ext.isIE) {
            this.df.el.up('td').setWidth(w - this.timeWidth - 4);
            this.tf.el.up('td').setWidth(this.timeWidth);
        }

    } // end of function setSize

    ,focus:function() {
        this.df.focus();
    } // end of function focus

    ,setValue:function(val) {
        var da, time;
        if(val instanceof Date) {
            this.setDate(val);
            this.setTime(val);
        }
        else {
					 if(val) {
	            da = val.split(this.dtSeparator);
	            this.setDate(da[0]);
	            if(da[1]) {
	                this.setTime(da[1]);
	            }
					  }
        }
        this.updateValue(true);
    } // end of function setValue

    ,getValue:function() {
        // create new instance of date
        return new Date(this.dateValue);
    } // end of function getValue

    ,onBlur:function() {
        this.updateValue(true);
        (function() {
            var suppressEvent = this.df.hasFocus || this.tf.hasFocus;
            this.updateValue(suppressEvent);
        }).defer(100, this);
    } // end of function onBlur

    ,updateValue:function(suppressEvent) {
        // update date
        var d = this.df.getValue();
        this.dateValue = new Date(d);
        if(d instanceof Date) {
            this.dateValue.setFullYear(d.getFullYear());
            this.dateValue.setMonth(d.getMonth());
            this.dateValue.setDate(d.getDate());
        }

        // update time
        var t = Date.parseDate(this.tf.getValue(), this.tf.format);
        if(t instanceof Date && this.dateValue instanceof Date) {
            this.dateValue.setHours(t.getHours());
            this.dateValue.setMinutes(t.getMinutes());
            this.dateValue.setSeconds(t.getSeconds());
        }

        // update underlying hidden
        if(this.rendered) {
            this.el.dom.value = this.dateValue instanceof Date ? this.dateValue.format(this.hiddenFormat) : this.dateValue;
        }

        // fire blur event if not suppressed and if neither DateField nor TimeField has it
        if(true !== suppressEvent) {
            this.fireEvent('blur', this);
        }
    } // end of function updateValue

    ,isValid:function() {
        return this.df.isValid() && this.tf.isValid();
    } // end of function isValid

    ,validate:function() {
        return this.df.validate() && this.tf.validate();
    } // end of function validate

    ,setDate:function(date) {
        this.df.setValue(date);
    } // end of function setDate

    ,setTime:function(date) {
        this.tf.setValue(date);
    } // end of function setTime

}); // end of extend

// register xtype
Ext.reg('xdatetime', Ext.ux.form.DateTime);


/**
 * Ext.ux.grid.Search
 *
 * Search plugin
 *
 * @author    Ing. Jozef Sakalos
 * @copyright (c) 2008, by Ing. Jozef Sakalos
 * @date      17. January 2008
 * @version   $Id: Ext.ux.grid.Search.js 634 2008-01-19 17:00:20Z jozo $
 */

Ext.namespace('Ext.ux', 'Ext.ux.grid');

/**
 * @constructor
 */
Ext.ux.grid.Search = function(config) {
    Ext.apply(this, config, {
        // defaults
         position:'bottom'
        ,searchText:'Search'
        ,searchTipText:'Type a text to search and press Enter'
        ,iconCls:'ux-icon-search'
        ,checkIndexes:'all'
        ,disableIndexes:[]
        ,dateFormat:undefined
        ,mode:'remote'
        ,paramNames: {
             fields:'fields'
            ,query:'query'
        }
    });

    Ext.ux.grid.Search.superclass.constructor.call(this);
}; // end of constructor

Ext.extend(Ext.ux.grid.Search, Ext.util.Observable, {
    // {{{
    init:function(grid) {
        this.grid = grid;

        grid.onRender = grid.onRender.createSequence(this.onRender, this);
        grid.reconfigure = grid.reconfigure.createSequence(this.reconfigure, this);
    } // end of function init
    // }}}
    // {{{
    ,onRender:function() {
        var grid = this.grid;
        var tb = 'bottom' == this.position ? grid.bottomToolbar : grid.topToolbar;

        // add menu
        this.menu = new Ext.menu.Menu();
        tb.addSeparator();
        tb.add({
             text:this.searchText
            ,menu:this.menu
            ,iconCls:this.iconCls
        });

        // add filter field
        this.field = new Ext.form.TwinTriggerField({
             width:this.width
            ,selectOnFocus:undefined === this.selectOnFocus ? true : this.selectOnFocus
            ,trigger1Class:'x-form-clear-trigger'
            ,trigger2Class:'x-form-search-trigger'
            ,onTrigger1Click:this.onTriggerClear.createDelegate(this)
            ,onTrigger2Click:this.onTriggerSearch.createDelegate(this)
        });
        this.field.on('render', function() {
            this.field.el.dom.qtip = this.searchTipText;
            var map = new Ext.KeyMap(this.field.el, [{
                 key:Ext.EventObject.ENTER
                ,scope:this
                ,fn:this.onTriggerSearch
            },{
                 key:Ext.EventObject.ESC
                ,scope:this
                ,fn:this.onTriggerClear
            }]);
            map.stopEvent = true;
        }, this, {single:true});

        tb.add(this.field);

        // reconfigure
        this.reconfigure();
    } // end of function onRender
    // }}}
    // {{{
    ,onTriggerClear:function() {
        this.field.setValue('');
        this.field.focus();
        this.onTriggerSearch();
    } // end of function onTriggerClear
    // }}}
    // {{{
    ,onTriggerSearch:function() {
        var val = this.field.getValue();
        var store = this.grid.store;

        if('local' === this.mode) {
            store.clearFilter();
            if(val) {
                store.filterBy(function(r) {
                    var retval = false;
                    this.menu.items.each(function(item) {
                        if(!item.checked || retval) {
                            return;
                        }
                        var rv = r.get(item.dataIndex);
                        rv = rv instanceof Date ? rv.format(this.dateFormat || r.fields.get(item.dataIndex).dateFormat) : rv;
                        var re = new RegExp(val, 'gi');
                        retval = re.test(rv);
                    }, this);
                    if(retval) {
                        return true;
                    }
                    return retval;
                }, this);
            }
            else {
            }
        }
        else {
            // clear start (necessary if we have paging)
            if(store.lastOptions && store.lastOptions.params) {
                store.lastOptions.params[store.paramNames.start] = 0;
            }

            // get fields to search array
            var fields = [];
            this.menu.items.each(function(item) {
                if(item.checked) {
                    fields.push(item.dataIndex);
                }
            });

            // add fields and query to baseParams of store
            delete(store.baseParams[this.paramNames.fields]);
            delete(store.baseParams[this.paramNames.query]);
            if(store.lastOptions && store.lastOptions.params) {
	            delete(store.lastOptions.params[this.paramNames.fields]);
	            delete(store.lastOptions.params[this.paramNames.query]);
						}
            if(fields.length) {
                store.baseParams[this.paramNames.fields] = Ext.encode(fields);
                store.baseParams[this.paramNames.query] = val;
            }

            // reload store
            store.reload();
        }

    } // end of function onTriggerSearch
    // }}}
    // {{{
    // private 
    ,reconfigure:function() {

        // {{{
        // remove old items
        var menu = this.menu;
        menu.removeAll();

        // }}}
        // {{{
        // add new items
        var cm = this.grid.colModel;
        Ext.each(cm.config, function(config) {
            var disable = false;
            if(config.header) {
                Ext.each(this.disableIndexes, function(item) {
                    disable = disable ? disable : item === config.dataIndex;
                });
                if(!disable) {
                    menu.add(new Ext.menu.CheckItem({
                         text:config.header
                        ,hideOnClick:false
                        ,checked:'all' === this.checkIndexes
                        ,dataIndex:config.dataIndex
                    }));
                }
            }
        }, this);
        // }}}
        // {{{
        // check items
        if(this.checkIndexes instanceof Array) {
            Ext.each(this.checkIndexes, function(di) {
                var item = menu.items.find(function(itm) {
                    return itm.dataIndex === di;
                });
                if(item) {
                    item.setChecked(true, true);
                }
            }, this);
        }
        // }}}

    } // end of function reconfigure
    // }}}

}); // end of extend


/*!
 * Ext JS Library 3.0.3
 * Copyright(c) 2006-2009 Ext JS, LLC
 * licensing@extjs.com
 * http://www.extjs.com/license
 */
/**
 * List compiled by mystix on the extjs.com forums.
 * Thank you Mystix!
 *
 * English Translations
 * updated to 2.2 by Condor (8 Aug 2008)
 */

Ext.UpdateManager.defaults.indicatorText = '<div class="loading-indicator">Loading...</div>';

if(Ext.DataView){
  Ext.DataView.prototype.emptyText = "";
}

if(Ext.grid.GridPanel){
  Ext.grid.GridPanel.prototype.ddText = "{0} selected row{1}";
}

if(Ext.LoadMask){
  Ext.LoadMask.prototype.msg = "Loading...";
}

Date.monthNames = [
  "January",
  "February",
  "March",
  "April",
  "May",
  "June",
  "July",
  "August",
  "September",
  "October",
  "November",
  "December"
];

Date.getShortMonthName = function(month) {
  return Date.monthNames[month].substring(0, 3);
};

Date.monthNumbers = {
  Jan : 0,
  Feb : 1,
  Mar : 2,
  Apr : 3,
  May : 4,
  Jun : 5,
  Jul : 6,
  Aug : 7,
  Sep : 8,
  Oct : 9,
  Nov : 10,
  Dec : 11
};

Date.getMonthNumber = function(name) {
  return Date.monthNumbers[name.substring(0, 1).toUpperCase() + name.substring(1, 3).toLowerCase()];
};

Date.dayNames = [
  "Sunday",
  "Monday",
  "Tuesday",
  "Wednesday",
  "Thursday",
  "Friday",
  "Saturday"
];

Date.getShortDayName = function(day) {
  return Date.dayNames[day].substring(0, 3);
};

Date.parseCodes.S.s = "(?:st|nd|rd|th)";

if(Ext.MessageBox){
  Ext.MessageBox.buttonText = {
    ok     : "OK",
    cancel : "Cancel",
    yes    : "Yes",
    no     : "No"
  };
}

if(Ext.util.Format){
  Ext.util.Format.date = function(v, format){
    if(!v) return "";
    if(!(v instanceof Date)) v = new Date(Date.parse(v));
    return v.dateFormat(format || "m/d/Y");
  };
}

if(Ext.DatePicker){
  Ext.apply(Ext.DatePicker.prototype, {
    todayText         : "Today",
    minText           : "This date is before the minimum date",
    maxText           : "This date is after the maximum date",
    disabledDaysText  : "",
    disabledDatesText : "",
    monthNames        : Date.monthNames,
    dayNames          : Date.dayNames,
    nextText          : 'Next Month (Control+Right)',
    prevText          : 'Previous Month (Control+Left)',
    monthYearText     : 'Choose a month (Control+Up/Down to move years)',
    todayTip          : "{0} (Spacebar)",
    format            : "m/d/y",
    okText            : "&#160;OK&#160;",
    cancelText        : "Cancel",
    startDay          : 0
  });
}

if(Ext.PagingToolbar){
  Ext.apply(Ext.PagingToolbar.prototype, {
    beforePageText : "Page",
    afterPageText  : "of {0}",
    firstText      : "First Page",
    prevText       : "Previous Page",
    nextText       : "Next Page",
    lastText       : "Last Page",
    refreshText    : "Refresh",
    displayMsg     : "Displaying {0} - {1} of {2}",
    emptyMsg       : 'No data to display'
  });
}

if(Ext.form.BasicForm){
    Ext.form.BasicForm.prototype.waitTitle = "Please Wait..."
}

if(Ext.form.Field){
  Ext.form.Field.prototype.invalidText = "The value in this field is invalid";
}

if(Ext.form.TextField){
  Ext.apply(Ext.form.TextField.prototype, {
    minLengthText : "The minimum length for this field is {0}",
    maxLengthText : "The maximum length for this field is {0}",
    blankText     : "This field is required",
    regexText     : "",
    emptyText     : null
  });
}

if(Ext.form.NumberField){
  Ext.apply(Ext.form.NumberField.prototype, {
    decimalSeparator : ".",
    decimalPrecision : 2,
    minText : "The minimum value for this field is {0}",
    maxText : "The maximum value for this field is {0}",
    nanText : "{0} is not a valid number"
  });
}

if(Ext.form.DateField){
  Ext.apply(Ext.form.DateField.prototype, {
    disabledDaysText  : "Disabled",
    disabledDatesText : "Disabled",
    minText           : "The date in this field must be after {0}",
    maxText           : "The date in this field must be before {0}",
    invalidText       : "{0} is not a valid date - it must be in the format {1}",
    format            : "m/d/y",
    altFormats        : "m/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d|Y-m-d"
  });
}

if(Ext.form.ComboBox){
  Ext.apply(Ext.form.ComboBox.prototype, {
    loadingText       : "Loading...",
    valueNotFoundText : undefined
  });
}

if(Ext.form.VTypes){
  Ext.apply(Ext.form.VTypes, {
    emailText    : 'This field should be an e-mail address in the format "user@example.com"',
    urlText      : 'This field should be a URL in the format "http:/'+'/www.example.com"',
    alphaText    : 'This field should only contain letters and _',
    alphanumText : 'This field should only contain letters, numbers and _'
  });
}

if(Ext.form.HtmlEditor){
  Ext.apply(Ext.form.HtmlEditor.prototype, {
    createLinkText : 'Please enter the URL for the link:',
    buttonTips : {
      bold : {
        title: 'Bold (Ctrl+B)',
        text: 'Make the selected text bold.',
        cls: 'x-html-editor-tip'
      },
      italic : {
        title: 'Italic (Ctrl+I)',
        text: 'Make the selected text italic.',
        cls: 'x-html-editor-tip'
      },
      underline : {
        title: 'Underline (Ctrl+U)',
        text: 'Underline the selected text.',
        cls: 'x-html-editor-tip'
      },
      increasefontsize : {
        title: 'Grow Text',
        text: 'Increase the font size.',
        cls: 'x-html-editor-tip'
      },
      decreasefontsize : {
        title: 'Shrink Text',
        text: 'Decrease the font size.',
        cls: 'x-html-editor-tip'
      },
      backcolor : {
        title: 'Text Highlight Color',
        text: 'Change the background color of the selected text.',
        cls: 'x-html-editor-tip'
      },
      forecolor : {
        title: 'Font Color',
        text: 'Change the color of the selected text.',
        cls: 'x-html-editor-tip'
      },
      justifyleft : {
        title: 'Align Text Left',
        text: 'Align text to the left.',
        cls: 'x-html-editor-tip'
      },
      justifycenter : {
        title: 'Center Text',
        text: 'Center text in the editor.',
        cls: 'x-html-editor-tip'
      },
      justifyright : {
        title: 'Align Text Right',
        text: 'Align text to the right.',
        cls: 'x-html-editor-tip'
      },
      insertunorderedlist : {
        title: 'Bullet List',
        text: 'Start a bulleted list.',
        cls: 'x-html-editor-tip'
      },
      insertorderedlist : {
        title: 'Numbered List',
        text: 'Start a numbered list.',
        cls: 'x-html-editor-tip'
      },
      createlink : {
        title: 'Hyperlink',
        text: 'Make the selected text a hyperlink.',
        cls: 'x-html-editor-tip'
      },
      sourceedit : {
        title: 'Source Edit',
        text: 'Switch to source editing mode.',
        cls: 'x-html-editor-tip'
      }
    }
  });
}

if(Ext.grid.GridView){
  Ext.apply(Ext.grid.GridView.prototype, {
    sortAscText  : "Sort Ascending",
    sortDescText : "Sort Descending",
    columnsText  : "Columns"
  });
}

if(Ext.grid.GroupingView){
  Ext.apply(Ext.grid.GroupingView.prototype, {
    emptyGroupText : '(None)',
    groupByText    : 'Group By This Field',
    showGroupsText : 'Show in Groups'
  });
}

if(Ext.grid.PropertyColumnModel){
  Ext.apply(Ext.grid.PropertyColumnModel.prototype, {
    nameText   : "Name",
    valueText  : "Value",
    dateFormat : "m/j/Y"
  });
}

if(Ext.grid.BooleanColumn){
   Ext.apply(Ext.grid.BooleanColumn.prototype, {
      trueText  : "true",
      falseText : "false",
      undefinedText: '&#160;'
   });
}

if(Ext.grid.NumberColumn){
    Ext.apply(Ext.grid.NumberColumn.prototype, {
        format : '0,000.00'
    });
}

if(Ext.grid.DateColumn){
    Ext.apply(Ext.grid.DateColumn.prototype, {
        format : 'm/d/Y'
    });
}

if(Ext.layout.BorderLayout && Ext.layout.BorderLayout.SplitRegion){
  Ext.apply(Ext.layout.BorderLayout.SplitRegion.prototype, {
    splitTip            : "Drag to resize.",
    collapsibleSplitTip : "Drag to resize. Double click to hide."
  });
}

if(Ext.form.TimeField){
  Ext.apply(Ext.form.TimeField.prototype, {
    minText : "The time in this field must be equal to or after {0}",
    maxText : "The time in this field must be equal to or before {0}",
    invalidText : "{0} is not a valid time",
    format : "g:i A",
    altFormats : "g:ia|g:iA|g:i a|g:i A|h:i|g:i|H:i|ga|ha|gA|h a|g a|g A|gi|hi|gia|hia|g|H"
  });
}

if(Ext.form.CheckboxGroup){
  Ext.apply(Ext.form.CheckboxGroup.prototype, {
    blankText : "You must select at least one item in this group"
  });
}

if(Ext.form.RadioGroup){
  Ext.apply(Ext.form.RadioGroup.prototype, {
    blankText : "You must select one item in this group"
  });
}


/*
 * Ext JS Library 3.0 Pre-alpha
 * Copyright(c) 2006-2008, Ext JS, LLC.
 * licensing@extjs.com
 * 
 * http://extjs.com/license
 */


Ext.form.FileUploadField = Ext.extend(Ext.form.TextField,  {
    /**
     * @cfg {String} buttonText The button text to display on the upload button (defaults to
     * 'Browse...').  Note that if you supply a value for {@link #buttonCfg}, the buttonCfg.text
     * value will be used instead if available.
     */
    buttonText: 'Browse...',
    /**
     * @cfg {Boolean} buttonOnly True to display the file upload field as a button with no visible
     * text field (defaults to false).  If true, all inherited TextField members will still be available.
     */
    buttonOnly: false,
    /**
     * @cfg {Number} buttonOffset The number of pixels of space reserved between the button and the text field
     * (defaults to 3).  Note that this only applies if {@link #buttonOnly} = false.
     */
    buttonOffset: 3,
    /**
     * @cfg {Object} buttonCfg A standard {@link Ext.Button} config object.
     */

    // private
    readOnly: true,
    
    /**
     * @hide 
     * @method autoSize
     */
    autoSize: Ext.emptyFn,
    
    // private
    initComponent: function(){
        Ext.form.FileUploadField.superclass.initComponent.call(this);
        
        this.addEvents(
            /**
             * @event fileselected
             * Fires when the underlying file input field's value has changed from the user
             * selecting a new file from the system file selection dialog.
             * @param {Ext.form.FileUploadField} this
             * @param {String} value The file value returned by the underlying file input field
             */
            'fileselected'
        );
    },
    
    // private
    onRender : function(ct, position){
        Ext.form.FileUploadField.superclass.onRender.call(this, ct, position);
        
        this.wrap = this.el.wrap({cls:'x-form-field-wrap x-form-file-wrap'});
        this.el.addClass('x-form-file-text');
        this.el.dom.removeAttribute('name');
        
        this.fileInput = this.wrap.createChild({
            id: this.getFileInputId(),
            name: this.name||this.getId(),
            cls: 'x-form-file',
            tag: 'input', 
            type: 'file',
            size: 1
        });
        
        var btnCfg = Ext.applyIf(this.buttonCfg || {}, {
            text: this.buttonText
        });
        this.button = new Ext.Button(Ext.apply(btnCfg, {
            renderTo: this.wrap,
            cls: 'x-form-file-btn' + (btnCfg.iconCls ? ' x-btn-icon' : '')
        }));
        
        if(this.buttonOnly){
            this.el.hide();
            this.wrap.setWidth(this.button.getEl().getWidth());
        }
        
        this.fileInput.on('change', function(){
            var v = this.fileInput.dom.value;
            this.setValue(v);
            this.fireEvent('fileselected', this, v);
        }, this);
    },
    
    // private
    getFileInputId: function(){
        return this.id+'-file';
    },
    
    // private
    onResize : function(w, h){
        Ext.form.FileUploadField.superclass.onResize.call(this, w, h);
        
        this.wrap.setWidth(w);
        
        if(!this.buttonOnly){
            var w = this.wrap.getWidth() - this.button.getEl().getWidth() - this.buttonOffset;
            this.el.setWidth(w);
        }
    },
    
    // private
    preFocus : Ext.emptyFn,
    
    // private
    getResizeEl : function(){
        return this.wrap;
    },

    // private
    getPositionEl : function(){
        return this.wrap;
    },

    // private
    alignErrorIcon : function(){
        this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
    }
    
});
Ext.reg('fileuploadfield', Ext.form.FileUploadField);