﻿/*
* Epath AJAX bits
* Copyright? Not really you can nick it for all I care :).
*
* Some bits hear I have copied such as the Querystring and other bits are my own
*
* Paul Johnson
* p_j10@htomail.com
* 
* http://www.e-path.co.uk
*/


function ePath() {

    function getAppPath() {
        return this.appPath;
    }
    function setAppPath(path) {
        this.appPath = path;
    }
}
var $ePath = new ePath();


(function($) {

    //************************************************************************************
    //*  AJAX Bindable Drop Down
    //************************************************************************************
    ePath.dropDownList = function(dropDownElement, options) {
        this.dataSource = null;
        this.dataTextField = "";
        this.dataValueField = "";
        //this.dropDownElement = dropDownElement;
        this.selectedIndex = -1;
        this.change = null;
        this.selectedItem = null;

        var dropDownList = this;

        for (prop in options) {
            this[prop] = options[prop];
        }

        this.dataBind = function() {
            dropDownList.clear();
            $(dropDownList.dataSource).each(function(index) {
                var item = $('<option></option>');
                item[0].dataItem = this;
                item[0].value = this[dropDownList.dataValueField];
                item.text(this[dropDownList.dataTextField]);
                item.itemIndex = index;
                if (dropDownList.selectedIndex == index)
                    item.attr("selected", "selected");
                $(dropDownElement).append(item);
            });
            dropDownList.onDataBound();
            if (dropDownList.dataSource.length > 0)
                dropDownList.onChange(true);

        };

        this.clear = function() {
            $(">option", dropDownElement).remove();
        };

        this.onChange = function(populateChange) {
            dropDownList.selectedItem = $(">option:selected", dropDownElement)[0];
            if (typeof dropDownList.change != "undefined") {
                dropDownList.change({
                    value: dropDownList.selectedItem.value,
                    text: $(dropDownList.selectedItem).text(),
                    itemIndex: dropDownList.selectedItem.itemIndex,
                    populateChange: populateChange
                });
            }
        };

        $(dropDownElement).change(function() {
            dropDownList.onChange(false);
        });

        this.dataReceiveFunction = function(results) {
            dropDownList.dataSource = results;
            dropDownList.dataBind();
        };

        this.onDataBound = function() {
        };

        this.setSelectedValue = function(value) {
            $(dropDownElement).val(value);
        };
    };

    //************************************************************************************
    //*  AJAX Repeater
    //************************************************************************************

    ePath.repeater = function(options) {

        var repeaterItem = $(options.repeaterItem);
        var repeaterElement = $(options.repeater);
        var repeater = this;

        repeaterItem.remove();

        this.dataSource = null;

        this.dataBind = function() {
            $(">*", repeaterElement).remove();
            if (typeof options.header != "undefined")
                repeaterElement.append($(options.header).clone(true));
            $(repeater.dataSource).each(function(index) {
                var item = repeaterItem.clone(true);
                item[0].dataItem = this;
                repeaterElement.append(item);
                if (typeof options.onItemDataBound != "undefined")
                    options.onItemDataBound(item, this, index);
            });
        };

        for (prop in options) {
            this[prop] = options[prop];
        }

    };


    //************************************************************************************
    //*  Empty value jQuery extension.   Sets textboxes display text if empty and removes it on blur
    //************************************************************************************
    jQuery.prototype.emptyValue = function(text) {
        var control = this;
        this.each(function(index) {
            if (this.value == "")
                this.value = text;
            this.emptyValue = text;
            this.title = text;
        });
        this.focus(function() {
            if (this.value == text)
                this.value = "";
        });
        this.blur(function() {
            if (this.value == "")
                this.value = text;
        });
        $(this).parents("form").eq(0).submit(function() {
        if (control.val() == text)
                control.val("");
        });

        return this;
    };

    //************************************************************************************
    //*  Trim
    //************************************************************************************

    String.prototype.lTrim = function(chars) {
        chars = chars || "\\s";
        return this.replace(new RegExp("^[" + chars + "]+", "g"), "");
    };

    String.prototype.rTrim = function(chars) {
        chars = chars || "\\s";
        return this.replace(new RegExp("[" + chars + "]+$", "g"), "");
    };

    String.prototype.trim = function(chars) {
        return this.rTrim(chars).lTrim(chars);
    };



    //************************************************************************************
    //*  Pad
    //************************************************************************************

    String.prototype.padLeft = function(ch, num) {
        var re = new RegExp(".{" + num + "}$");
        var pad = "";
        if (!ch) ch = " ";
        do {
            pad += ch;
        } while (pad.length < num);
        return re.exec(pad + this) + "";
    };

    String.prototype.padRight = function(ch, num) {
        var re = new RegExp("^.{" + num + "}");
        var pad = "";
        if (!ch) ch = " ";
        do {
            pad += ch;
        } while (pad.length < num);
        return re.exec(val + this);
    };

    //************************************************************************************
    //*  Validation.  Added to jQuery
    //*
    //*  Call addValidator on the elements that contain the form.  e.g.
    //* 
    //* $("#formCont").addValidator({
    //*     submitButtons: $("#formCont").find("input[name=download]"),
    //*     invalidCss: { border: "solid 1px red" },
    //*     showErrorLabel: false,
    //*     validCss: { border: "solid 1px green" },
    //*     fields: {
    //*         email: { selector: "[name=email]", email: true },
    //*         name: { selector: "[name=name]", required: true },
    //*         company: { selector: "[name=company]", required: true }
    //*     }
    //* });
    //*
    //************************************************************************************

    $.prototype.addValidator = function(options) {
        var rootControl = this;
        var validatingControls = new Array();
        var errorLabel = $('<label class="error"></label>');
        var allFields = new Object();

        if (options.submitButtons) {
            if (typeof options.submitButtons == "string")
                options.submitButtons = $(options.submitButtons);
            options.submitButtons.click(function() {
                var allValid = validateAll();
                if (allValid && options.submitSuccess) {
                    for (prop in options.fields) {
                        var field = options.fields[prop];
                        if (field.controls.length > 0) {
                            var firstCont = $(field.controls[0]);
                            if (firstCont.attr("name") && typeof firstCont.val() == "string")
                                allFields[firstCont.attr("name")] = firstCont.val();
                        }
                    }
                    //options.submitSuccess(allFields, rootControl);
                }
                if (!allValid && options.submitFailed)
                    options.submitFailed();
                return allValid;
            });
        }
        for (prop in options.fields) {
            var field = options.fields[prop];
            if (options.invalidCss && !field.invalidCss)
                field.invalidCss = options.invalidCss;
            if (options.validCss && !field.validCss)
                field.validCss = options.validCss;

            if (options.showErrorLabel && !field.showErrorLabel && field.showErrorLabel !== false)
                field.showErrorLabel = options.showErrorLabel;

            field.controls = new Array();

            rootControl.find(field.selector).each(function() {
                this.validationInfo = field;
                this.validationMessages = new Array();
                this.isValid = true;
                this.errorLabel = errorLabel.clone();
                Array.add(field.controls, [this]);


                if (field.infoText) {
                    var infoText = field.infoText;
                    $(this).val(field.infoText);
                    $(this).focus(function() {
                        if ($(this).val() == infoText)
                            $(this).val("");
                    }).blur(function() {
                        if ($(this).val() == "")
                            $(this).val(infoText);
                    });
                }

                if (field.required === true)
                    field.required = { active: true };
                if (field.email === true) {
                    field.email = { active: true };
                }
                if (field.minLength && !field.minLength.length)
                    field.minLength = { active: true, length: field.minLength };

                $.merge(validatingControls, [this]);
            });
        }

        function validateAll() {
            var isValid = true;
            $(validatingControls).each(function() {
                if (!validate(this))
                    isValid = false;
            });
            return isValid;
        }

        function reValidate() { validate(this); }

        function validate(control) {
            var isValid = true;
            control.validationMessages = new Array();
            $(control).unbind('change', reValidate);
            $(control).unbind('keyup', reValidate);
            $(control).change(reValidate);
            $(control).keyup(reValidate);


            if (control.validationInfo.email || control.validationInfo.minLength)
                control.validationInfo.required = true;

            //Required Field
            if (control.validationInfo.required &&
                    ($.trim($(control).val()) == "" || (control.emptyValue && $(control).val() == control.emptyValue))
                    ) {
                $.merge(control.validationMessages, ["This field is required."]);
                isValid = false;
                control.validationInfo.required.isValid = false;
            } else if (control.validationInfo.required)
                control.validationInfo.required.isValid = true;

            //Email check
            if (control.validationInfo.email) {
                var emailRegEx = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
                if (!$(control).val().match(emailRegEx)) {
                    if (control.validationInfo.required.isValid === true)
                        $.merge(control.validationMessages, ["Please enter a valid email address."]);
                    isValid = false;
                    control.validationInfo.email.isValid = false;
                } else
                    control.validationInfo.email.isValid = true;
            }

            //Min Length Check
            if (control.validationInfo.minLength) {
                if (String($(control).val()).length < control.validationInfo.minLength.length) {
                    if (control.validationInfo.required.isValid === true)
                        $.merge(control.validationMessages, ["Please enter at least " + control.validationInfo.minLength.length + " characters."]);
                    isValid = false;
                    control.validationInfo.minLength.isValid = false;
                } else
                    control.validationInfo.minLength.isValid = true;
            }

            if (control.validationInfo.validCss && isValid)
                $(control).css(control.validationInfo.validCss);
            else if (control.validationInfo.validCss && !isValid)
                $(control).css(control.validationInfo.invalidCss);

            control.errorLabel.remove();
            var errMessage = "";
            $(control.validationMessages).each(function() {
                errMessage += this + "<br />";
            });
            control.errorLabel.html(errMessage);
            if (!isValid && control.validationInfo.showErrorLabel)
                $(control).after(control.errorLabel);


            control.isValid = isValid;
            return isValid
        }

        return this;

    };

    $ePath.validation = {
        isEmail: function(email) {
            var emailRegEx = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
            if (email.match(emailRegEx))
                return true;
            else
                return false;
        }
    };


    //************************************************************************************
    //*  Default Buttons
    //************************************************************************************
    $ePath.addDefaultButton = function(inputBox, button) {
        jQuery(inputBox).keypress(function(e) {
            if (e.which == 13) {
                jQuery(button).click();
                if (jQuery(button).attr("href"))
                    eval(jQuery(button).attr("href"));
                return false;
            }
        });

    };


    //************************************************************************************
    //*  Request QueryString
    //************************************************************************************
    (function() {
        var qsss = new Querystring();
        $ePath.queryString = qsss.params;
    })();

    //************************************************************************************
    //*  File Upload by Paul Johnson
    //************************************************************************************
    ePath.prototype.FileUpload = function(options) {
        if (!options)
            options = new Object();
        this.element = null;
        this.savePaths = new Array();
        this.viewUrl = "";
        this.dom = jQuery('<div style="display:block;float:none;"><iframe style="display:block;float:left;" width="235" height="25" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="' + (options.handlerPath ? options.handlerPath : document.appPath + 'CMS/AddImages.aspx') + '"></iframe><div stlye="float:left; padding-top:2px;">' +
        (options.enableView == null || options.enableView === true ? '<a class="fu_view" href="#">View</a>&nbsp;' : '') +
        (options.enableDelete == null || options.enableDelete === true ? '<a class="fu_delete" href="#">Delete</a>' : '') +
        '<div><div style="clear:both;"></div></div>');
        this.uploadPage = null;
        var fu = this;


        jQuery(".fu_view,.fu_delete", this.dom).css({ display: "none" });
        jQuery(".fu_delete", this.dom).css({ color: "red" });

        jQuery("iframe", fu.dom).load(function() {
            fu.uploadPage = jQuery("iframe", fu.dom)[0].contentWindow;
            fu.testViewUrl();
        });


        this.renderTo = function(renderTo) {
            fu.element = jQuery(renderTo).get(0); jQuery(fu.element).append(fu.dom);
        };

        this.addSaveLocation = function(path, name, argument, width, height, resizeType) {
            var savePath = new Object();
            savePath.path = path;
            savePath.name = name;
            savePath.argument = argument;
            savePath.width = width;
            savePath.height = height;
            savePath.resizeType = resizeType;
            Array.add(fu.savePaths, savePath);
        };

        this.clearSaveLocations = function() {
            Array.clear(fu.savePaths);
        };

        this.setViewUrl = function(url) {
            fu.viewUrl = url;
            fu.testViewUrl();
        };

        this.deleteFiles = function() {
            var message = "Are you sure you want to delete this/these files?\r\n";
            jQuery(fu.savePaths).each(function() {
                message += this.path + "\r\n";
            });
            if (confirm(message)) {
                fu.uploadPage.setSavePaths(Sys.Serialization.JavaScriptSerializer.serialize(fu.savePaths));
                fu.uploadPage.__doPostBack("lbtnDelete", "");
            }
        };

        this.testViewUrl = function() {
            var newImage = jQuery('<img />');
            var viewUrlRnd = fu.viewUrl + ("?r=" + Math.random()).replace(".", "");
            var segments = fu.viewUrl.split('.');
            var extension = segments[segments.length - 1];
            switch (extension.toLowerCase()) {
                case "jpg":
                case "gif":
                case "png":
                    newImage.load(function() {
                        fu.fileUploaded(viewUrlRnd.replace("~/", document.appPath));
                        jQuery(".fu_view", fu.dom).unbind();
                        jQuery(".fu_view", fu.dom).click(function() {
                            parent.Shadowbox.open({ type: 'img', fadeDuration: 0.1, resizeDuration: 0.1, content: viewUrlRnd.replace("~/", document.appPath) });
                            return false;
                        });
                        jQuery(".fu_delete", fu.dom).unbind();
                        jQuery(".fu_delete", fu.dom).click(function() {
                            fu.deleteFiles();
                            return false;
                        });
                        jQuery(".fu_view,.fu_delete", fu.dom).css({ display: "" });
                    }).error(function() {
                        jQuery(".fu_view,.fu_delete", fu.dom).css({ display: "none" });
                    });
                    newImage.attr('src', viewUrlRnd.replace("~/", document.appPath));
                    break;
                default:
                    jQuery(".fu_view,.fu_delete", fu.dom).css({ display: "" });
                    break;
            }
        };

        this.uploadFile = function() {

            $("iframe", fu.element).load(fu.fileUploaded);
            //$($("iframe", fu.dom)[0].contentWindow.document).ready(function() { alert("ready"); });
            //            $("iframe", fu.dom)[0].contentWindow.load(function() { alert("hi"); });
            fu.uploadPage.setSavePaths(Sys.Serialization.JavaScriptSerializer.serialize(fu.savePaths));
            fu.uploadPage.showProgress();
            fu.uploadPage.__doPostBack("lbtnUpload", "");
        };

        this.fileUploaded = function(url) { };

    };

    //$ePath.FileUpload.appPath = "";


    //************************************************************************************
    //*  Number Textbox by Paul Johnson
    //************************************************************************************
    $ePath.NumberTextboxClass = function() {

    };

    $ePath.NumberTextboxClass.prototype = {
        addTextboxJq: function(jqElements) {
            var prevVal = "";
            jqElements.keydown(function(event) {
                prevVal = this.value;
                if (event.keyCode < 30 || event.keyCode == 46 || event.keyCode == 190 || (event.keyCode >= 48 && event.keyCode <= 57))
                    return true;
                else if (event.keyCode == 8)
                    return true;
                else
                    return false;
            });
            jqElements.keyup(function(event) {
                if (/^\.\d{0,}$/.test(this.value)) {
                    this.value = "0" + this.value;
                }
                if (/^\d+\.{0,1}\d{0,}$/.test(this.value) || this.value == "") {
                } else {
                    this.value = prevVal;
                }
            });
        },
        addTextbox: function(element) {
            this.addTextboxJq(jQuery(element));
        }
    };


    $ePath.NumberTextbox = new $ePath.NumberTextboxClass();

    Array.prototype.dedupe = function() {
        var newArray = new Array();
        var seen = new Object();
        for (var i = 0; i < this.length; i++) {
            if (seen[this[i]]) continue;
            newArray.push(this[i]);
            seen[this[i]] = 1;
        }
        return newArray;
    };

    $ePath.highlighting = new Object();
    $ePath.highlighting.outline = new Object();

    //************************************************************************************
    //*  Outline an element.
    //************************************************************************************
    (function() {
        var outline = jQuery("<div></div><div></div><div></div><div></div>");
        outline.css({ backgroundColor: "#ffdd66", position: "absolute", display: "none", outline: "solid 1px #ffaa44"  });
        $ePath.highlighting.outline.show = function(s) {
            if (!s.outlineOn) {
                s.outlineOn = true;
                s.outline = outline.clone();
                jQuery(document.body).append(s.outline);
                setSize();
                s.outline.fadeIn(300);
                return true;
            }
            setSize();
            return false;

            function setSize() {
                var offset = jQuery(s).offset();
                var width = s.offsetWidth;
                var height = s.offsetHeight;
                s.outline.eq(0).css({ height: height + 3 + "px", width: "3px", top: offset.top - 3, left: offset.left - 3 });
                s.outline.eq(1).css({ height: height + 3 + "px", width: "3px", top: offset.top - 3, left: offset.left + width });
                s.outline.eq(2).css({ height: "3px", width: width + 6 + "px", top: offset.top - 3, left: offset.left - 3 });
                s.outline.eq(3).css({ height: "3px", width: width + 6 + "px", top: offset.top + height, left: offset.left - 3 });
            }
        };

        $ePath.highlighting.outline.hide = function(s) {
            s.outlineOn = false;
            var outlineToRemove = s.outline;
            s.outline.fadeOut(600, function() { outlineToRemove.remove(); });
        };

        $ePath.highlighting.outline.blink = function(s, onTime) {
            var theOnTime = 1000;
            if (onTime)
                theOnTime = onTime;
            if ($ePath.highlighting.outline.show(s))
                setTimeout(function() { $ePath.highlighting.outline.hide(s); }, theOnTime);
        };
    })();

})(jQuery);


//************************************************************************************
//*  Ext JS extensions
//************************************************************************************
if (this.Ext) {
    Ext.grid.GridPanel.prototype.getSelectedIndex = function() {
        var theGrid = this;
        var index = 0;
        var selectedIndex = -1;
        jQuery(this.store.data).each(function() {
            if (theGrid.getSelectionModel().isSelected(index))
                selectedIndex = index;
            index++;
        });
        return selectedIndex;
    };
}

//************************************************************************************
//*  Variouse bits by other people
//************************************************************************************

function Querystring(qs) { // optionally pass a querystring to parse
    this.params = {};

    if (qs == null) qs = location.search.substring(1, location.search.length);
    if (qs.length == 0) return;

    // Turn <plus> back to <space>
    // See: http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4.1
    qs = qs.replace(/\+/g, ' ');
    var args = qs.split('&'); // parse out name/value pairs separated via &

    // split out each name=value pair
    for (var i = 0; i < args.length; i++) {
        var pair = args[i].split('=');
        var name = decodeURIComponent(pair[0]);

        var value = (pair.length == 2)
			? decodeURIComponent(pair[1])
			: name;

        this.params[name] = value;
    }
}

Querystring.prototype.get = function(key, default_) {
    var value = this.params[key];
    return (value != null) ? value : default_;
};

Querystring.prototype.set = function(key, value) {
    this.params[key] = value;
};

Querystring.prototype.getQuerystring = function() {
    var qs = "";
    for (var i in this.params) {
        if (qs != "") qs += "&";
        qs += (i + "=" + this.params[i]);
    }
    return qs;
};

Querystring.prototype.contains = function(key) {
    var value = this.params[key];
    return (value != null);
};


///* Prevent Firefox store of Viewstate */
//function setAutoCompleteOff(id) {
//    var elem = document.getElementById(id);
//    if(elem) {
//        elem.setAttribute('autocomplete', 'off');
//    }            
//}

//setAutoCompleteOff('__VIEWSTATE');
//setAutoCompleteOff('__EVENTTARGET');
//setAutoCompleteOff('__EVENTARGUMENT');
//setAutoCompleteOff('__EVENTVALIDATION');

/****************/

function ePath() {
    this.switchToSync = function() {
        var __xmlHttpRequest = window.XMLHttpRequest;
        window.XMLHttpRequest = XMLHttpRequest = function() {
            var _xmlHttp = null;
            if (!__xmlHttpRequest) {
                try {
                    _xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
                }
                catch (ex) { }
            }
            else {
                _xmlHttp = new __xmlHttpRequest();
            }

            if (!_xmlHttp) return null;

            this.abort = function() { return _xmlHttp.abort(); };
            this.getAllResponseHeaders = function() { return _xmlHttp.getAllResponseHeaders(); };
            this.getResponseHeader = function(header) { return _xmlHttp.getResponseHeader(header); };
            this.open = function(method, url, async, user, password) {
                return _xmlHttp.open(method, url, false, user, password);
            };
            this.send = function(body) {
                _xmlHttp.send(body);
                this.readyState = _xmlHttp.readyState;
                this.responseBody = _xmlHttp.responseBody;
                this.responseStream = _xmlHttp.responseStream;
                this.responseText = _xmlHttp.responseText;
                this.responseXML = _xmlHttp.responseXML;
                this.status = _xmlHttp.status;
                this.statusText = _xmlHttp.statusText;
                this.onreadystatechange();
            };
            this.setRequestHeader = function(name, value) { return _xmlHttp.setRequestHeader(name, value); };
        };
    };
}

var Imtech = Imtech || {};

Imtech.Utils = {
    date: {
        "1033": {
            monthsLong: ["January", "Febraury", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
            monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
            daysLong: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
            daysShort: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
            patterns: {
                "d": "M/d/yyyy",
                "D": "dddd, MMMM dd, yyyy",
                "f": "dddd, MMMM dd, yyyy H:mm tt",
                "F": "dddd, MMMM dd, yyyy H:mm:ss tt",
                "g": "M/d/yyyy H:mm tt",
                "G": "M/d/yyyy H:mm:ss tt",
                "m": "MMMM dd",
                "o": "yyyy-MM-ddTHH:mm:ss.fff",
                "s": "yyyy-MM-ddTHH:mm:ss",
                "t": "H:mm tt",
                "T": "H:mm:ss tt",
                "U": "dddd, MMMM dd, yyyy HH:mm:ss tt",
                "y": "MMMM, yyyy"
            },
            tt: {
                "AM": "AM",
                "PM": "PM"
            },
            clockType: 12
        },
        "1043": {
            monthsLong: ["januari", "febrauri", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december"],
            monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"],
            daysLong: ["maandag", "dinsdag", "woensdag", "donderdag", "vridag", "zaterdag", "zondag"],
            daysShort: ["ma", "di", "wo", "do", "vr", "za", "zo"],
            patterns: {
                "d": "d-M-yyyy",
                "D": "dddd d MMMM yyyy",
                "f": "dddd d MMMM yyyy H:mm",
                "F": "dddd d MMMM yyyy H:mm:ss",
                "g": "d-M-yyyy H:mm",
                "G": "d-M-yyyy H:mm:ss",
                "m": "dd MMMM",
                "o": "yyyy-MM-ddTHH:mm:ss.fff",
                "s": "yyyy-MM-ddTHH:mm:ss",
                "t": "H:mm",
                "T": "H:mm:ss",
                "U": "dddd d MMMM yyyy HH:mm:ss",
                "y": "MMMM, yyyy"
            },
            tt: {
                "AM": "",
                "PM": ""
            },
            clockType: 24
        }
    }
}

Date.prototype.format = function(format, locale) {
    var fd = this.toString();
    var dateFormat = Imtech.Utils.date[locale];
    if (typeof (dateFormat) !== "undefined") {
        var pattern = typeof (dateFormat.patterns[format]) !== "undefined" ? dateFormat.patterns[format] : format;

        fd = pattern.replace(/yyyy/g, this.getFullYear());
        fd = fd.replace(/yy/g, (this.getFullYear() + "").substring(2));

        var month = this.getMonth();
        fd = fd.replace(/MMMM/g, dateFormat.monthsLong[month].escapeDateTimeTokens());
        fd = fd.replace(/MMM/g, dateFormat.monthsShort[month].escapeDateTimeTokens());
        fd = fd.replace(/MM/g, month + 1 < 10 ? "0" + (month + 1) : month + 1);
        fd = fd.replace(/(\\)?M/g, function($0, $1) { return $1 ? $0 : month + 1; });

        var dayOfWeek = this.getDay();
        fd = fd.replace(/dddd/g, dateFormat.daysLong[dayOfWeek].escapeDateTimeTokens());
        fd = fd.replace(/ddd/g, dateFormat.daysShort[dayOfWeek].escapeDateTimeTokens());

        var day = this.getDate();
        fd = fd.replace(/dd/g, day < 10 ? "0" + day : day);
        fd = fd.replace(/(\\)?d/g, function($0, $1) { return $1 ? $0 : day; });

        var hour = this.getHours();
        if (dateFormat.clockType == 12) {
            if (hour > 12) {
                hour -= 12;
            }
        }

        fd = fd.replace(/HH/g, hour < 10 ? "0" + hour : hour);
        fd = fd.replace(/(\\)?H/g, function($0, $1) { return $1 ? $0 : hour; });

        var minutes = this.getMinutes();
        fd = fd.replace(/mm/g, minutes < 10 ? "0" + minutes : minutes);
        fd = fd.replace(/(\\)?m/g, function($0, $1) { return $1 ? $0 : minutes; });

        var seconds = this.getSeconds();
        fd = fd.replace(/ss/g, seconds < 10 ? "0" + seconds : seconds);
        fd = fd.replace(/(\\)?s/g, function($0, $1) { return $1 ? $0 : seconds; });

        fd = fd.replace(/fff/g, this.getMilliseconds());

        fd = fd.replace(/tt/g, this.getHours() > 12 || this.getHours() == 0 ? dateFormat.tt["PM"] : dateFormat.tt["AM"]);
    }

    return fd.replace(/\\/g, "");
}

String.prototype.escapeDateTimeTokens = function() {
    return this.replace(/([dMyHmsft])/g, "\\$1");
}
