/*
 *
 * Wijmo Library 3.20173.126
 * http://wijmo.com/
 *
 * Copyright(c) GrapeCity, Inc.  All rights reserved.
 * 
 * Licensed under the Wijmo Commercial License. Also available under the GNU GPL Version 3 license.
 * licensing@wijmo.com
 * http://wijmo.com/widgets/license/
 *
 */
/// <reference path="../../External/declarations/jquery.d.ts"/>
var wijmo;
(function (wijmo) {
    wijmo.expando = ".wijmo";

    /** @ignore */
    var WijmoError = (function () {
        function WijmoError(message) {
            this.message = message;
            this.stack = "Wijmo" + (new Error()).stack;
            this.name = "WijmoError";
        }
        return WijmoError;
    })();
    wijmo.WijmoError = WijmoError;
    var wijerr = WijmoError;
    wijerr.prototype = new Error();
    wijerr.prototype["constructor"] = wijerr;
})(wijmo || (wijmo = {}));

var wijmo;
(function (wijmo) {
    (function (data) {
        /** @ignore */
        var Expando = (function () {
            function Expando(object) {
                this.object = object;
            }
            Expando.getFrom = function (obj, create) {
                if (typeof create === "undefined") { create = true; }
                var propertyName = wijmo.expando, ext;
                if (Object(obj) !== obj)
                    return null;

                ext = obj[propertyName];
                if (ext && ext.object !== obj) {
                    ext = null;
                }

                if (create && !(ext instanceof Expando && Object.prototype.hasOwnProperty.call(obj, propertyName))) {
                    ext = new Expando(obj);
                    try  {
                        Object.defineProperty(obj, propertyName, {
                            value: ext,
                            configurable: false,
                            enumerable: false,
                            writable: false
                        });
                    } catch (e) {
                        obj[propertyName] = ext;
                    }
                }
                return ext;
            };
            return Expando;
        })();
        data.Expando = Expando;
    })(wijmo.data || (wijmo.data = {}));
    var data = wijmo.data;
})(wijmo || (wijmo = {}));

var wijmo;
(function (wijmo) {
    (function (data) {
        /** @ignore */
        (function (util) {
            function funcClass(ctor) {
                return function () {
                    var result = function () {
                        return ctor.prototype._call.apply(result, arguments);
                    };
                    $.extend(result, ctor.prototype);
                    ctor.apply(result, arguments);
                    return result;
                };
            }
            util.funcClass = funcClass;
        })(data.util || (data.util = {}));
        var util = data.util;
    })(wijmo.data || (wijmo.data = {}));
    var data = wijmo.data;
})(wijmo || (wijmo = {}));
/// <reference path="core.ts"/>
/// <reference path="util.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    (function (data) {
        var $ = jQuery;

        /** @ignore */
        var SubscriberEntry = (function () {
            function SubscriberEntry(handler, context) {
                this.handler = handler;
                this.context = context;
            }
            SubscriberEntry.prototype.trigger = function (args) {
                return this.handler.apply(this.context, args);
            };
            return SubscriberEntry;
        })();
        data.SubscriberEntry = SubscriberEntry;

        /** @ignore */
        var Subscribable = (function () {
            function Subscribable(defaultContext) {
                this.defaultContext = defaultContext;
                this._entries = [];
            }
            Subscribable.prototype.subscribe = function (handler, context) {
                var _this = this;
                if (typeof context === "undefined") { context = this.defaultContext; }
                var entry = new SubscriberEntry(handler, context);
                this._entries.push(entry);
                return {
                    dispose: function () {
                        return data.util.remove(_this._entries, entry);
                    }
                };
            };
            Subscribable.prototype.trigger = function () {
                var args = [];
                for (var _i = 0; _i < (arguments.length - 0); _i++) {
                    args[_i] = arguments[_i + 0];
                }
                data.util.each(this._entries, function (_, e) {
                    return e.trigger(args);
                });
            };

            Subscribable.makeSubscribable = function (obj) {
                var subscribable = new Subscribable(obj);
                obj.subscribe = $.proxy(subscribable.subscribe, subscribable);
                return subscribable;
            };
            return Subscribable;
        })();
        data.Subscribable = Subscribable;
        function isSubscriptable(subscribable) {
            return $.isFunction(subscribable.subscribe);
        }
        data.isSubscriptable = isSubscriptable;

        /** @ignore */
        var BaseObservable = (function () {
            function BaseObservable() {
            }
            BaseObservable.prototype.subscribe = function (handler, context) {
                this._subscribable = this._subscribable || new Subscribable(this);
                return this._subscribable.subscribe(handler, context);
            };
            BaseObservable.prototype._trigger = function () {
                var args = [];
                for (var _i = 0; _i < (arguments.length - 0); _i++) {
                    args[_i] = arguments[_i + 0];
                }
                if (this._subscribable) {
                    this._subscribable.trigger.apply(this._subscribable, arguments);
                }
            };
            return BaseObservable;
        })();
        data.BaseObservable = BaseObservable;

        /** @ignore */
        var _ReadOnlyObservable = (function (_super) {
            __extends(_ReadOnlyObservable, _super);
            function _ReadOnlyObservable(mutable) {
                _super.call(this);
                this.mutable = mutable;
            }
            _ReadOnlyObservable.prototype._call = function () {
                return this.mutable.value;
            };
            return _ReadOnlyObservable;
        })(BaseObservable);
        data._ReadOnlyObservable = _ReadOnlyObservable;
        var ReadOnlyObservable = data.util.funcClass(_ReadOnlyObservable);

        /** @ignore */
        var _MutableObservable = (function (_super) {
            __extends(_MutableObservable, _super);
            function _MutableObservable(value, checkNewValue) {
                if (typeof checkNewValue === "undefined") { checkNewValue = false; }
                _super.call(this);
                this.value = value;
                this.checkNewValue = checkNewValue;
            }
            _MutableObservable.prototype._call = function (newValue) {
                if (arguments.length > 0 && (!this.checkNewValue || newValue !== this.value)) {
                    this.value = newValue;
                    this._trigger(newValue);
                    if (this._readOnly) {
                        this._readOnly._trigger(newValue);
                    }
                }
                return this.value;
            };

            _MutableObservable.prototype.read = function () {
                this._readOnly = this._readOnly || new ReadOnlyObservable(this);
                return this._readOnly;
            };
            return _MutableObservable;
        })(BaseObservable);
        data._MutableObservable = _MutableObservable;
        var MutableObservable = data.util.funcClass(_MutableObservable);

        /** @ignore */
        var _NumericMutableObservable = (function (_super) {
            __extends(_NumericMutableObservable, _super);
            function _NumericMutableObservable(value) {
                _super.call(this, value, false);
                this.value = value;
            }
            _NumericMutableObservable.prototype.change = function (delta) {
                return this._call(this._call() + delta);
            };
            _NumericMutableObservable.prototype.inc = function () {
                return this.change(1);
            };
            _NumericMutableObservable.prototype.dec = function () {
                return this.change(-1);
            };
            return _NumericMutableObservable;
        })(_MutableObservable);
        data._NumericMutableObservable = _NumericMutableObservable;
        var NumericMutableObservable = data.util.funcClass(_NumericMutableObservable);

        function observable(value) {
            if (typeof value === "undefined") { value = null; }
            return new MutableObservable(value);
        }
        data.observable = observable;

        /** @ignore */
        function numericObservable(value) {
            if (typeof value === "undefined") { value = 0; }
            return new NumericMutableObservable(value);
        }
        data.numericObservable = numericObservable;

        /** @ignore */
        function observableWithNewValueCheck(value) {
            if (typeof value === "undefined") { value = null; }
            return new MutableObservable(value, true);
        }
        data.observableWithNewValueCheck = observableWithNewValueCheck;
        function isObservable(observable) {
            return $.isFunction(observable) && isSubscriptable(observable);
        }
        data.isObservable = isObservable;
    })(wijmo.data || (wijmo.data = {}));
    var data = wijmo.data;
})(wijmo || (wijmo = {}));
/// <reference path="../../Base/wijmo.d.ts"/>
/// <reference path="core.ts"/>
/// <reference path="observable.ts"/>
var wijmo;
(function (wijmo) {
    (function (data) {
        /** @ignore */
        (function (util) {
            var $ = jQuery;

            function clone(obj, deep) {
                if (typeof deep === "undefined") { deep = false; }
                if ($.isArray(obj)) {
                    obj = obj.slice(0);
                } else if ($.isPlainObject(obj)) {
                    obj = $.extend(!!deep, {}, obj);
                }
                return obj;
            }
            util.clone = clone;

            function isString(str) {
                return typeof str === "string" || str instanceof String;
            }
            util.isString = isString;
            function isNumeric(value) {
                return typeof value === "number";
            }
            util.isNumeric = isNumeric;

            function isInternalProperty(p) {
                return p === wijmo.expando || p === $.expando;
            }
            util.isInternalProperty = isInternalProperty;

            function each(obj, fn) {
                var _this = this;
                $.each(obj, function (key, value) {
                    if (!isInternalProperty(key)) {
                        return fn.call(_this, key, value);
                    }
                });
            }
            util.each = each;
            function map(obj, fn) {
                var result = $.map(obj, fn);
                delete result[wijmo.expando];
                return result;
            }
            util.map = map;

            function toStr(obj) {
                var text;
                if (obj && $.isFunction(obj.toString) && obj.toString !== Object.prototype.toString) {
                    text = obj.toString();
                } else {
                    text = JSON.stringify(obj);
                }
                if (text != null && text.length > 2 && text[0] === '"' && text[text.length - 1] === '"') {
                    text = text.substr(1, text.length - 2);
                }
                return text;
            }
            util.toStr = toStr;
            function format(format) {
                var args = [];
                for (var _i = 0; _i < (arguments.length - 1); _i++) {
                    args[_i] = arguments[_i + 1];
                }
                return format.replace(/{(\d+)}/g, function (m, index) {
                    return toStr(args[parseInt(index, 10)]);
                });
            }
            util.format = format;

            function every(obj, predicate) {
                var res = true;
                each(obj, function (key, value) {
                    res = value;
                    if (predicate) {
                        res = predicate.call(res, res, key);
                    }
                    if (!res) {
                        return false;
                    }
                });
                return res;
            }
            util.every = every;
            function some(obj, predicate) {
                var res = false;
                each(obj, function (key, value) {
                    res = value;
                    if (predicate) {
                        res = predicate.call(res, res, key);
                    }
                    if (res) {
                        return false;
                    }
                });
                return res;
            }
            util.some = some;

            function compare(a, b) {
                var i, len, cmp;

                if (a == null) {
                    return b == null ? 0 : -1;
                } else if (b == null) {
                    return 1;
                }

                if ($.isArray(a) && $.isArray(b)) {
                    len = Math.min(a.length, b.length);
                    for (i = 0; i < len; i++) {
                        cmp = compare(a[i], b[i]);
                        if (cmp !== 0) {
                            return cmp;
                        }
                    }
                    return a.length - b.length;
                } else if (isString(a) && isString(b)) {
                    a = a.toLowerCase();
                    b = b.toLowerCase();
                    return a < b ? -1 : a > b ? 1 : 0;
                }

                cmp = a - b;
                return isNaN(cmp) ? 0 : cmp;
            }
            util.compare = compare;

            function contains(array, elem) {
                return $.inArray(elem, array) >= 0;
            }
            util.contains = contains;
            function remove(array, elem) {
                var removed = 0, i;

                for (i = 0; i < array.length;) {
                    if (array[i] !== elem) {
                        i++;
                    } else {
                        array.splice(i, 1);
                        removed++;
                    }
                }
                return removed;
            }
            util.remove = remove;

            function pageCount(totalCount, pageSize) {
                if (totalCount == -1) {
                    return -1;
                } else if (totalCount == 0) {
                    return 0;
                } else if (!pageSize) {
                    return 1;
                } else {
                    return Math.ceil(totalCount / pageSize);
                }
            }
            util.pageCount = pageCount;
            ;

            function executeDelayed(fn, context) {
                var args = [];
                for (var _i = 0; _i < (arguments.length - 2); _i++) {
                    args[_i] = arguments[_i + 2];
                }
                function callback() {
                    return fn.apply(context, args);
                }

                if (typeof setTimeout === typeof undefined) {
                    return callback();
                } else {
                    setTimeout(callback, 10);
                }
            }
            util.executeDelayed = executeDelayed;

            function logError(message) {
                if (typeof console == "undefined")
                    return;
                if (console.error) {
                    console.error(message);
                } else if (console.log) {
                    console.log(message);
                }
            }
            util.logError = logError;

            function getProperty(obj, property) {
                var start = 0, value = obj, key;
                while (true) {
                    var point = property.indexOf('.', start);
                    if (point >= 0) {
                        key = property.substring(start, point);
                        start = point + 1;
                    } else if (start > 0) {
                        key = property.substring(start);
                    } else {
                        key = property;
                    }

                    value = value[key];
                    if (data.isObservable(value)) {
                        value = value();
                    }

                    if (point < 0) {
                        break;
                    }
                }
                return value;
            }
            util.getProperty = getProperty;
            function setProperty(obj, property, newValue) {
                var start = 0, key;
                while (true) {
                    var point = property.indexOf('.', start);
                    if (point >= 0) {
                        key = property.substring(start, point);
                        start = point + 1;
                    } else if (start > 0) {
                        key = property.substring(start);
                    } else {
                        key = property;
                    }

                    var value = obj[key];

                    if (point >= 0) {
                        if (data.isObservable(value)) {
                            value = value();
                        }
                        obj = value;
                    } else {
                        if (data.isObservable(value)) {
                            value(newValue);
                        } else {
                            obj[key] = newValue;
                        }
                        break;
                    }
                }
            }
            util.setProperty = setProperty;

            function isClassInstance(instance) {
                return typeof instance === "object" && !$.isArray(instance) && !$.isPlainObject(instance) && instance.constructor !== Object.prototype.constructor;
            }
            util.isClassInstance = isClassInstance;

            function convertDateProperties(entities) {
                util.each(entities, function (_, entity) {
                    if (!entity || typeof entity !== "object")
                        return;
                    util.each(entity, function (key, value) {
                        var match;
                        if (!util.isString(value))
                            return;
                        match = /\/Date\((-?\d+)\)\//.exec(value);
                        if (!match)
                            return;
                        entity[key] = new Date(parseInt(match[1], 10));
                    });
                });
            }
            util.convertDateProperties = convertDateProperties;

            var HashMapEntry = (function () {
                function HashMapEntry(key) {
                    this.key = key;
                }
                return HashMapEntry;
            })();
            util.HashMapEntry = HashMapEntry;

            var HashMap = (function () {
                function HashMap() {
                    this.hash = {};
                }
                HashMap.prototype.getEntry = function (key, create) {
                    if (typeof create === "undefined") { create = false; }
                    if (key === null) {
                        if (!this.nullEntry && create) {
                            this.nullEntry = new HashMapEntry(key);
                        }
                        return this.nullEntry;
                    }

                    var strKey = String(key);
                    var list = this.hash[strKey];
                    var entry;
                    if (list == null) {
                        if (!create) {
                            return null;
                        }

                        list = [];
                        this.hash[strKey] = list;
                    }

                    for (var i = 0; i < list.length; i++) {
                        if (list[i].key === key) {
                            return list[i];
                        }
                    }

                    if (create) {
                        entry = new HashMapEntry(key);
                        list.push(entry);
                    }

                    return null;
                };

                HashMap.prototype.containsKey = function (key) {
                    return !!this.getEntry(key);
                };

                HashMap.prototype.get = function (key, defaultValue) {
                    if (typeof defaultValue === "undefined") { defaultValue = null; }
                    var entry = this.getEntry(key);
                    return entry ? entry.value : defaultValue;
                };

                HashMap.prototype.put = function (key, value) {
                    this.getEntry(key, true).value = value;
                };
                return HashMap;
            })();
            util.HashMap = HashMap;
        })(data.util || (data.util = {}));
        var util = data.util;
    })(wijmo.data || (wijmo.data = {}));
    var data = wijmo.data;
})(wijmo || (wijmo = {}));
/// <reference path="util.ts"/>
var wijmo;
(function (wijmo) {
    /** @ignore */
    (function (data) {
        data.errors = {};
        data.errors._register = function (messages) {
            data.util.each(messages, function (name, msg) {
                function create() {
                    var fmtArgs = [];
                    for (var _i = 0; _i < (arguments.length - 0); _i++) {
                        fmtArgs[_i] = arguments[_i + 0];
                    }
                    var lastChar;
                    if ($.isFunction(msg)) {
                        msg = msg.apply(this, arguments);
                    } else if (arguments.length > 0) {
                        fmtArgs.unshift(msg);
                        msg = data.util.format.apply(this, fmtArgs);
                    }

                    msg = $.trim(msg);
                    lastChar = msg[msg.length - 1];
                    if (lastChar !== '.' && lastChar !== '!' && lastChar !== '?') {
                        msg += '.';
                    }

                    return new wijmo.WijmoError(msg);
                }

                data.errors[name] = function () {
                    throw create.apply(this, arguments);
                };
                data.errors[name].create = create;
            });
        };

        data.errors._register({
            indexOutOfBounds: "Index is outside the bounds of the array.",
            notImplemented: "The operation is not implemented",
            unsupportedOperation: "Unsupported operation",
            unsupportedFilterOperator: "Unsupported filter operator: {0}",
            unsupportedDataSource: "Unsupported data source",
            argument: function (paramName) {
                var message = "Unexpected argument value.";
                if (paramName) {
                    message += "\nParameter name: " + paramName;
                }
                return message;
            },
            argumentNull: "Argument '{0}' is null/undefined",
            noParser: "There is no parser for type '{0}'",
            noUrl: "Url is not specified",
            cantConvert: "Value can't be converted to type '{0}': '{1}'",
            noGlobalize: "Globalize is not defined. Make sure you include globalize.js",
            itemNotInView: "Item {0} is not in the data view",
            unsupportedFilterFormat: "The filter format is not supported",
            multiPropertyKeysNotSupported: "Entities with multiple properties in the primary key are not supported. Entity type: {0}",
            keyPropertyNotFound: "Key property not found in {0} entity type"
        });
    })(wijmo.data || (wijmo.data = {}));
    var data = wijmo.data;
})(wijmo || (wijmo = {}));
/// <reference path="dataView.ts"/>
var wijmo;
(function (wijmo) {
    (function (data) {
        /** @ignore */
        (function (filtering) {
            var $ = jQuery;

            filtering.opMap = {
                "==": "equals",
                doesnotcontain: "notcontain",
                "!=": "notequal",
                ">": "greater",
                "<": "less",
                ">=": "greaterorequal",
                "<=": "lessorequal",
                isnotempty: "notisempty",
                isnotnull: "notisnull"
            };

            function findOperator(name, throwIfNotFound) {
                if (typeof throwIfNotFound === "undefined") { throwIfNotFound = false; }
                name = name.toLowerCase();
                var op = filtering.ops[name];
                if (!op) {
                    var mappedName = filtering.opMap[name];
                    if (mappedName) {
                        op = filtering.ops[mappedName];
                    }
                }
                if (!op && throwIfNotFound)
                    data.errors.unsupportedFilterOperator(name);
                return op;
            }

            function normalizeCondition(cond) {
                var filter;
                if (!$.isPlainObject(cond)) {
                    return { operator: "==", op: filtering.ops.equals, value: cond };
                }

                var op = cond.operator || filtering.ops.equals;
                if (data.util.isString(cond.operator)) {
                    if (cond.operator.toLowerCase() === "nofilter")
                        return null;
                    op = findOperator(cond.operator, true);
                } else if (!$.isFunction(op.apply)) {
                    data.errors.unsupportedFilterOperator(op);
                }
                return { operator: cond.operator, op: op, value: cond.value };
            }
            filtering.normalizeCondition = normalizeCondition;

            function compile(filter) {
                var result = {
                    isEmpty: false,
                    original: filter,
                    func: null,
                    normalized: null
                };
                if ($.isFunction(filter)) {
                    result.func = filter;
                } else if ($.isArray(filter)) {
                    data.errors.unsupportedFilterFormat(filter);
                } else if (filter) {
                    result.normalized = {};
                    var hasConditions = false;
                    data.util.each(filter, function (prop, cond) {
                        if ($.isArray(cond)) {
                            data.errors.unsupportedFilterFormat();
                        }

                        cond = normalizeCondition(cond);
                        if (cond) {
                            result.normalized[prop] = cond;
                            hasConditions = true;
                        }
                    });

                    if (!hasConditions) {
                        result.normalized = null;
                    } else {
                        result.func = function (x) {
                            return data.util.every(result.normalized, function (cond, prop) {
                                var propValue = data.util.getProperty(x, prop);
                                return cond.op.apply(propValue, cond.value);
                            });
                        };
                    }
                }

                if (!result.normalized && !result.func) {
                    result.isEmpty = true;
                    result.func = function (x) {
                        return true;
                    };
                }

                return result;
            }
            filtering.compile = compile;

            //#region operators
            filtering.ops = (function () {
                var ops = {}, types = {
                    str: ["string"],
                    prim: ["string", "number", "datetime", "currency", "boolean"],
                    comparable: ["string", "number", "datetime", "currency"]
                };

                function op(name, displayName, arity, types, apply) {
                    return ops[name.toLowerCase()] = {
                        name: name,
                        displayName: displayName,
                        arity: arity,
                        applicableTo: types,
                        apply: apply
                    };
                }

                function preprocessOperand(value) {
                    if (value instanceof Date) {
                        value = value.getTime();
                    }
                    if (data.util.isString(value)) {
                        value = value.toLowerCase();
                    }
                    return value;
                }
                function bin(name, displayName, types, apply) {
                    op(name, displayName, 2, types, function (left, right) {
                        return apply(preprocessOperand(left), preprocessOperand(right));
                    });
                }
                function unary(name, displayName, types, apply) {
                    op(name, displayName, 1, types, apply);
                }
                function binprim(name, displayName, apply) {
                    bin(name, displayName, types.prim, apply);
                }
                function binstr(name, displayName, apply) {
                    bin(name, displayName, types.str, apply);
                }
                function bincomparable(name, displayName, apply) {
                    bin(name, displayName, types.comparable, apply);
                }

                // Primitive binary operators
                binprim("Equals", "Equals", function (l, r) {
                    return l == r;
                });
                binprim("NotEqual", "Not equal", function (l, r) {
                    return l != r;
                });
                bincomparable("Greater", "Greater than", function (l, r) {
                    return l > r;
                });
                bincomparable("Less", "Less than", function (l, r) {
                    return l < r;
                });
                bincomparable("GreaterOrEqual", "Greater or equal", function (l, r) {
                    return l >= r;
                });
                bincomparable("LessOrEqual", "Less or equal", function (l, r) {
                    return l <= r;
                });

                // String operators
                binstr("Contains", "Contains", function (left, right) {
                    return left == right || left && left.indexOf && left.indexOf(right) >= 0;
                });
                binstr("NotContain", "Does not contain", function (left, right) {
                    return left != right && (!left || !left.indexOf || left.indexOf(right) < 0);
                });
                binstr("BeginsWith", "Begins with", function (left, right) {
                    return left == right || left && left.indexOf && left.indexOf(right) == 0;
                });
                binstr("EndsWith", "Ends with", function (left, right) {
                    var idx;
                    if (!data.util.isString(left) || !data.util.isString(right))
                        return false;
                    idx = left.lastIndexOf(right);
                    return idx >= 0 && left.length - idx === right.length;
                });

                // Unary operators
                unary("IsEmpty", "Is empty", types.str, function (x) {
                    return !x && x !== 0 && x !== false;
                }); // null, undefined, or empty string
                unary("NotIsEmpty", "Is not empty", types.str, function (x) {
                    return !!x || x === 0 || x === false;
                });
                unary("IsNull", "Is null", types.prim, function (x) {
                    return x == null;
                });
                unary("NotIsNull", "Is not null", types.prim, function (x) {
                    return x != null;
                });

                return ops;
            })();
        })(data.filtering || (data.filtering = {}));
        var filtering = data.filtering;
    })(wijmo.data || (wijmo.data = {}));
    var data = wijmo.data;
})(wijmo || (wijmo = {}));
/// <reference path="dataView.ts"/>
var wijmo;
(function (wijmo) {
    (function (data) {
        /** @ignore */
        (function (sorting) {
            function normalize(sort) {
                var result = [];
                sort = data.util.isString(sort) ? sort.split(/,\s*/) : !$.isArray(sort) ? [sort] : sort.slice(0);

                sort = $.isArray(sort) ? sort.slice(0) : [sort];
                data.util.each(sort, function (_, prop) {
                    var asc = true, i;
                    if (prop == null)
                        return;
                    if (!data.util.isString(prop)) {
                        if (prop.property != null) {
                            result.push(prop);
                        }
                        return;
                    }

                    if (prop[0] === "-") {
                        asc = false;
                        prop = prop.substr(1);
                    } else {
                        var match = /\s(asc|desc)\s*$/.exec(prop);
                        if (match) {
                            prop = prop.substr(0, match.index);
                            asc = !(match[1] === "desc");
                        }
                    }

                    result.push({ property: prop, asc: asc });
                });

                return result.length > 0 ? result : null;
            }
            function compile(sort, compareTo) {
                if (typeof compareTo === "undefined") { compareTo = data.util.compare; }
                var normalized = normalize(sort);
                var result = {
                    isEmpty: true,
                    original: sort,
                    propertyCompareTo: compareTo,
                    compare: null,
                    normalized: normalized
                };

                if (normalized != null) {
                    result.isEmpty = false;
                    result.compare = function (a, b) {
                        var i = 0, cmp, descr;
                        for (i = 0; i < normalized.length; i++) {
                            descr = normalized[i];
                            cmp = compareTo(data.util.getProperty(a, descr.property), data.util.getProperty(b, descr.property));
                            if (cmp !== 0) {
                                if (!descr.asc) {
                                    cmp = -cmp;
                                }
                                return cmp;
                            }
                        }

                        return 0;
                    };
                }
                return result;
            }
            sorting.compile = compile;
        })(data.sorting || (data.sorting = {}));
        var sorting = data.sorting;
    })(wijmo.data || (wijmo.data = {}));
    var data = wijmo.data;
})(wijmo || (wijmo = {}));
/// <reference path="core.ts"/>
/// <reference path="filtering.ts"/>
/// <reference path="sorting.ts"/>
/// <reference path="arrayDataView.ts"/>
var wijmo;
(function (wijmo) {
    (function (_data) {
        var $ = jQuery;

        

        

        

        

        

        

        

        

        

        

        

        var dataViewFactories = [];

        /** Registers a new IDataView provider.
        * @param {IDataViewFactory} factory A function that creates a IDataView for a data source if possible. Otherwise returns null.
        * @returns An IDisposable that can be used to remove the registration.
        * @remarks
        * Use this method to provide your own IDataView implementation for a specific data source. See wijmo.data.breeze.ts for an example.
        */
        function registerDataViewFactory(factory) {
            if (!$.isFunction(factory)) {
                _data.errors.argument("factory");
            }
            dataViewFactories.push(factory);
            return {
                dispose: function () {
                    _data.util.remove(dataViewFactories, factory);
                }
            };
        }
        _data.registerDataViewFactory = registerDataViewFactory;

        registerDataViewFactory(function (view) {
            return isDataView(view) && view;
        });
        registerDataViewFactory(function (array) {
            return $.isArray(array) && new _data.ArrayDataView(array);
        });

        //#endregion Data view factories
        /** Creates an IDataView for a data source.
        * @param src A data source, can be anything that is supported by the registered IDataView providers
        * @returns An IDataView instance for the data source.
        */
        function asDataView(src) {
            if (isDataView(src))
                return src;
            var view = _data.util.some(dataViewFactories, function (p) {
                return p(src);
            });
            return view || _data.errors.unsupportedDataSource();
        }
        _data.asDataView = asDataView;

        /** Returns true if the view parameter is a IDataView */
        function isDataView(view) {
            return view && $.isFunction(view.count) && $.isFunction(view.item) && $.isFunction(view.getProperty);
        }
        _data.isDataView = isDataView;
    })(wijmo.data || (wijmo.data = {}));
    var data = wijmo.data;
})(wijmo || (wijmo = {}));
/// <reference path="core.ts"/>
/// <reference path="arrayDataView.ts"/>
var wijmo;
(function (wijmo) {
    /** @ignore */
    (function (data) {
        var $ = jQuery;

        var CurrencyManager = (function () {
            function CurrencyManager(array) {
                this.array = array;
                this.currentItem = data.observableWithNewValueCheck(null);
                this.currentPosition = data.observableWithNewValueCheck(-1);
                var syncing = false;
                function synced(fn) {
                    return function () {
                        if (syncing)
                            return;
                        syncing = true;
                        try  {
                            fn.apply(this, arguments);
                        } finally {
                            syncing = false;
                        }
                    };
                }

                this.currentItem.subscribe(synced(function (value) {
                    this.currentPosition(value == null ? -1 : $.inArray(value, this.array));
                }), this);

                this.currentPosition.subscribe(synced(function (value) {
                    if (!data.util.isNumeric(value))
                        data.errors.argument("value");
                    if (value < -1 || value >= this.array.length)
                        data.errors.indexOutOfBounds();
                    this.currentItem(value < 0 ? null : this.array[value]);
                }), this);
            }
            CurrencyManager.prototype.update = function () {
                var item = this.currentItem(), pos = this.currentPosition(), newIndex = $.inArray(item, this.array);

                if (newIndex < 0 && item == null && this._recentlyRemovedItem != null) {
                    newIndex = $.inArray(this._recentlyRemovedItem, this.array);
                }

                if (newIndex >= 0) {
                    if (item) {
                        this._recentlyRemovedItem = item;
                    }
                    this.currentPosition(newIndex);
                } else if (pos >= 0 && pos < this.array.length) {
                    this.currentItem(this.array[pos]);
                } else if (pos >= this.array.length && this.array.length > 0) {
                    pos = this.array.length - 1;
                    this.currentPosition(pos);
                    this.currentItem(this.array[pos]);
                } else {
                    this.currentPosition(-1);
                    this.currentItem(null);
                }
            };
            CurrencyManager.prototype.updateDelayed = function () {
                data.util.executeDelayed(this.update, this);
            };
            return CurrencyManager;
        })();
        data.CurrencyManager = CurrencyManager;
    })(wijmo.data || (wijmo.data = {}));
    var data = wijmo.data;
})(wijmo || (wijmo = {}));
/// <reference path="core.ts"/>
/// <reference path="errors.ts"/>
/// <reference path="dataView.ts"/>
/// <reference path="observable.ts"/>
/// <reference path="currency.ts"/>

var wijmo;
(function (wijmo) {
    (function (data) {
        var $ = jQuery;

        /** @ignore */
        var Shape = (function () {
            function Shape(onChanged) {
                this.onChanged = onChanged;
                this.filter = data.observable();
                this._compiledFilter = data.filtering.compile(null);
                this.sort = data.observable();
                this._compiledSort = data.sorting.compile(null);
                this.pageIndex = data.observable(0);
                this.pageSize = data.observable(0);
                this._skip = 0;
                this._take = -1;
                this.filter.subscribe(function (newValue) {
                    this.onFilterChanged(newValue);
                    onChanged();
                }, this);
                this.sort.subscribe(function () {
                    this._compiledSort = data.sorting.compile(this.sort());
                    onChanged();
                }, this);

                function updatePaging() {
                    if (this.pageSize() > 0 && this.pageIndex() >= 0) {
                        this._skip = this.pageSize() * this.pageIndex();
                        this._take = this.pageSize();
                    } else {
                        this._skip = 0;
                        this._take = -1;
                    }
                    onChanged(true);
                }
                this.pageIndex.subscribe(updatePaging, this);
                this.pageSize.subscribe(updatePaging, this);
            }
            Shape.prototype.onFilterChanged = function (newValue) {
                this._compiledFilter = data.filtering.compile(newValue);
            };
            Shape.prototype.setFilter = function (filter) {
                this.filter(filter);
            };

            Shape.prototype.update = function (shape) {
                if ("filter" in shape) {
                    this.setFilter(shape.filter);
                }
                if ("sort" in shape) {
                    this.sort(shape.sort);
                }
                if ("pageSize" in shape) {
                    this.pageSize(shape.pageSize);
                }
                if ("pageIndex" in shape) {
                    this.pageIndex(shape.pageIndex);
                }
            };

            Shape.prototype.apply = function (array, applyPaging, destination) {
                if (typeof applyPaging === "undefined") { applyPaging = true; }
                if (typeof destination === "undefined") { destination = null; }
                var i;

                // filter
                if (!this._compiledFilter.isEmpty) {
                    if (destination) {
                        destination.length = 0;
                    } else {
                        destination = [];
                    }
                    for (i = 0; i < array.length; i++) {
                        var item = array[i];
                        if (this._compiledFilter.func(item)) {
                            destination.push(item);
                        }
                    }
                } else {
                    // just clone it
                    if (!destination) {
                        destination = array.slice(0);
                    } else {
                        destination.length = array.length;
                        for (i = 0; i < array.length; i++) {
                            destination[i] = array[i];
                        }
                    }
                }

                // sort
                if (!this._compiledSort.isEmpty) {
                    this._stableSort(destination, this._compiledSort.compare);
                }

                // page
                var totalCount = destination.length;
                if (applyPaging && this._take > 0) {
                    if (this._skip > 0) {
                        destination.splice(0, Math.min(this._skip, destination.length));
                    }
                    if (this._take < destination.length) {
                        destination.length = this._take;
                    }
                }

                return { results: destination, totalCount: totalCount };
            };

            Shape.prototype._stableSort = function (arr, fn) {
                var isChrome = /chrom(e|ium)/.test(navigator.userAgent.toLowerCase()) && /Google Inc/.test(navigator.vendor);
                if (fn && isChrome) {
                    arr.forEach(function (ele, index) {
                        arr[index] = { index: index, value: ele };
                    });
                    arr.sort(function (c, d) {
                        var result = fn(c.value, d.value);
                        if (result === 0) {
                            return c.index - d.index;
                        }
                        return result;
                    });
                    arr.forEach(function (ele, index) {
                        arr[index] = ele.value;
                    });
                } else {
                    arr.sort(fn);
                }
            };

            Shape.prototype.toObj = function () {
                return {
                    filter: this._compiledFilter.normalized,
                    sort: this._compiledSort.normalized,
                    pageSize: this.pageSize(),
                    pageIndex: this.pageIndex()
                };
            };
            return Shape;
        })();
        data.Shape = Shape;

        var ArrayDataViewBase = (function () {
            function ArrayDataViewBase(shape) {
                this.isRemote = false;
                this.localPaging = true;
                //#region items
                /**
                * The element array of current view after client-side filtering/sorting/paging have been applied.
                */
                this.local = [];
                this._updatingShape = false;
                this._pageCount = data.observable(1);
                this._totalItemCount = data.numericObservable(0);
                //#endregion shape
                //#region loading
                this._isLoaded = data.observable(false);
                this._isLoading = data.observable(false);
                //#endregionn
                //#region editing
                this._currentEditItem = data.observable();
                this._isCurrentEditItemNew = false;
                this._currentEditItemSnapshot = null;
                this.isLoading = this._isLoading.read();
                this.isLoaded = this._isLoaded.read();
                this._changed = new data.Subscribable(this);

                this.currentEditItem = this._currentEditItem.read();
                this._initCurrency();
                this._initShape(shape);
            }
            /**
            * @ ignore
            */
            ArrayDataViewBase.prototype.dispose = function () {
            };

            /**
            * Returns the number of items in the current view after client-side filtering/sorting/paging have been applied.
            */
            ArrayDataViewBase.prototype.count = function () {
                return this.local.length;
            };

            /**
            * Returns an element in the view by index.
            * @ param {Number} index The zero-based index of the element to get
            * @ remarks Throws an exception if the index is out of range
            */
            ArrayDataViewBase.prototype.item = function (index) {
                if (index < 0 || index >= this.local.length) {
                    data.errors.indexOutOfBounds();
                }
                return this.local[index];
            };

            /**
            * Returns the index of the element in current view
            * @ param {object} item The element in current view.
            */
            ArrayDataViewBase.prototype.indexOf = function (item) {
                return $.inArray(item, this.local);
            };

            /**
            * Returns the element array before applying client-side filtering/sorting/paging.
            * @remarks In the case of a remote data source, usually it is the array returned by a server.
            */
            ArrayDataViewBase.prototype.getSource = function () {
                return this.sourceArray;
            };

            /**
            * Converts the element array of current view after filter, sort and paging have been applied to Obervable Array.
            */
            ArrayDataViewBase.prototype.toObservableArray = function () {
                if (!this._koArray) {
                    this._koArray = ko.observableArray(this.local);
                }
                return this._koArray;
            };

            //#endregion items
            //#region properties
            ArrayDataViewBase._getProps = function (item) {
                var cols = [];
                data.util.each(item, function (key, value) {
                    key = String(key);
                    if (key.match(/^_/))
                        return;
                    if ($.isFunction(value) && !value.subscribe)
                        return;
                    cols.push({ name: key });
                });
                return cols;
            };

            /**
            * Returns properties for elements in the view.
            */
            ArrayDataViewBase.prototype.getProperties = function () {
                return this.count() ? ArrayDataViewBase._getProps(this.item(0)) : [];
            };

            ArrayDataViewBase.prototype._readProperty = function (item, property) {
                return data.util.getProperty(item, property);
            };

            /**
            * Returns the current value of the property in the element at the specified index.
            * @ param {Object} itemOrIndex The element with the property value that is to be read
            * or the zero-based index of the element with the property value that is to be read.
            * @ param {string} property The name of the property to read
            * @ returns The current value of the property in the element
            */
            ArrayDataViewBase.prototype.getProperty = function (itemOrIndex, property) {
                var item = this._getItem(itemOrIndex);
                return this._readProperty(item, property);
            };
            ArrayDataViewBase.prototype._writeProperty = function (item, property, newValue) {
                data.util.setProperty(item, property, newValue);
            };

            /**
            * Sets the value of the property in the element.
            * @ param {Object} itemOrIndex The element with the property value that is to be read
            * or the zero-based index of the element with the property value that is to be read.
            * @ param {string} property The name of the property to set
            * @ param newValue The new value
            * @ remarks
            * If the class implementing IDataView also implements IEditableDataView and the element is being edited,
            * then the property value change is done within the editing transaction.
            */
            ArrayDataViewBase.prototype.setProperty = function (itemOrIndex, property, newValue) {
                var item = this._getItem(itemOrIndex);

                if (item === this.currentEditItem() && this._currentEditItemSnapshot && !(property in this._currentEditItemSnapshot)) {
                    this._currentEditItemSnapshot[property] = this.getProperty(itemOrIndex, property);
                }

                this._writeProperty(item, property, newValue);

                return this;
            };

            /**
            * Registers Subcription of changes for current view.
            * @ param {function} handler Function that will be called when current view is changed.
            * @ param {Object?} context Indicates which calls the handler function.
            */
            ArrayDataViewBase.prototype.subscribe = function (handler, context) {
                return this._changed.subscribe(handler, context);
            };

            /**
            * Triggers the changes for current view.
            */
            ArrayDataViewBase.prototype.trigger = function () {
                this._currencyManager.update();
                this._changed.trigger(this.local);
                if (this._koArray) {
                    this._koArray.notifySubscribers(this.local);
                }
            };

            /**
            * Returns a value that indicates whether the data view supports filtering.
            */
            ArrayDataViewBase.prototype.canFilter = function () {
                return true;
            };

            /**
            * Returns a value that indicates whether the data view supports sorting.
            */
            ArrayDataViewBase.prototype.canSort = function () {
                return true;
            };

            ArrayDataViewBase.prototype._updateShape = function (shape) {
                this._updatingShape = true;
                try  {
                    this._shape.update(shape);
                } finally {
                    this._updatingShape = false;
                }
            };

            /*
            * Goes to previous page of current view if paging has been applied.
            * @ remarks
            * If current page is the first page, it will return false.
            * Otherwise it will return true.
            */
            ArrayDataViewBase.prototype.prevPage = function () {
                if (this.pageIndex() < 1) {
                    return false;
                }
                this.pageIndex(this.pageIndex() - 1);
                return true;
            };

            /*
            * Goes to next page of current view if paging has been applied.
            * @ remarks
            * If current page is the last page, it will return false.
            * Otherwise it will return true.
            */
            ArrayDataViewBase.prototype.nextPage = function () {
                if (this.pageCount() > 0 && this.pageIndex() + 1 >= this.pageCount()) {
                    return false;
                }
                this.pageIndex(this.pageIndex() + 1);
                return true;
            };

            ArrayDataViewBase.prototype._createShape = function (onChanged) {
                return new Shape(onChanged);
            };
            ArrayDataViewBase.prototype._initShape = function (shape) {
                var _this = this;
                var onChanged = function (onlyPaging) {
                    if (typeof onlyPaging === "undefined") { onlyPaging = false; }
                    if (!_this._updatingShape) {
                        _this.refresh(null, onlyPaging && _this.localPaging);
                    }
                };

                this._shape = this._createShape(onChanged);
                if (shape) {
                    this._updateShape(shape);
                }
                this.filter = this._shape.filter;
                this.sort = this._shape.sort;
                this.pageIndex = this._shape.pageIndex;
                this.pageSize = this._shape.pageSize;
                this.pageCount = this._pageCount.read();
                this.totalItemCount = this._totalItemCount.read();
            };

            ArrayDataViewBase.prototype._localRefresh = function (doPaging) {
                if (typeof doPaging === "undefined") { doPaging = this.localPaging; }
                var result = this._shape.apply(this.sourceArray, doPaging, this.local);

                if (doPaging) {
                    this._totalItemCount(result.totalCount);
                }
                this._pageCount(data.util.pageCount(this.totalItemCount(), this.pageSize()));

                // notify
                this.trigger();
                return $.Deferred().resolve().promise();
            };
            ArrayDataViewBase.prototype._remoteRefresh = function () {
                return this._localRefresh();
            };

            /** Reloads the data view.
            *
            * @ param {IShape} shape
            * Settings for filtering, sorting and/or paging to be applied before loading.
            *
            * In contrast to filter/sort properties in IDataView,
            * the format of properties in the shape parameter does not have to follow the specs defined in IDataView.
            * For instance, BreezeDataView accepts a Breeze.Predicate as shape.filter.
            * However the IDataView properties must not violate the IDataView specs. If a custom filter format cannot be aligned to the IDataView specs,
            * then the properties values must be functions or null.
            *
            * @ param {boolean} local Prevents server requests and applies filtering/sorting/paging of the source array on the client-side.
            *
            * @ returns {IRefreshResult} A promise object that can be used to receive notification of asynchronous refresh completion or failure.
            *
            * @ remarks
            * Depending on the implementation, data can be loaded from a local or a remote data source.
            * The implementation transaltes filtering/sorting/paging defined in the IDataView to the data provider specific format.
            * If it is possible, then the data is reshaped on the client-side.
            *
            * The optional shape parameter can be used to change multiple filtering/sorting/paging settings at a time to avoid unnecessary refreshes.
            *
            * During the refresh, the isLoading property value must be true. After a successful refresh, the isLoaded property value must be true.
            *
            * When the method is called, the pending refresh, if any, is canceled.
            */
            ArrayDataViewBase.prototype.refresh = function (shape, local) {
                var _this = this;
                if (typeof local === "undefined") { local = false; }
                this.cancelRefresh();
                if (shape) {
                    this._updateShape(shape);
                }
                this._isLoading(true);
                var promise = local ? this._localRefresh() : this._remoteRefresh();
                return promise.then(function () {
                    _this._isLoaded(true);
                    _this._isLoading(false);
                });
            };

            /**
            * Cancels the ongoing refresh operation
            */
            ArrayDataViewBase.prototype.cancelRefresh = function () {
            };

            ArrayDataViewBase.prototype._initCurrency = function () {
                this._currencyManager = new data.CurrencyManager(this.local);
                this.currentItem = this._currencyManager.currentItem;
                this.currentPosition = this._currencyManager.currentPosition;
            };

            /**
            * Returns a value indicating whether the element being edited is added by the add(item) methods.
            */
            ArrayDataViewBase.prototype.isCurrentEditItemNew = function () {
                return this._isCurrentEditItemNew;
            };

            ArrayDataViewBase.prototype._beginEdit = function (item, isNew) {
                this.commitEdit();
                this._currentEditItemSnapshot = {};
                this._isCurrentEditItemNew = isNew;
                this._currentEditItem(item);
            };

            /**
            * Returns a value that indicates whether the add(item) method is implemented.
            */
            ArrayDataViewBase.prototype.canAdd = function () {
                return true;
            };

            /**
            * Adds a new element and marks it as being edited.
            * @ param {Object} item The item to add.
            * @ remarks
            * Adds a new element to the data view, but not to the underlying data source.
            * Commits the element currently being edited, if any.
            */
            ArrayDataViewBase.prototype.add = function (item) {
                if (!item)
                    data.errors.argument("item");
                this.commitEdit();
                this.local.push(item);
                this._beginEdit(item, true);
                this.trigger();
            };

            /**
            * Returns a value that indicates whether the addNew() method is implemented.
            */
            ArrayDataViewBase.prototype.canAddNew = function () {
                return false;
            };

            /*
            * @ignore
            */
            ArrayDataViewBase.prototype.addNew = function () {
                return data.errors.unsupportedOperation();
            };

            /**
            * Starts editing of an element at the index.
            * @ param {Object} element The element to edit.
            * Defaults to the value of IDataView.currentItem property.
            * @ remarks
            * Commits the element currently being edited, if any.
            */
            ArrayDataViewBase.prototype.editItem = function (item) {
                if (typeof item === "undefined") { item = this.currentItem(); }
                this.commitEdit();

                item = this._getItem(item);
                if (item) {
                    this._beginEdit(item, false);
                }
            };

            /**
            * Returns a value that indicates whether the remove method overloads are implemented.
            */
            ArrayDataViewBase.prototype.canRemove = function () {
                return true;
            };
            ArrayDataViewBase.prototype._remove = function (entry) {
                this.local.splice(entry.index, 1);
                data.util.remove(this.sourceArray, entry.item);
                this._totalItemCount.dec();
                this.trigger();
            };

            /**
            * Removes an element at the specified index.
            * @ param {Object} item The element to remove.
            * Defaults to the value of the IDataView.currentItem property.
            * @ remarks
            * If the element success removing, it will return true.
            * Otherwise it will return false.
            */
            ArrayDataViewBase.prototype.remove = function (item) {
                if (typeof item === "undefined") { item = this.currentItem(); }
                this.commitEdit();

                var entry = this._resolve(item);
                if (!entry)
                    return false;
                this._remove(entry);
                return true;
            };

            /**
            * Returns a value that indicates whether the current changes can be canceled.
            */
            ArrayDataViewBase.prototype.canCancelEdit = function () {
                return true;
            };

            /**
            * Cancels the changes made to the currently editing element since the editing was started.
            * @ remarks After a successful cancelation, the currentEditItem property value must be null.
            */
            ArrayDataViewBase.prototype.cancelEdit = function () {
                var _this = this;
                var key;
                if (!this.currentEditItem())
                    return;
                var item = this.currentEditItem();
                this._currentEditItem(null);

                if (this._isCurrentEditItemNew) {
                    data.util.remove(this.local, item);
                } else if (this._currentEditItemSnapshot) {
                    $.each(this._currentEditItemSnapshot, function (k, v) {
                        return _this._writeProperty(item, k, v);
                    });
                }
                this.trigger();
            };

            /**
            * Returns a value that indicates whether the current changes can be committed
            */
            ArrayDataViewBase.prototype.canCommitEdit = function () {
                return true;
            };

            /**
            * Commits the changes made to the currently editing element
            * @ remarks After a successful commit, the currentEditItem property value must be null.
            * If the item being edited was new, it is added to the underlying data source.
            * If the element does not satisfy the filter, then it is removed from the data view, but not from the data source.
            */
            ArrayDataViewBase.prototype.commitEdit = function () {
                if (!this.currentEditItem())
                    return;
                var item = this.currentEditItem();
                this._currentEditItem(null);

                if (this._isCurrentEditItemNew) {
                    this.sourceArray.push(item);
                    this._totalItemCount.inc();
                }

                var filter = this._shape._compiledFilter;
                if (!filter.isEmpty && !filter.func(item)) {
                    data.util.remove(this.local, item);
                }
                this.trigger();
            };

            //#endregion editing
            ArrayDataViewBase.prototype._getItem = function (itemOrIndex) {
                var index;
                if (data.util.isNumeric(itemOrIndex)) {
                    return this.item(itemOrIndex);
                } else {
                    return itemOrIndex;
                }
            };

            ArrayDataViewBase.prototype._resolve = function (itemOrIndex, raiseIfNotContained) {
                if (typeof raiseIfNotContained === "undefined") { raiseIfNotContained = false; }
                var index;
                if (data.util.isNumeric(itemOrIndex)) {
                    return {
                        index: itemOrIndex,
                        item: this.item(itemOrIndex)
                    };
                } else {
                    index = this.indexOf(itemOrIndex);
                    if (index < 0) {
                        if (raiseIfNotContained)
                            data.errors.itemNotInView(itemOrIndex);
                        return null;
                    }
                    return {
                        index: index,
                        item: itemOrIndex
                    };
                }
            };

            /** @ignore */
            ArrayDataViewBase.prototype.clone = function () {
                throw "Not supported.";
            };
            return ArrayDataViewBase;
        })();
        data.ArrayDataViewBase = ArrayDataViewBase;

        
        var ArrayDataView = (function (_super) {
            __extends(ArrayDataView, _super);
            function ArrayDataView(source, shape) {
                _super.call(this, shape);
                this.sourceArray = source;
                this.refresh();
            }
            /** @ignore */
            ArrayDataView.prototype.clone = function () {
                var shape = this._shape ? this._shape.toObj() : undefined;
                return new ArrayDataView(this.getSource(), shape);
            };
            return ArrayDataView;
        })(ArrayDataViewBase);
        data.ArrayDataView = ArrayDataView;
    })(wijmo.data || (wijmo.data = {}));
    var data = wijmo.data;
})(wijmo || (wijmo = {}));
//interface NavigatorID {
//    vendor: string;
//}
/// <reference path="arrayDataView.ts"/>
var wijmo;
(function (wijmo) {
    (function (data) {
        var $ = jQuery;

        var RemoteDataView = (function (_super) {
            __extends(RemoteDataView, _super);
            function RemoteDataView(options) {
                _super.call(this);
                this.isRemote = true;
                this.sourceArray = [];
                if (options) {
                    this._construct(options);
                }
            }
            RemoteDataView.prototype._construct = function (options) {
                this.options = options = $.extend({
                    localPaging: false
                }, options);
                this.localPaging = options.localPaging;
                this._updateShape(options);
            };
            return RemoteDataView;
        })(data.ArrayDataViewBase);
        data.RemoteDataView = RemoteDataView;
    })(wijmo.data || (wijmo.data = {}));
    var data = wijmo.data;
})(wijmo || (wijmo = {}));
;
/// <reference path="src/arrayDataView.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*globals jQuery, Globalize, wijmo */
    /*
    * Depends:
    *  wijmo.data.js
    *  globalize.js
    *  jquery.js
    *
    */
    (function (_data) {
        var $ = jQuery;

        var wijdatasourceReader = (function () {
            function wijdatasourceReader(originalReader) {
                this._originalReader = originalReader;
            }
            wijdatasourceReader.prototype.read = function (wijDataSource) {
                wijDataSource.items = null;

                if (this._originalReader && $.isFunction(this._originalReader.read)) {
                    this._originalReader.read(wijDataSource);
                }

                if (!$.isArray(wijDataSource.items)) {
                    if ($.isArray(wijDataSource.data)) {
                        wijDataSource.items = wijDataSource.data;
                    } else if (wijDataSource.data && $.isArray(wijDataSource.data.rows)) {
                        wijDataSource.items = wijDataSource.data.rows; // remoteDynamical
                    } else {
                        wijDataSource.items = [];
                    }
                }

                if (wijDataSource.dynamic) {
                    if (!wijDataSource.data || isNaN(wijDataSource.data.totalRows)) {
                        throw "totalRows value is missing";
                    }
                }
            };
            return wijdatasourceReader;
        })();

        var WijdatasourceView = (function (_super) {
            __extends(WijdatasourceView, _super);
            function WijdatasourceView(dataSource) {
                var _this = this;
                _super.call(this);
                this.dataSource = dataSource;
                this.isRemote = true;
                this.localPaging = true;

                this._origLoaded = dataSource.loaded;
                this._origReader = dataSource.reader;

                dataSource.loaded = function (e, data) {
                    _this._loaded();
                    if ($.isFunction(_this._origLoaded)) {
                        _this._origLoaded.apply(_this, arguments);
                    }
                };

                dataSource.reader = new wijdatasourceReader(dataSource.reader);

                var hasItems = dataSource.items && dataSource.items.length > 0;
                if ($.isArray(dataSource.data) && !hasItems) {
                    dataSource.read();
                }

                if (dataSource.items) {
                    this._loaded();
                }
            }
            WijdatasourceView.prototype.dispose = function () {
                this.dataSource.loaded = this._origLoaded;
                this.dataSource.reader = this._origReader;
                _super.prototype.dispose.call(this);
            };

            WijdatasourceView.prototype.getProperties = function () {
                return this.sourceArray && this.sourceArray.length ? _data.ArrayDataViewBase._getProps(this.sourceArray[0]) : [];
            };
            WijdatasourceView.prototype._loaded = function () {
                this.sourceArray = this.dataSource.items;
                if (this.dataSource.data && _data.util.isNumeric(this.dataSource.data.totalRows)) {
                    this._totalItemCount(this.dataSource.data.totalRows);
                }
                var def = _super.prototype._localRefresh.call(this, !this.dataSource.dynamic);
                if (this._currentDeferred) {
                    def.then(this._currentDeferred.resolve);
                }
            };

            WijdatasourceView.prototype._remoteRefresh = function () {
                if (this._currentDeferred && this._currentDeferred.state() === "pending") {
                    this._currentDeferred.fail();
                }
                this._currentDeferred = $.Deferred();

                var userData = {}, forceReload = false;

                if (this.dataSource.dynamic) {
                    forceReload = true;
                    userData.data = this._prepareRequest();
                    if (this.dataSource.proxy) {
                        if (!this._origDataOption) {
                            this._origDataOption = $.extend({}, this.dataSource.proxy.options.data);
                        }
                        this.dataSource.proxy.options.data = $.extend({}, this._origDataOption, userData.data);
                    }
                }

                this.dataSource.load(userData, forceReload);
                return this._currentDeferred;
            };

            WijdatasourceView.prototype._prepareRequest = function () {
                return {
                    filtering: this._prepareFilterRequest(),
                    paging: this._preparePageRequest(),
                    sorting: this._prepareSortRequest()
                };
            };

            WijdatasourceView.prototype._prepareFilterRequest = function () {
                var result = [];

                if (!this._shape._compiledFilter.isEmpty && this._shape._compiledFilter.normalized) {
                    $.each(this._shape._compiledFilter.normalized, function (prop, cond) {
                        result.push({
                            dataKey: prop,
                            filterOperator: cond.op.Name,
                            filterValue: cond.value
                        });
                    });
                }

                return result;
            };

            WijdatasourceView.prototype._preparePageRequest = function () {
                return {
                    pageIndex: this._shape.pageIndex(),
                    pageSize: this._shape.pageSize()
                };
            };

            WijdatasourceView.prototype._prepareSortRequest = function () {
                if (this._shape._compiledSort.isEmpty || !this._shape._compiledSort.normalized || this._shape._compiledSort.normalized.length == 0) {
                    return [];
                }

                return $.map(this._shape._compiledSort.normalized, function (sd) {
                    return {
                        dataKey: sd.property,
                        sortDirection: sd.asc ? "ascending" : "descending"
                    };
                });
            };
            return WijdatasourceView;
        })(_data.ArrayDataViewBase);

        _data.registerDataViewFactory(function (wds) {
            if (typeof wijdatasource !== "function" || !(wds instanceof wijdatasource))
                return;
            return new WijdatasourceView(wds);
        });
    })(wijmo.data || (wijmo.data = {}));
    var data = wijmo.data;
})(wijmo || (wijmo = {}));
;
/// <reference path="../Base/jquery.wijmo.widget.ts"/>
/*globals jQuery*/
/*jslint white: false */
/*
* Depends:
*  jquery-1.11.1.js
*  jquery.ui.core.js
*  jquery.ui.widget.js
*  jquery.wijmo.widget.js
*/
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    (function (pager) {
        var $ = jQuery;

        /** @widget */
        var wijpager = (function (_super) {
            __extends(wijpager, _super);
            function wijpager() {
                _super.apply(this, arguments);
            }
            wijpager.prototype._create = function () {
                var o = this.options;
                if (window.wijmoApplyWijTouchUtilEvents) {
                    $ = window.wijmoApplyWijTouchUtilEvents($);
                }

                this.element.addClass(this.options.wijCSS.widget + " wijmo-wijpager " + this.options.wijCSS.helperClearFix);

                this._refresh();
                _super.prototype._create.call(this);
            };

            wijpager.prototype._destroy = function () {
                this.element.removeClass(this.options.wijCSS.widget + " wijmo-wijpager " + this.options.wijCSS.helperClearFix);
                this.$ul.remove();
            };

            wijpager.prototype._setOption = function (key, value) {
                this._super(key, value);
                this._refresh();
            };

            wijpager.prototype._refresh = function () {
                this._validate();

                if (this.$ul) {
                    this.$ul.remove();
                }

                this.element.append(this.$ul = $("<ul class=\"ui-list " + this.options.wijCSS.cornerAll + " " + this.options.wijCSS.content + " " + this.options.wijCSS.helperClearFix + "\" role=\"tablist\"></ul>"));

                switch ((this.options.mode || "").toLowerCase()) {
                    case "nextprevious":
                        this._createNextPrev(false);
                        break;

                    case "nextpreviousfirstlast":
                        this._createNextPrev(true);
                        break;

                    case "numeric":
                        this._createNumeric(false);
                        break;

                    case "numericfirstlast":
                        this._createNumeric(true);
                        break;
                }
            };

            wijpager.prototype._validate = function () {
                var o = this.options;

                if (isNaN(o.pageCount) || o.pageCount < 1) {
                    o.pageCount = 1;
                }

                if (isNaN(o.pageIndex) || o.pageIndex < 0) {
                    o.pageIndex = 0;
                } else {
                    if (o.pageIndex >= o.pageCount) {
                        o.pageIndex = o.pageCount - 1;
                    }
                }

                if (isNaN(o.pageButtonCount) || o.pageButtonCount < 1) {
                    o.pageButtonCount = 1;
                }
            };

            wijpager.prototype._createNextPrev = function (addFirstLast) {
                var o = this.options, firstPageClass = !!o.firstPageClass ? o.firstPageClass + " " + o.wijCSS.iconSeekFirst : "", previousPageClass = !!o.previousPageClass ? o.previousPageClass + " " + o.wijCSS.iconSeekPrev : "", nextPageClass = !!o.nextPageClass ? o.nextPageClass + " " + o.wijCSS.iconSeekNext : "", lastPageClass = !!o.lastPageClass ? o.lastPageClass + " " + o.wijCSS.iconSeekEnd : "";

                // first button
                if (addFirstLast && o.pageIndex) {
                    this.$ul.append(this._createPagerItem(false, o.firstPageText, 1, firstPageClass));
                }

                // previous button
                if (o.pageIndex) {
                    this.$ul.append(this._createPagerItem(false, o.previousPageText, o.pageIndex, previousPageClass));
                }

                // next button
                if (o.pageIndex + 1 < o.pageCount) {
                    this.$ul.append(this._createPagerItem(false, o.nextPageText, o.pageIndex + 2, nextPageClass));
                }

                // last button
                if (addFirstLast && (o.pageIndex + 1 < o.pageCount)) {
                    this.$ul.append(this._createPagerItem(false, o.lastPageText, o.pageCount, lastPageClass));
                }
            };

            wijpager.prototype._createNumeric = function (addFirstLast) {
                var o = this.options, currentPage = o.pageIndex + 1, startPageNumber = 1, endPageNumber = Math.min(o.pageCount, o.pageButtonCount), i, firstPageClass = !!o.firstPageClass ? o.firstPageClass + " " + o.wijCSS.iconSeekFirst : "", lastPageClass = !!o.lastPageClass ? o.lastPageClass + " " + o.wijCSS.iconSeekEnd : "";

                if (currentPage > endPageNumber) {
                    startPageNumber = (Math.floor(o.pageIndex / o.pageButtonCount)) * o.pageButtonCount + 1;

                    endPageNumber = startPageNumber + o.pageButtonCount - 1;
                    endPageNumber = Math.min(endPageNumber, o.pageCount);

                    if (endPageNumber - startPageNumber + 1 < o.pageButtonCount) {
                        startPageNumber = Math.max(1, endPageNumber - o.pageButtonCount + 1);
                    }
                }

                // first + "..." buttons
                if (startPageNumber !== 1) {
                    // first button
                    if (addFirstLast) {
                        this.$ul.append(this._createPagerItem(false, o.firstPageText, 1, firstPageClass));
                    }

                    // "..." button
                    this.$ul.append(this._createPagerItem(false, "...", startPageNumber - 1, ""));
                }

                for (i = startPageNumber; i <= endPageNumber; i++) {
                    this.$ul.append(this._createPagerItem(i === currentPage, i.toString(), i, ""));
                }

                // "..." + last buttons
                if (o.pageCount > endPageNumber) {
                    this.$ul.append(this._createPagerItem(false, "...", endPageNumber + 1, ""));

                    // last button
                    if (addFirstLast) {
                        this.$ul.append(this._createPagerItem(false, o.lastPageText, o.pageCount, lastPageClass));
                    }
                }
            };

            wijpager.prototype._createPagerItem = function (active, title, pageIndex, btnClass) {
                var btnContent, wijCSS = this.options.wijCSS, self = this, $li = $("<li />").addClass(wijCSS.pagerButton + " " + wijCSS.cornerAll).attr({ "role": "tab", "title": title });

                try  {
                    $li.attribute("aria-label", title); // throws "member not found" exception in IE10\11 if IE7 compatibility mode is used.
                } catch (ex) {
                }

                if (active) {
                    $li.addClass(wijCSS.stateActive).attribute("aria-selected", "true");
                } else {
                    $li.addClass(wijCSS.stateDefault).hover(function () {
                        if (!self._isDisabled()) {
                            $(this).addClass(wijCSS.stateHover);
                        }
                    }, function () {
                        if (!self._isDisabled()) {
                            $(this).removeClass(wijCSS.stateHover);
                        }
                    }).bind("click." + this.widgetName, { newPageIndex: pageIndex - 1 }, $.proxy(this._onClick, this)); // pageIndex is 1-based.
                }

                if (active) {
                    btnContent = $("<span />");
                } else {
                    btnContent = btnClass ? $("<span />").addClass(wijCSS.icon + " " + btnClass) : $("<a/>").attr("href", "#");
                }

                btnContent.text(title);

                $li.append(btnContent);

                return $li;
            };

            wijpager.prototype._onClick = function (arg) {
                if (this._isDisabled()) {
                    return false;
                }

                var pagingArgs = { newPageIndex: arg.data.newPageIndex, handled: false };

                if (this._trigger("pageIndexChanging", null, pagingArgs) !== false) {
                    if (this.options.pageIndex !== pagingArgs.newPageIndex) {
                        this.options.pageIndex = pagingArgs.newPageIndex;
                        if (!pagingArgs.handled) {
                            this._refresh();
                        }

                        var pagedArgs = { newPageIndex: pagingArgs.newPageIndex };
                        this._trigger("pageIndexChanged", null, pagedArgs);
                    }
                }

                return false;
            };
            return wijpager;
        })(wijmo.wijmoWidget);
        pager.wijpager = wijpager;

        wijpager.prototype.widgetEventPrefix = "wijpager";

        var wijpager_options = (function () {
            function wijpager_options() {
                /** @ignore */
                this.wijCSS = {
                    pagerButton: "wijmo-wijpager-button"
                };
                /** @ignore */
                this.wijMobileCSS = {
                    header: "ui-header ui-bar-a",
                    content: "ui-body-b",
                    stateDefault: "ui-btn ui-btn-b",
                    stateHover: "ui-btn-down-b",
                    stateActive: "ui-btn-down-c"
                };
                /**
                * An option that indicates the class of the first-page button. You can set this option with any of the jQuery UI CSS Framework icons.
                * @default "ui-icon-seek-first"
                * @example
                * // Here's the general way you'll set the option:
                * $("#element").wijpager({
                *    firstPageClass: "ui-icon-seek-first"
                * });
                */
                this.firstPageClass = $.wijmo.widget.prototype.options.wijCSS.iconSeekFirst;
                /**
                * An option that indicates the text to display for the first-page button. The text will display like a tooltip when a user hovers over the first-page button.
                * @example
                * // Here's the general way you'll set the option:
                * $("#element").wijpager({
                *    firstPageText: "Go To First"
                * });
                */
                this.firstPageText = "First";
                /**
                * An option that indicates the class of the last-page button. You can set this option with any of the jQuery UI CSS Framework icons.
                * @default "ui-icon-seek-end"
                * @example
                * // Here's the general way you'll set the option:
                * $("#element").wijpager({
                *    lastPageClass: "ui-icon-seek-end"
                * });
                */
                this.lastPageClass = $.wijmo.widget.prototype.options.wijCSS.iconSeekEnd;
                /**
                * An option that indicates the text to display for the last-page button. The text will display like a tooltip when a user hovers over the last-page button.
                * @example
                * // Here's the general way you'll set the option:
                * $("#element").wijpager({
                *   lastPageText: "Go To Last"
                * });
                */
                this.lastPageText = "Last";
                /**
                * This option determines the pager mode. The possible values for this option are: "nextPrevious", "nextPreviousFirstLast", "numeric", "numericFirstLast".
                * @remarks
                * Possible values are: "nextPrevious", "nextPreviousFirstLast", "numeric", "numericFirstLast".
                * "nextPrevious": a set of pagination controls consisting of Previous and Next buttons.
                * "nextPreviousFirstLast": a set of pagination controls consisting of Previous, Next, First, and Last buttons.
                * "numeric": a set of pagination controls consisting of numbered link buttons to access pages directly.
                * "numericFirstLast": a set of pagination controls consisting of numbered and First and Last link buttons.
                * @example
                * // Here's the general way you'll set the option:
                * $("#element").wijpager({
                *    mode: "nextPrevious"
                * });
                */
                this.mode = "numeric";
                /**
                * An option that indicates the class of the next-page button. You can set this option with any of the jQuery UI CSS Framework Icons.
                * @default "ui-icon-seek-next"
                * @example
                * // Here's the general way you'll set the option:
                * $("#element").wijpager({
                *    nextPageClass: "ui-icon-seek-next"
                * });
                */
                this.nextPageClass = $.wijmo.widget.prototype.options.wijCSS.iconSeekNext;
                /**
                * An option that indicates the text to display for the next-page button. The text appears like a tooltip when a user hovers over the next-page button.
                * @example
                * // Here's the general way you'll set the option:
                * $("#element").wijpager({
                *    nextPageText: "Go To Next"
                * });
                */
                this.nextPageText = "Next";
                /**
                * An option that indicates the number of page buttons to display in the pager. You can customize how many page buttons are available for your users to use to page through content.
                * You can use this option in conjunction with the pageCount to customize the pager display.
                * @example
                * // Here's the general way you'll set the option:
                * $("#element").wijpager({
                *    pageButtonCount: 15
                * });
                */
                this.pageButtonCount = 10;
                /**
                * An option that indicates the class of the previous-page button. You can set this option with any of the jQuery UI CSS Framework Icons.
                * @type {string}
                * @default "ui-icon-seek-prev"
                * @example
                * // Here's the general way you'll set the option:
                * $("#element").wijpager({
                *    previousPageClass: "ui-icon-seek-prev"
                * });
                */
                this.previousPageClass = $.wijmo.widget.prototype.options.wijCSS.iconSeekPrev;
                /**
                * An option that indicates the text to display for the previous-page button. The text appears like a tooltip when a user hovers over the previous-page button.
                * @example
                * // Here's the general way you'll set the option:
                * $("#element").wijpager({
                *    previousPageText: "Go To Previous"
                * });
                */
                this.previousPageText = "Previous";
                /**
                * An option that indicates the total number of pages. This option allows you to customize the total number of pages that your users will be able to page through. You can use this option in conjunction with the pageButtonCount to customize the pager display.
                * @example
                * // Here's the general way you'll set the option:
                * $("#element").wijpager({
                *    pageCount: 10
                * });
                */
                this.pageCount = 1;
                /**
                * An option that indicates the zero-based index of the current page. By default, your pager will display with the first pager button highlighted since its index is 0.
                * @example
                * // Here's the general way you'll set the option. This will allow your pager widget to display with the 3rd page button highlighted:
                * $("#element").wijpager({
                *    pageIndex: 2
                * });
                */
                this.pageIndex = 0;
                /**
                * The pageIndexChanging event handler is a function called when page index is changing. This item is cancellable if you return false.
                * @event
                * @param {object} e The jQuery.Event object.
                * @param {wijmo.grid.IPageIndexChangingEventArgs} args The data associated with this event.
                * @example
                * // Supply a callback function to handle the event:
                * $("#element").wijpager({
                *    pageIndexChanging: function (e, args) {
                *       // Handle the event here.
                *    }
                * });
                
                * // Bind to the event by type:
                * $("#element").bind("wijpagerpageindexchanging", function (e, args) {
                *    // Handle the event here.
                * });
                *
                * // You can cancel this event be returning false:
                * $("#element").wijpager({
                *    pageIndexChanging: function(e, args) {
                *       return false;
                *    }
                * });
                */
                this.pageIndexChanging = null;
                /**
                * The pageIndexChanged event handler is a function called when the page index is changed.
                * @event
                * @param {object} e The jQuery.Event object.
                * @param {wijmo.grid.IPageIndexChangedEventArgs} args The data associated with this event.
                * @example
                * // Supply a callback function to handle the event:
                * $("#element").wijpager({
                *    pageIndexChanged: function (e, args) {
                *       // Handle the event here.
                *    }
                * });
                
                * // Bind to the event by type:
                * $("#element").bind("wijpagerpageindexchanged", function (e, args) {
                *    // Handle the event here.
                * });
                *
                * // You can also use this event to get the selected page by using the args.newPageIndex parameter:
                * $("#element").wijpager({
                *    pageIndexChanged: function(e, args) {
                *       var selectedPageIndex = args.newPageIndex;
                *    }
                * });
                */
                this.pageIndexChanged = null;
            }
            return wijpager_options;
        })();
        ;

        wijpager.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijpager_options());

        $.wijmo.registerWidget("wijpager", wijpager.prototype);

        

        

        

        
        ;
    })(wijmo.pager || (wijmo.pager = {}));
    var pager = wijmo.pager;
})(wijmo || (wijmo = {}));

;
/// <reference path="../External/declarations/jquery.d.ts"/>
/// <reference path="../wijutil/jquery.wijmo.wijutil.ts"/>
/// <reference path="../Base/wijmo.d.ts"/>
var wijmo;
(function (wijmo) {
    /*globals jQuery*/
    /*
    * Depends:
    *  jquery.js
    *  jquery-ui.js
    *
    */
    (function (checkbox) {
        var $ = jQuery, wijdatasource, wijarrayreader, wijhttpproxy;

        wijdatasource = function (options) {
            var self = this;

            /// <summary>
            /// The data to process using the wijdatasource class.
            /// Default: {}.
            /// Type: Object.
            /// </summary>
            self.data = {};

            /// <summary>
            /// The reader to use with wijdatasource. The wijdatasource class will call the
            /// read method of reader to read from rawdata with an array of fields provided.
            /// The field contains a name, mapping and defaultValue properties which define
            /// the rule of the mapping.
            /// If no reader is configured with wijdatasource it will directly return the
            /// raw data.
            /// Default: null.
            /// Type: Object.
            /// </summary>
            self.reader = null;

            /// <summary>
            /// The proxy to use with wijdatasource. The wijdatasource class will call
            /// the proxy object's request method.
            /// In the proxy object, you can send a request to a remote server to
            /// obtain data with the ajaxs options object provided.
            /// Then you can use the wijdatasource reader to process the raw data in the call.
            /// Default: null.
            /// Type: Object.
            /// </summary>
            self.proxy = null;

            /// <summary>
            /// The processed items from the raw data.  This can be obtained after
            /// datasource is loaded.
            /// Default: [].
            /// Type: Array.
            /// </summary>
            self.items = [];

            /// <summary>
            /// Function called before loading process starts
            /// Default: null.
            /// Type: Function.
            /// Code example:
            /// var datasource = new wijdatasource({loading: function(e, data) { }})
            /// </summary>
            /// <param name="datasource" type="wijdatasource">
            /// wijdatasource object that raises this event.
            /// </param>
            /// <param name="data" type="Object">
            /// data passed in by load method.
            /// </param>
            self.loading = null;

            /// <summary>
            /// Function called after loading.
            /// Default: null.
            /// Type: Function.
            /// Code example:
            /// var datasource = new wijdatasource({loaded: function(e, data) { }})
            /// </summary>
            /// <param name="datasource" type="wijdatasource">
            /// wijdatasource object that raises this event.
            /// </param>
            /// <param name="data" type="Object">
            /// data passed in by load method.
            /// </param>
            self.loaded = null;
            self._constructor(options);
        };
        window.wijdatasource = wijdatasource;

        $.extend(wijdatasource.prototype, {
            _constructor: function (options) {
                $.extend(this, options);
            },
            load: function (data, forceLocalReload) {
                /// <summary>
                /// Triggers data loading process of wijdatasource.
                /// </summary>
                /// <param name="data" type="Object">
                /// The data to pass to the loading and loaded event handler.
                /// </param>
                /// <param name="forceLocalReload" type="boolean">
                /// Normally local data is only load for one time,
                /// if needs to reload the data, try to set forceLocalReload to true.
                /// </param>
                var self = this, p = self.proxy;

                //var d = self.data;
                // fire loading event.
                if ($.isFunction(self.loading)) {
                    //self.loading(self, data);
                    //if return false in loading event, cancel this request.
                    if (self.loading(self, data) === false) {
                        return;
                    }
                }

                // if datasource has an proxy object, it will use the request method of
                // proxy to retrive the raw data.
                if (p) {
                    // pass callback function to request method so that proxy could
                    // call the function when request is finished.
                    p.request(self, self.loaded, data);
                } else {
                    // local data is loaded only once, if force loading is needed
                    // forceLocalReload should be true.
                    if (self.items.length === 0 || forceLocalReload) {
                        // no proxy, read raw data
                        this.read();
                    }

                    // callback function is called
                    if ($.isFunction(self.loaded)) {
                        self.loaded(self, data);
                    }
                }
            },
            read: function () {
                /// <summary>
                /// Triggers data reading process of wijdatasource
                /// by using a DataReader if presented.
                /// </summary>
                var self = this, d = self.data;

                // reads using a reader object
                if (d && self.reader) {
                    self.reader.read(self);
                } else {
                    // returns raw data if no reader is configured with datasource.
                    self.items = self.data;
                    //removed by Jeffrey for removing unnecessary return
                    //return self.data;
                    //end by Jeffrey
                }
            }
        });

        /// <summary>
        /// wijdatasource ArrayReader reads from a array and processes items.
        /// </summary>
        wijarrayreader = function (fields) {
            // this.fields to store the fields info
            // Add for parse objectValue options for jUICE. D.H
            if ($.isFunction(window["wijmoASPNetParseOptions"])) {
                wijmoASPNetParseOptions(fields);
            }

            if ($.isArray(fields)) {
                this.fields = fields;
            }
        };
        window.wijarrayreader = wijarrayreader;

        $.extend(wijarrayreader.prototype, {
            read: function (datasource) {
                /// <summary>
                /// Starts reading data.
                /// </summary>
                /// <param name="datasource" type="wijdatasource">
                /// The wijdatasource using this DataReader.
                /// </param>
                // convert the raw data of wijdatasource
                if ($.isArray(datasource.data)) {
                    datasource.items = this._map(datasource.data);
                } else {
                    datasource.items = [];
                }
            },
            _map: function (data) {
                var self = this, arr = [];
                if (self.fields === undefined || self.fields.length === 0) {
                    $.extend(true, arr, data);
                    return arr;
                } else {
                    $.each(data, function (index, value) {
                        var i = {};
                        $.each(self.fields, function (index, field) {
                            // mapping property is a function,
                            // the return value will be used as value.
                            //handle the juice
                            if (field.mapping && typeof field.mapping && window[field.mapping]) {
                                field.mapping = window[field.mapping];
                            }

                            if ($.isFunction(field.mapping)) {
                                i[field.name] = field.mapping(value);
                                return true;
                            }

                            // use string field mapping or number index mapping.
                            var mapping = field.mapping !== undefined ? field.mapping : field.name, v = value[mapping];
                            if (v === undefined) {
                                if (field.defaultValue !== undefined) {
                                    v = field.defaultValue;
                                } else {
                                    v = value;
                                }
                            }
                            i[field.name] = v;
                        });
                        arr.push(i);
                    });
                }
                return arr;
            }
        });

        /// <summary>
        /// wijdatasource HttpProxy fetches data by using Ajax request.
        /// </summary>
        wijhttpproxy = function (options) {
            this.options = options;

            // Add for parse objectValue options for jUICE. D.H
            if ($.isFunction(window["wijmoASPNetParseOptions"])) {
                wijmoASPNetParseOptions(options);
            }
        };
        window.wijhttpproxy = wijhttpproxy;

        $.extend(wijhttpproxy.prototype, {
            request: function (datasource, callBack, userData) {
                /// <summary>
                /// Starts requesting data.
                /// </summary>
                /// <param name="datasource" type="wijdatasource">
                /// The wijdatasource using this DataReader.
                /// </param>
                /// <param name="callback" type="Function">
                /// The function to call after requesting data successfully.
                /// </param>
                var self = this, o, oldSuccess;
                o = $.extend({}, this.options);
                oldSuccess = o.success;

                o.success = function (data) {
                    if ($.isFunction(oldSuccess)) {
                        oldSuccess(data);
                    }
                    self._complete(data, datasource, callBack, o, userData);
                };
                $.ajax(o);
            },
            _complete: function (data, datasource, callback, options, userData) {
                // set raw data
                datasource.data = options.key !== undefined ? data[options.key] : data;

                // read raw data using a data reader in datasource
                datasource.read();

                // fire loaded callback
                if ($.isFunction(callback)) {
                    callback(datasource, userData);
                }
            }
        });
    })(wijmo.checkbox || (wijmo.checkbox = {}));
    var checkbox = wijmo.checkbox;
})(wijmo || (wijmo = {}));

;
/// <reference path="../Base/jquery.wijmo.widget.ts" />
/// <reference path="../wijutil/jquery.wijmo.wijutil.ts" />
/// <reference path="../wijlist/jquery.wijmo.wijlist.ts" />
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*globals jQuery,window,document*/
    /*
    * Depends:
    *     jquery.ui.core.js
    *     jquery.ui.widget.js
    *     jquery.wijmo.wijtooltip.js
    */
    (function (combobox) {
        var $ = jQuery, widgetName = "wijcombobox";

        /** @widget */
        var wijcombobox = (function (_super) {
            __extends(wijcombobox, _super);
            function wijcombobox() {
                _super.apply(this, arguments);
            }
            wijcombobox.prototype._create = function () {
                var t = this, focusElement;

                // inits selected items
                t.selectedItem = null;
                t.selectedItems = [];

                // enable touch support:
                if (window.wijmoApplyWijTouchUtilEvents) {
                    $ = window.wijmoApplyWijTouchUtilEvents($);
                }

                try  {
                    focusElement = document.activeElement;
                } catch (e) {
                }

                //update for visibility change
                if (t.element.is(":hidden") && t.element.wijAddVisibilityObserver) {
                    t.element.wijAddVisibilityObserver(function () {
                        t.repaint();
                        if (t.element.wijRemoveVisibilityObserver) {
                            t.element.wijRemoveVisibilityObserver();
                        }
                    }, "wijcombobox");
                }

                // inits wijcombobox
                t._initInnerData();
                t._createDOMElements();
                t._bindInputEvents();
                t._initDropDownList();
                t.repaint();
                t._checkSelectIndex();
                t.options.text = t._input.val();

                if (t._usingRemoteData() && t.options.data) {
                    t.originalDataSourceLoaded = t.options.data.loaded;
                }

                //If combo is in an invisible iframe, exception will throw.
                //add this in try block to prevent this exception.
                //focusElement = document.activeElement;
                if (focusElement === t._input[0] && t.options.isEditable) {
                    $(function () {
                        t._input.focus();
                    });
                }
                _super.prototype._create.call(this);
            };

            wijcombobox.prototype._initInnerData = function () {
                var self = this, o = self.options, isBind;
                if (o.dataSource !== null) {
                    isBind = self._isBind();
                    if (isBind) {
                        self.innerData = self._getMappingItems();
                    } else {
                        self.innerData = o.data;
                    }
                } else {
                    self.innerData = o.data;
                }

                self.listHasCreated = false;
            };

            wijcombobox.prototype._checkSelectIndex = function () {
                var self = this, index, o = self.options, data = self.innerData;

                if (o.selectedIndex === -1 && o.selectedValue != null) {
                    $.each(data, function (i, item) {
                        if (data[i].value === o.selectedValue) {
                            o.selectedIndex = i;
                            if (o.selectionMode === "multiple") {
                                o.selectedIndex = [o.selectedIndex];
                            }
                            return false;
                        }
                    });
                }
                index = o.selectedIndex;
                if (!self._usingRemoteData() && (index >= 0 || $.isArray(index))) {
                    self.search(null, "checkindex");
                }

                // if the selecteIndex is -1 and selectedValue is null, the text
                // option will give to combobox
                if (o.selectedIndex === -1 && o.text) {
                    if (!o.forceSelectionText || (o.forceSelectionText && self._checkTextInItems(o.text) !== -1)) {
                        self._input.val(o.text);
                        o.selectedIndex = self._checkTextInItems(o.text);
                        if (o.selectionMode === "multiple") {
                            o.selectedIndex = [o.selectedIndex];
                        }
                        if (o.selectedIndex > -1) {
                            self._checkSelectIndex();
                        }
                    }
                }
            };

            /** Repaints wijcombobox. Returns true if it succeeds;
            *   otherwise, returns false.
            * @returns {boolean} true if it succeeds; otherwise, returns false.
            */
            wijcombobox.prototype.repaint = function () {
                var o = this.options, self = this;
                if (self.element.is(":visible") || self._comboDiv || (self._select !== undefined && self._input.is(":visible"))) {
                    self._showTrigger();
                    self._handleAdjustWidthOptions();
                    if (self._isDisabled()) {
                        self._innerDisable();
                    }
                    return true;
                }
                return false;
            };

            wijcombobox.prototype._bindInputEvents = function () {
                var self = this, wijCSS = this.options.wijCSS, code, keyCode, inputText, input = self._input, o = self.options;

                // self.element is an html input element.
                input.bind("keydown.wijcombobox", function (event) {
                    if (self._isDisabled()) {
                        return;
                    }
                    code = event.keyCode;

                    //keyCode = $.ui.keyCode;
                    keyCode = wijmo.getKeyCodeEnum();
                    switch (code) {
                        case keyCode.UP:
                            self._move("previous", event);

                            // prevent moving cursor to beginning of
                            // text field in some browsers
                            event.preventDefault();
                            break;
                        case keyCode.DOWN:
                            self._move("next", event);

                            // prevent moving cursor to end of text field in some browsers
                            event.preventDefault();
                            break;
                        case keyCode.ENTER:
                            // when menu is open or has focus
                            if (self.menu.active) {
                                event.preventDefault();

                                //update for issue 24045
                                if (o.selectionMode === "multiple" && self.menu && self.menu.items && self.menu.items.length === 1) {
                                    $.each(self.selectedItems, function (index, i) {
                                        if (i !== self.menu.items[0]) {
                                            i.selected = false;
                                        }
                                    });
                                }

                                //end
                                self.menu.select(event);
                            }
                            event.preventDefault(); //update for issue 24134 at 2012/7/19
                            break;

                        case keyCode.TAB:
                            input.trigger("wijcomboblur");
                            if (!self.menu.active || (o.selectionMode === "multiple" && keyCode.TAB === code)) {
                                return;
                            }
                            self.menu.select(event);

                            // remove selection from input.
                            var end = input.val().length;
                            self._selectText(end, end, input);

                            break;
                        case keyCode.ESCAPE:
                            self.close(event, undefined);
                            break;
                        case keyCode.LEFT:
                        case keyCode.RIGHT:
                        case keyCode.SHIFT:
                        case 16:
                        case 17:
                        case keyCode.CTRL:
                        case keyCode.HOME:
                        case keyCode.END:
                        case keyCode.PAGE_UP:
                        case keyCode.PAGE_DOWN:
                            break;
                        case keyCode.DELETE:
                            if (!inputText) {
                                inputText = input.val();
                            }
                            break;
                        case 18:
                            input.trigger("wijcomboblur");
                            break;
                        default:
                            // keypress is triggered before the input value is changed
                            //IE and Chrome the keycode is 229 in IME mode
                            //In Firefox it says 'Characters entered through an IME do not register through keyCode or charCode.' in documetation.  So the keycode is 0 and key of event is 'Unidentified' in IME mode.
                            //Please refer https://developer.mozilla.org/en-US/docs/Web/API/event.keyCode
                            if (code === 229 || ($.browser.mozilla && event.key === "Unidentified" && code === 0)) {
                                return;
                            }

                            self._processingSearch(input, code, event);
                            break;
                    }
                }).bind("keyup.wijcombobox", function (event) {
                    if (self._isDisabled()) {
                        return;
                    }
                    code = event.keyCode;
                    keyCode = wijmo.getKeyCodeEnum();
                    switch (code) {
                        case keyCode.DELETE:
                            if (inputText !== input.val()) {
                                self._processingSearch(input, code, event);
                            }
                            inputText = undefined;
                            break;
                    }
                }).bind("wijcomboblur.wijcombobox", function (event) {
                    window.clearTimeout(self.searching);
                    self._addInputFocus(false, wijCSS.stateFocus);

                    // TODO try to implement this without a timeout,
                    // see clearTimeout in search()
                    self.closing = window.setTimeout(function () {
                        self.close(event, true);
                    }, 150);
                }).bind("focus.wijcombobox", function () {
                    self._addInputFocus(true, wijCSS.stateFocus);
                }).bind("blur.wijcombobox", function () {
                    if (!self.menu.element.is(":visible")) {
                        input.trigger("wijcomboblur");
                    }

                    // 1)if inputed char include in dropdown items,
                    // the dropdown will open
                    // if the inputed char don't include in dropdown items,
                    // the dropdown won't open, it's for issue 42012
                    // 2)Thinking of "forceSelectionText" option, so move the "textChange"
                    // event to _change method
                    // self._setInputText(input.val());
                    if (!self._inputBlurCausedByListItemClick) {
                        self._change();
                    }
                }).bind("compositionend.wijcombobox", function (event) {
                    self._processingSearch(input, code, event);
                });

                //fixed the issue 40441
                if ($.browser.msie && parseInt($.browser.version) > 9) {
                    input.bind("mouseup.wijcombobox", function (event) {
                        // fixed an issue of IE10(browser mode IE9), when runs in this mode,
                        // the input element will show clear button at the right side of the input element.
                        // click the button, the widget's text value will not cleared.
                        if (input.val() === '') {
                            return;
                        }

                        // Wait for it....
                        setTimeout(function () {
                            if (input.val() === '') {
                                self.menu.deactivate();
                            }
                        }, 5);
                    });
                }
            };

            wijcombobox.prototype._processingSearch = function (input, code, event) {
                var self = this, o = self.options;

                window.clearTimeout(self.searching);
                if (o.isEditable === false) {
                    if (self._cacheKey === undefined) {
                        self._cacheKey = "";
                    }
                    self._cacheKey += String.fromCharCode(code);
                }
                self.searching = window.setTimeout(function () {
                    var term;
                    if (o.isEditable === false) {
                        term = self._cacheKey;
                        self._cacheKey = undefined;
                    } else {
                        term = input.val();
                    }
                    self.search(term, event);
                }, o.delay);
            };

            wijcombobox.prototype._addInputFocus = function (add, css) {
                var self = this, wrap, key, arrow;

                wrap = self._input.parent();
                key = add ? "addClass" : "removeClass";
                arrow = self._triggerArrow;
                wrap[key](css);
                if (arrow !== undefined) {
                    arrow[key](css);
                }
            };

            wijcombobox.prototype._renderColumnsHeader = function (header) {
                var self = this, ul = $("<ul class='wijmo-wijcombobox-rowheader'></ul>");
                $.each(this.options.columns, function (index, column) {
                    var li = $("<li class='wijmo-wijcombobox-cell " + self.options.wijCSS.header + "'></li>");
                    li.html(column.name);
                    if (column.width !== undefined) {
                        li.width(column.width);
                    }
                    li.appendTo(ul);
                });
                header.append(ul);
            };

            wijcombobox.prototype._hasSameValueText = function (item1, item2) {
                return item1.label === item2.label && item1.value === item2.value;
            };

            wijcombobox.prototype._initDropDownList = function () {
                var self = this, doc, menuElement, o = self.options, header, listOptions, wijCSS = this.options.wijCSS, zIndex = parseInt(self._input.css("zIndex"), 10), dropDownContainer;

                doc = self.element[0].ownerDocument;
                if (isNaN(zIndex)) {
                    zIndex = 0;
                }
                if (!self._comboDiv) {
                    menuElement = $("<div class='" + wijCSS.comboboxListCss + "'></div>");
                } else {
                    menuElement = self._oriList;
                }
                if (o.columns.length > 0) {
                    menuElement.addClass("wijmo-wijcombobox-multicolumn");
                    header = $("<div class='wijmo-wijsuperpanel-header " + wijCSS.stateDefault + "'></div>");
                    self._renderColumnsHeader(header);
                    menuElement.append(header);
                }

                listOptions = {
                    keepHightlightOnMouseLeave: true,
                    selectionMode: o.selectionMode,
                    addHoverItemClass: o.columns.length === 0,
                    focus: function (e, item) {
                        var i = item;
                        if (o.selectOnItemFocus) {
                            self.menu.select(null, {
                                notCloseAfterSelected: true
                            });
                        }
                        if (o.columns.length > 0) {
                            if (i.element) {
                                i.element.prev().addClass("wijmo-wijcombobox-active-prev");
                                i.element.find(".wijmo-wijcombobox-row>.wijmo-wijcombobox-cell").addClass(wijCSS.stateHover);
                            }
                        }
                    },
                    selected: function (event, ui) {
                        window.clearTimeout(self.closing);
                        var mode = o.selectionMode, item, newIndex, cancelSelect = false, oldText, oldIndex, oldItem;

                        item = ui.item;

                        newIndex = $.inArray(item, self.items);
                        if (newIndex < 0) {
                            return;
                        }

                        if (self._trigger("select", event, item)) {
                            if (mode === "single") {
                                // local data select
                                if (!self._usingRemoteData()) {
                                    if (newIndex !== o.selectedIndex) {
                                        oldIndex = o.selectedIndex;
                                        oldItem = self.selectedItem;
                                        cancelSelect = self._triggerSelectedIndexChanging(oldItem, item, oldIndex, newIndex);
                                        if (cancelSelect) {
                                            return;
                                        }

                                        self._setInputText(item.label);

                                        if (oldItem) {
                                            oldItem.selected = false;
                                        }
                                        self.selectedItem = item;

                                        o.selectedIndex = newIndex;
                                        o.selectedValue = self.selectedItem.value;

                                        o.inputTextInDropDownList = true;

                                        //o.text = self._input.val();for #33666 issue
                                        // fixed the issue 41831
                                        if (oldItem && oldItem.element) {
                                            oldItem.element.removeClass("wijmo-wijcombobox-selecteditem");
                                        }

                                        self._triggerChangeEvents(oldItem, oldIndex);
                                    } else {
                                        // for fixing bug 24133 at 2012/8/6
                                        if (self.selectedItem && self._input.val() !== self.selectedItem.label && (ui.data === undefined || !ui.data.notCloseAfterSelected)) {
                                            self._input.val(item.label);
                                        }
                                    }
                                } else {
                                    // If items have the same text and value,
                                    // they are considered to be same in remote mode.
                                    if (self.selectedItem === null || !self._hasSameValueText(item, self.selectedItem)) {
                                        oldItem = self.selectedItem;
                                        oldIndex = o.selectedIndex;
                                        cancelSelect = self._triggerSelectedIndexChanging(oldItem, item, oldIndex, ui.selectedIndex);
                                        if (cancelSelect) {
                                            return;
                                        }

                                        //self._input.val(item.label);
                                        self._setInputText(item.label);

                                        //o.text = self._input.val();for #33666 issue
                                        self.selectedItem = item;

                                        //update for 29162 issue.
                                        if (newIndex !== o.selectedIndex) {
                                            o.selectedIndex = newIndex;
                                            o.selectedValue = self.selectedItem.value;
                                        }

                                        //end
                                        o.inputTextInDropDownList = true;

                                        self._triggerChangeEvents(oldItem, oldIndex);
                                    }
                                }
                            } else {
                                if (!self._usingRemoteData()) {
                                    cancelSelect = self._triggerSelectedIndexChanging(null, item, oldIndex, ui.selectedIndex);
                                    if (cancelSelect) {
                                        return;
                                    }

                                    self.selectedItems = ui.selectedItems;
                                    self._selectedItemsToInputVal(self.selectedItems);
                                    o.inputTextInDropDownList = true;
                                    o.selectedIndex = ui.selectedIndex;

                                    self._triggerChangeEvents(null, null);
                                    ///TODO: show helper list
                                }
                            }
                        }
                        if ((ui.data === undefined || !ui.data.notCloseAfterSelected) && mode === "single") {
                            self.close(event);
                            self._input.focus();
                        }
                        self._inputBlurCausedByListItemClick = false;
                    },
                    blur: function (e, item) {
                        var d = item.element;
                        if (o.columns.length > 0 && d) {
                            d.find(".wijmo-wijcombobox-row>.wijmo-wijcombobox-cell").removeClass(wijCSS.stateHover);
                            d.prev().removeClass("wijmo-wijcombobox-active-prev");
                        }
                    },
                    mouseDown: function (event) {
                        self._inputBlurCausedByListItemClick = true;
                    },
                    itemRendering: function (event, data) {
                        var item = data, css = "";
                        if (item.isSeparator) {
                            css += " wijmo-wijcombobox-separator";
                        }
                        if (item.selected) {
                            css += " wijmo-wijcombobox-selecteditem";
                        }
                        if (css.length > 0) {
                            item.element.addClass(css);
                        }
                    },
                    itemRendered: function (event, data) {
                        var item = data, li, u;
                        if (self.menu._templates || item.cells == null) {
                            return;
                        }
                        li = item.element;
                        li.empty();
                        u = $("<ul class='wijmo-wijcombobox-row'></ul>");
                        $.each(item.cells, function (index, cell) {
                            var l = $("<li class='wijmo-wijcombobox-cell " + wijCSS.stateDefault + "'></li>");

                            //Fix a bug that columns.width doesn't work.
                            if (o.columns && o.columns.length > index) {
                                if (typeof o.columns[index].width !== "undefined") {
                                    l.width(o.columns[index].width);
                                }
                            }

                            //end comments.
                            l.append($.trim(cell) || "&nbsp;");
                            l.attr("title", cell);
                            u.append(l);
                        });
                        li.append(u);
                    },
                    listRendered: function (event, data) {
                        var selectedItem = self.menu.selectedItem, selectedItems = self.menu.selectedItems, selecedIndex, items;
                        if (o.selectionMode === "single" && selectedItem) {
                            selecedIndex = $.inArray(selectedItem, self.items);
                            if (selecedIndex < 0) {
                                return;
                            }
                            self.selectedItem = self.items[selecedIndex];
                            self._setInputText(self.selectedItem.label, true);
                            if (selecedIndex >= -1) {
                                o.selectedIndex = selecedIndex;
                            }
                        } else if (selectedItems && selectedItems.length > 0) {
                            selecedIndex = [];
                            items = [];
                            $.each(selectedItems, function (i, item) {
                                var index = $.inArray(item, self.items);
                                if (index < 0) {
                                    return true;
                                }
                                selecedIndex.push(index);
                                items.push(self.items[index]);
                            });
                            self._selectedItemsToInputVal(items);
                            if (selecedIndex.length >= 0) {
                                o.selectedIndex = selecedIndex;
                            }
                        }
                    },
                    superPanelOptions: {
                        resized: function (e) {
                            var m = self.menu, ele = m.element;
                            o.dropdownWidth = ele.outerWidth();
                            o.dropdownHeight = ele.outerHeight();
                            self._positionList();
                            self.menu.refreshSuperPanel();
                        }
                    }
                };
                listOptions = $.extend(true, listOptions, o.listOptions);

                dropDownContainer = o.ensureDropDownOnBody ? $("body") : self._comboElement;

                self.menu = menuElement.appendTo(dropDownContainer, doc).wijlist(listOptions).css({
                    zIndex: zIndex + 1,
                    top: 0,
                    left: 0
                }).hide().data("wijmo-wijlist");
                self._createDropDownList();
                self._menuUL = self.menu.ul;
            };

            wijcombobox.prototype._setInputText = function (text, notfiredTextChanged) {
                var self = this, oldText = self.options.text;

                self._input.val(text);
                self.options.text = text;
                if (oldText !== text && !notfiredTextChanged) {
                    self._trigger("textChanged", null, {
                        oldText: oldText,
                        newText: text
                    });
                }
            };

            wijcombobox.prototype._triggerChangeEvents = function (oldSelectedItem, oldSelectedIndex) {
                var o = this.options, mode = o.selectionMode, selectedItem = this.selectedItem, selectedIndex = this.options.selectedIndex, changedData;

                this._triggerSelectElementChange();

                changedData = {
                    oldItem: oldSelectedItem,
                    selectedItem: this.selectedItem,
                    newIndex: selectedIndex,
                    oldIndex: oldSelectedIndex
                };
                if (mode === "multiple") {
                    changedData = $.extend(changedData, { selectedItems: this.selectedItems });
                }

                this._trigger("changed", null, changedData);

                if (selectedIndex != oldSelectedIndex) {
                    this._triggerSelectedIndexChanged(oldSelectedItem, selectedItem, oldSelectedIndex, selectedIndex);
                }
            };

            wijcombobox.prototype._triggerSelectElementChange = function () {
                var o = this.options;

                // fire select change event
                if (this._select !== undefined) {
                    if ($.isArray(o.selectedIndex) && o.selectedIndex.length > 0) {
                        this._select[0].selectedIndex = o.selectedIndex[0];
                    } else {
                        this._select[0].selectedIndex = o.selectedIndex;
                    }
                    this._select.trigger("change");
                }
            };

            wijcombobox.prototype._triggerSelectedIndexChanged = function (oldItem, newItem, oldIndex, newIndex) {
                var o = this.options, curSelectedIdx;

                if (o.selectionMode === "single") {
                    this._trigger("selectedIndexChanged", null, {
                        oldItem: oldItem,
                        selectedItem: newItem,
                        newIndex: newIndex,
                        oldIndex: oldIndex
                    });
                } else {
                    curSelectedIdx = $.inArray(newItem, this.items);
                    this._trigger("selectedIndexChanged", null, {
                        selectedItem: newItem,
                        selectedIndex: curSelectedIdx,
                        selectedItems: this.selectedItems
                    });
                }
            };

            wijcombobox.prototype._triggerSelectedIndexChanging = function (oldItem, newItem, oldIndex, newIndex) {
                var o = this.options, curSelectedIdx, args, isSelect = true;

                if (o.selectionMode === "single") {
                    args = {
                        oldItem: oldItem,
                        selectedItem: newItem,
                        newIndex: newIndex,
                        oldIndex: oldIndex
                    };
                    isSelect = this._trigger("selectedIndexChanging", null, args);
                } else {
                    curSelectedIdx = $.inArray(newItem, this.items);
                    args = {
                        selectedItem: newItem,
                        selectedIndex: curSelectedIdx,
                        selectedItems: this.selectedItems
                    };
                    isSelect = this._trigger("selectedIndexChanging", null, args);
                }
                if (!isSelect) {
                    newItem.selected = false;
                    if (newItem.element) {
                        newItem.element.removeClass("wijmo-wijcombobox-selecteditem");
                    }
                }
                return !isSelect;
            };

            wijcombobox.prototype._createDropDownList = function (datasrc) {
                var self = this, items, o = self.options, datasource = datasrc;

                if (!datasource) {
                    datasource = self.innerData;
                }

                if (datasource === null) {
                    items = null;
                } else {
                    items = $.isArray(datasource) ? datasource : datasource.items;
                }
                if (self._comboDiv) {
                    //update for case 20689 at 2012/4/11
                    if (!self.listHasCreated && items && items.length > 0) {
                        self.menu.setTemplateItems(o.data);
                        if ($.isArray(self.innerData)) {
                            self.innerData = self.menu.items;
                        } else {
                            self.innerData.items = self.menu.items;
                        }
                        self.items = self.menu.items;
                        self.menu.renderList();
                        self.listHasCreated = true;
                    }
                } else {
                    if (!self.listHasCreated && items && items.length > 0) {
                        self.menu.setItems(items);
                        if ($.isArray(self.innerData)) {
                            self.innerData = self.menu.items;
                        } else {
                            self.innerData.items = self.menu.items;
                        }
                        self.items = self.menu.items;
                        self.menu.renderList();
                        self.listHasCreated = true;
                    }
                }
                self._handleAdjustWidthOptions();
            };

            wijcombobox.prototype._getSelectedItemsText = function (items) {
                var s = "", self = this, sep = self.options.multipleSelectionSeparator;
                self.selectedItems = items;

                $.each(items, function (index, item) {
                    //update for bug 24045
                    if (item) {
                        s += item.label + sep;
                    }
                });
                if (s.length > 0) {
                    s = s.substr(0, s.lastIndexOf(sep));
                }

                return s;
            };

            wijcombobox.prototype._selectedItemsToInputVal = function (items) {
                var self = this;

                //self._input.val(self._getSelectedItemsText(items));
                self._setInputText(self._getSelectedItemsText(items));
                //self.options.text = self._input.val();for #33666 issue
            };

            wijcombobox.prototype._createDOMElements = function () {
                var self = this, comboElement, wijCSS = this.options.wijCSS, ele, input, wrapperElement;

                wrapperElement = $("<div class='" + wijCSS.comboboxWrapperCss + " " + wijCSS.stateDefault + " " + wijCSS.cornerAll + "'></div>");

                // check if element is a select element
                ele = self.element;

                // create from a select element
                if (ele.is("select")) {
                    comboElement = $("<div role='combobox' class='" + wijCSS.comboboxCss + " " + wijCSS.widget + " " + wijCSS.helperClearFix + "'></div>");
                    comboElement.append(wrapperElement);
                    self._comboElement = comboElement;
                    self._select = ele;

                    // add class to set font size to get the correct width of select.
                    ele.addClass(wijCSS.widget);
                    input = self._input = $("<input role='textbox' " + "aria-autocomplete='list' aria-haspopup='true' />").insertAfter(ele);
                    if (!self.options.data) {
                        self.options.data = self._convertSelectOptions();
                        self._initInnerData();
                    }
                } else if (ele.is("div") && $(ele.children()[0]).is("input[type='text']") && $(ele.children()[1]).is("div")) {
                    //div tag
                    self._comboElement = self._comboDiv = comboElement = ele;
                    self._oriList = $(ele.children()[1]);
                    input = self._input = $(ele.children()[0]);

                    wrapperElement.prependTo(comboElement).append(input);
                    ele.addClass(wijCSS.comboboxCss + " " + wijCSS.widget + " " + wijCSS.helperClearFix);
                    ele.attr("role", "combobox");
                } else {
                    comboElement = $("<div role='combobox' class='" + wijCSS.comboboxCss + " " + wijCSS.widget + " " + wijCSS.helperClearFix + "'></div>");
                    comboElement.append(wrapperElement);
                    self._comboElement = comboElement;
                    input = self._input = ele;
                }
                if (!self._comboDiv) {
                    comboElement.insertBefore(input);

                    //update for fixing bug 17328 at 2011/10/18 by wuhao
                    //add visible judge for visibility change at 2012/7/24
                    if (self.element.is(":visible")) {
                        input.width(input.width());
                    }

                    //end for fixing bug 17328
                    comboElement.children("." + wijCSS.comboboxWrapperCss).append(input);
                }

                if (ele.attr("title")) {
                    self._comboElement.attr("title", ele.attr("title"));
                }
                input.attribute({
                    autocomplete: "off",
                    role: "textbox",
                    "aria-haspopup": "true",
                    "aria-label": "input"
                }).addClass(wijCSS.comoboboxInputCss);
                self._oldWidth = ele.css("width");
                if (self.options.isEditable === false) {
                    input.attr("readonly", "readonly");

                    //update for add issue: when iseditable is false
                    //click the all the combobox, the dropdown list will open
                    wrapperElement.bind("click", function () {
                        if (self._isDisabled()) {
                            return;
                        }
                        self._triggerClick();
                    });
                }
                if (self._isDisabled()) {
                    self._comboElement.addClass("wijmo-wijcombobox-disabled " + wijCSS.stateDisabled);
                    input.attr("disabled", "disabled");
                }
                comboElement.bind("mouseenter.wijcombobox", function () {
                    if (self._isDisabled()) {
                        return;
                    }
                    self._addInputFocus(true, wijCSS.stateHover);
                }).bind("mouseleave.wijcombobox", function () {
                    self._addInputFocus(false, wijCSS.stateHover);
                }).attribute({
                    "aria-label": "wijcombobox",
                    "aria-expanded": "false"
                });
            };

            wijcombobox.prototype._convertSelectOptions = function () {
                var items = [], self = this, selectOptions;

                selectOptions = self._select.get(0).options;
                $.each(selectOptions, function (idx, opt) {
                    items.push({ label: opt.text, value: opt.value });
                });

                //update for case 28976
                if (self.options.selectedIndex === -1 && self.options.selectedValue === null && self.options.text === null) {
                    self.options.selectedIndex = self._select[0].selectedIndex;
                }
                return items;
            };

            /** @ignore */
            wijcombobox.prototype.getComboElement = function () {
                return this._comboElement;
            };

            wijcombobox.prototype._updateLabelTextElement = function () {
                var self = this, o = self.options, wijCSS = o.wijCSS, labelHTML = "<label class='wijmo-wijcombobox-label " + wijCSS.content + "'></label>", label = self._input.parent().children(".wijmo-wijcombobox-label");
                if (o.labelText !== null) {
                    if (label.length === 0) {
                        label = $(labelHTML);
                        self._input.parent().append(label);
                    }
                    self._label = label;
                    label.html(o.labelText);
                } else {
                    if (label) {
                        label.remove();
                        self._label = undefined;
                    }
                }
            };

            wijcombobox.prototype._showTrigger = function () {
                var self = this, o = self.options, input = self._input, inputWrapper = input.parent(), comboElement = self._comboElement, wijCSS = this.options.wijCSS, selectClone, selectWidth = 0, trigger = self._triggerArrow, label = self._label, sp, padding, labelPadding, triggerPadding, asideBorder, triggerHTML = "<div class='" + wijCSS.comboboxTriggerCss + " " + wijCSS.stateDefault + " " + wijCSS.cornerRight + "' role='button' aria-label='trigger'>" + "<span class='" + wijCSS.icon + " " + wijCSS.iconArrowDown + "'></span>" + "</div>";

                // set size
                if (self._select !== undefined) {
                    // the hidden _select element indicated the
                    // combobox is repainting; so use the native width
                    // to draw combobox
                    if (!self._select.is(":visible")) {
                        selectWidth = self._nativeWidth;
                    } else {
                        if (!$.browser.msie) {
                            selectWidth = self._select.width();
                        } else {
                            selectClone = self._select.clone();
                            self._select.after(selectClone);
                            selectWidth = selectClone.width();
                            selectClone.remove();
                        }
                        self._nativeWidth = selectWidth;
                    }

                    //update for bind array
                    comboElement.css("width", "");
                    input.width(selectWidth + (o.dropdownHeight < self.menu.element.height() ? o.selectElementWidthFix : 0));
                    self._select.hide();
                }

                //update for fixing bug 15920 by wuhao
                input.css("margin-left", "");
                input.css("margin-right", "");

                //end for bug 15920.
                comboElement.width(inputWrapper[0].offsetWidth);

                //comboElement.height(inputWrapper[0].offsetHeight);
                // show label
                self._updateLabelTextElement();
                label = self._label;

                if (o.showTrigger) {
                    input.removeClass(wijCSS.cornerAll);
                    if (trigger === undefined) {
                        trigger = self._triggerArrow = $(triggerHTML);
                        comboElement.append(trigger);
                        trigger.bind("mouseover.triggerevent", self, function (e) {
                            if (self._isDisabled()) {
                                return;
                            }
                            var ct = $(e.currentTarget);
                            ct.addClass(wijCSS.stateHover);
                        }).bind("mousedown.triggerevent", self, function (e) {
                            if (self._isDisabled()) {
                                return;
                            }
                            var ct = $(e.currentTarget);
                            ct.addClass(wijCSS.stateActive);
                        }).bind("mouseup.triggerevent", self, function (e) {
                            var ct = $(e.currentTarget);
                            ct.removeClass(wijCSS.stateActive);
                        }).bind("click.triggerevent", self, function () {
                            if (self._isDisabled()) {
                                return;
                            }
                            self._triggerClick();
                        });
                    }
                    if (o.triggerPosition === "right") {
                        trigger.css({ left: "", right: "0px" });
                        trigger.removeClass(wijCSS.cornerLeft);
                        trigger.addClass(wijCSS.cornerRight);
                    } else {
                        trigger.css({ "right": "", "left": "0px" });
                        trigger.removeClass(wijCSS.cornerRight);
                        trigger.addClass(wijCSS.cornerLeft);
                    }
                    trigger.setOutHeight(comboElement.innerHeight());
                    sp = trigger.find("span");
                    sp.css("margin-left", (trigger.innerWidth() - sp[0].offsetWidth) / 2);
                    sp.css("margin-top", (trigger.innerHeight() - sp[0].offsetHeight) / 2);
                } else {
                    if (trigger !== undefined) {
                        trigger.unbind(".triggerevent");
                        trigger.remove();
                        trigger = undefined;
                        self._triggerArrow = undefined;
                    }
                    input.removeClass(wijCSS.cornerLeft);
                    input.removeClass(wijCSS.cornerRight);
                    input.addClass(wijCSS.cornerAll);
                }

                // padding
                padding = labelPadding = triggerPadding = 0;
                if (label !== undefined) {
                    labelPadding += label.outerWidth(true);
                }
                asideBorder = o.triggerPosition === "left" ? inputWrapper.leftBorderWidth() : inputWrapper.rightBorderWidth();
                if (trigger !== undefined) {
                    triggerPadding = trigger.outerWidth(true) - asideBorder;
                }
                padding = labelPadding + triggerPadding;
                input.setOutWidth(inputWrapper.width() - padding);

                padding = padding === 0 ? "" : padding;
                if (o.triggerPosition === "right") {
                    input.css("margin-left", "");
                    input.css("margin-right", padding);
                    if (label !== undefined) {
                        label.css("left", "");
                        label.css("right", triggerPadding);
                    }
                } else {
                    input.css("margin-right", "");
                    input.css("margin-left", padding);

                    if (label !== undefined) {
                        label.css("right", "");
                        label.css("left", triggerPadding);
                    }
                }
            };

            wijcombobox.prototype._triggerClick = function () {
                var self = this, term = "";
                window.clearTimeout(self.closing);
                if (self.menu.element.is(":visible")) {
                    self.close();
                } else {
                    // TODO: click open should not render again.
                    if (self._usingRemoteData()) {
                        term = self._input.val();
                    }
                    self.search(term, undefined, false);
                }
            };

            /**
            * Remove the functionality completely. This will return the element back to its pre-init state.
            */
            wijcombobox.prototype.destroy = function () {
                var self = this, wijCSS = this.options.wijCSS, ele = self.element;
                if (self.options.isEditable === false) {
                    ele.removeAttr("readonly");
                }

                if (self._input) {
                    self._input.unbind(".wijcombobox");
                }

                if (self._comboElement) {
                    self._comboElement.unbind(".wijcombobox");
                }

                if (self._triggerArrow) {
                    self._triggerArrow.unbind(".triggerevent");
                }

                if (self._select !== undefined) {
                    self._select.removeClass(wijCSS.widget);
                    self._select.show();
                    self._input.remove();
                } else if (self._comboDiv) {
                    self._comboDiv.removeClass(wijCSS.comboboxCss + " " + wijCSS.widget + " " + wijCSS.helperClearFix);
                    self._comboDiv.removeAttr("role");
                    self._input.insertBefore(self._comboDiv);
                    self._comboDiv.children("." + wijCSS.comboboxWrapperCss).remove();
                } else {
                    ele.css("width", self._oldWidth);
                    ele.removeClass(wijCSS.comoboboxInputCss);
                    ele.removeAttr("autocomplete").removeAttr("role").removeAttribute("aria-haspopup");
                    ele.insertBefore(self._comboElement);
                    ele.css("padding", "");
                }

                if (self.options.ensureDropDownOnBody) {
                    $(window).unbind("resize.wijcombobox");
                }

                self._comboElement.remove();
                self.menu.destroy();
                self.menu.element.remove();
                _super.prototype.destroy.call(this);
            };

            wijcombobox.prototype._setOption = function (key, value) {
                var self = this, o = self.options, ele = self._comboElement, input = self.element, items, inputWrapper = input.parent(), cancelSelect, wijCSS = this.options.wijCSS, label = self._label, triggerPadding, oldSelectedIndex = o.selectedIndex, newSelectedItem, oldDisabled = o.disabled, oldSelectedItem = null, triggerWidth = 0;

                if (self._triggerArrow) {
                    triggerWidth = self._triggerArrow.outerWidth();
                }

                _super.prototype._setOption.call(this, key, value);
                if (key === "labelText") {
                    self._updateLabelTextElement();
                    label = self._label;
                    if (label && label.length > 0) {
                        if (self._triggerArrow !== undefined) {
                            triggerPadding = self._triggerArrow[0].offsetWidth;
                        }
                        if (o.triggerPosition === "right") {
                            if (label !== undefined) {
                                label.css("left", "");
                                label.css("right", triggerPadding);
                            }
                        } else {
                            if (label !== undefined) {
                                label.css("right", "");
                                label.css("left", triggerPadding);
                            }
                        }
                        self.repaint();
                    }
                } else if (key === "showTrigger") {
                    self._showTrigger();
                    if (!o.showTrigger && self.element.is("select")) {
                        input.width(input.width() + triggerWidth);
                    }
                } else if (key === "triggerPosition") {
                    input.width(input.width() + triggerWidth);
                    self._showTrigger();
                } else if (key === "selectionMode") {
                    self.menu._setOption("selectionMode", value);
                } else if (key === "isEditable") {
                    if (value) {
                        //update for 27917
                        self._input.removeAttr("readonly");

                        //update for add issue: when iseditable is false
                        //click the all the combobox, the dropdown list will open
                        $("." + wijCSS.comboboxWrapperCss, self._comboElement[0]).bind("click", function () {
                            self._triggerClick();
                        });
                    } else {
                        //update for 27917
                        self._input.attr("readonly", "readonly");
                        $("." + wijCSS.comboboxWrapperCss, self._comboElement[0]).unbind("click");
                    }
                } else if (key === "data" || key === "dataSource") {
                    self._initInnerData();
                    self._setSelectedIndex(o.selectedIndex);
                    if ($.isArray(self.innerData)) {
                        self.listHasCreated = false;
                        self._createDropDownList();
                    } else {
                        try  {
                            self.innerData.loaded = function (e, data) {
                                if (e === null) {
                                    self.items = null;
                                } else {
                                    self.items = $.isArray(e) ? e : e.items;
                                }
                                self.listHasCreated = false;
                                self._createDropDownList();
                            };
                            self.innerData.load(null);
                        } catch (e) {
                        }
                    }

                    if (o.selectedIndex !== -1) {
                        oldSelectedItem = items ? items[oldSelectedIndex] : null;
                        items = self.innerData;

                        self._triggerChangeEvents(oldSelectedItem, oldSelectedIndex);
                    }
                    self._keypress = false;
                } else if (key === "selectedIndex") {
                    if (value === oldSelectedIndex) {
                        return;
                    }
                    if (value === null || value === undefined) {
                        value = -1;
                    }
                    if (self.innerData === null) {
                        items = null;
                    } else {
                        items = $.isArray(self.innerData) ? self.innerData : self.innerData.items;
                    }

                    if (o.selectionMode === "single") {
                        oldSelectedItem = items ? items[oldSelectedIndex] : null;
                        if (value > -1) {
                            if (items && items[value] !== null) {
                                newSelectedItem = items[value];
                            }
                            cancelSelect = self._triggerSelectedIndexChanging(oldSelectedItem, newSelectedItem, oldSelectedIndex, value);
                            if (cancelSelect) {
                                o.selectedIndex = oldSelectedIndex;
                                return;
                            }

                            // if the data option is reset and the self.selectedItem is underfined,
                            // need use oldSelectedIndex to clear selection
                            if (oldSelectedIndex !== null && oldSelectedIndex !== -1 && oldSelectedIndex !== undefined && oldSelectedItem) {
                                oldSelectedItem.selected = false;
                                this.menu.unselectItems(oldSelectedIndex);
                                if (oldSelectedItem.element) {
                                    oldSelectedItem.element.removeClass("wijmo-wijcombobox-selecteditem");
                                }
                            }

                            if (items && items[value] !== null) {
                                self.selectedItem = items[value];
                                if (self.selectedItem) {
                                    self.selectedItem.selected = true;
                                    self._setInputText(self.selectedItem.label);
                                    o.selectedValue = self.selectedItem.value;
                                    o.inputTextInDropDownList = true;
                                    //o.text = self._input.val();for #33666 issue
                                }
                            }
                        } else if (value <= -1 || !value) {
                            cancelSelect = self._triggerSelectedIndexChanging(oldSelectedItem, null, oldSelectedIndex, value);
                            if (cancelSelect) {
                                o.selectedIndex = oldSelectedIndex;
                                return;
                            }
                            o.inputTextInDropDownList = false;
                            self._clearSelection();
                        }

                        self._triggerChangeEvents(oldSelectedItem, oldSelectedIndex);
                    } else {
                        if (!$.isArray(oldSelectedIndex)) {
                            oldSelectedIndex = [oldSelectedIndex];
                        }

                        $.each(oldSelectedIndex, function (i, index) {
                            if (self.menu.items && self.menu.items[index]) {
                                self.menu.items[index].selected = false;
                            }
                        });
                        this.menu.unselectItems(oldSelectedIndex);
                        self.selectedItems = [];
                        self.selectedItem = null;
                        if (!$.isArray(value)) {
                            value = [value];
                            o[key] = value;
                        }
                        self._setSelectedIndex(value);
                        $.each(value, function (i, index) {
                            if (self.menu.items && self.menu.items[index]) {
                                self.menu.items[index].selected = true;
                            }
                        });

                        self._triggerChangeEvents(null, null);
                    }
                } else if (key === "selectedValue") {
                    items = self.items;
                    if (!items) {
                        items = self.innerData;
                    }
                    if (o.selectionMode === "single") {
                        oldSelectedItem = items ? items[oldSelectedIndex] : null;
                    } else {
                        oldSelectedIndex = null;
                    }

                    if (value != null) {
                        if (self.selectedItem && self.selectedItem.selected !== undefined) {
                            self.selectedItem.selected = false;
                        }

                        if (items) {
                            if (this.options.selectedIndex > -1 && items.length > this.options.selectedIndex && items[this.options.selectedIndex]) {
                                items[this.options.selectedIndex].selected = false;
                                this.menu.deactivate();
                                this.menu.unselectItems(this.options.selectedIndex);
                                self.menu.items[this.options.selectedIndex].selected = false;
                            }
                            $.each(items, function (index, item) {
                                if (items[index].value === value) {
                                    self.selectedItem = items[index];
                                    self.selectedItem.selected = true;
                                    self.menu.items[index].selected = true;

                                    //self._input.val(self.selectedItem.label);
                                    self._setInputText(self.selectedItem.label);
                                    if (o.selectionMode === "single") {
                                        o.selectedIndex = index;
                                    } else {
                                        o.selectedIndex = [index];
                                    }
                                    o.inputTextInDropDownList = true;

                                    //o.text = self._input.val();for #33666 issue
                                    return false;
                                }
                            });
                        }
                    } else if (o.selectionMode === "single") {
                        o.inputTextInDropDownList = false;
                        self._clearSelection();
                    }

                    self._triggerChangeEvents(oldSelectedItem, oldSelectedIndex);
                } else if (key === "text") {
                    if (o.forceSelectionText && self._checkTextInItems(value) === -1) {
                        return;
                    }

                    //self._input.val(value);
                    self._setInputText(value);
                } else if (key === "selectElementWidthFix") {
                    self._showTrigger();
                } else if (key === "adjustComboWidth" || key === "dropdownWidth") {
                    self._handleAdjustWidthOptions();
                }
            };

            wijcombobox.prototype._handleAdjustWidthOptions = function () {
                var self = this, o = self.options, width = 0, safeWidth = 25;
                if (o.adjustComboWidth === true) {
                    if (o.dropdownWidth === "auto" || o.dropdownWidth === "fit") {
                        width = self._getMaxListItemWidth() + safeWidth; // add a safe amount to avoid word wrap in case of v-scrollbar appears.
                    } else {
                        width = o.dropdownWidth;
                    }
                    self._setComboWidth(width);
                    self._setDropdownWidth(width);
                } else {
                    if (o.dropdownWidth === "auto") {
                        width = self._getComboWidth();
                    } else if (o.dropdownWidth === "fit") {
                        width = Math.max(self._getComboWidth(), self._getMaxListItemWidth() + safeWidth);
                    } else {
                        width = o.dropdownWidth;
                    }
                    self._setDropdownWidth(width);
                }
                return width;
            };

            wijcombobox.prototype._innerDisable = function () {
                _super.prototype._innerDisable.call(this);
                this._toggleDisableCombobox(true);
            };

            wijcombobox.prototype._innerEnable = function () {
                _super.prototype._innerEnable.call(this);
                this._toggleDisableCombobox(false);
            };

            wijcombobox.prototype._toggleDisableCombobox = function (disabled) {
                var wijCSS = this.options.wijCSS;
                this._input.prop("disabled", disabled);
                this._comboElement.toggleClass("wijmo-wijcombobox-disabled " + wijCSS.stateDisabled, disabled);
                if (this._comboDiv) {
                    this._input.toggleClass("wijmo-wijcombobox-disabled " + wijCSS.stateDisabled, disabled);
                }
                if (disabled) {
                    this.close();
                }
            };

            wijcombobox.prototype._setSelectedIndex = function (value) {
                var self = this, o = self.options, selectedItems = [], data = self.innerData;
                if (value === null || value === undefined) {
                    return;
                }

                if (value === -1) {
                    self.selectedItem = null;
                    o.selectedIndex = -1;
                    o.selectedValue = null;
                    if (o.text) {
                        self._input.val(o.text);
                    } else {
                        self._input.val("");
                    }
                } else {
                    if ($.isArray(value)) {
                        self.selectedItems = [];
                        $.each(value, function (i, val) {
                            if (data && data[val] !== null && data[val] !== undefined) {
                                data[val].selected = true;
                                selectedItems.push(data[val]);
                            }
                        });
                        self.selectedItems = selectedItems;
                        self._selectedItemsToInputVal(selectedItems);
                    } else {
                        if (data && data[value] !== null && data[value] !== undefined) {
                            data[value].selected = true;
                            self._input.val(data[value].label);
                            self.selectedItem = data[value];
                        } else if (data && $.isArray(data) && value > data.length - 1) {
                            o.selectedIndex = -1;
                            self._input.val("");
                        }
                    }
                }
                o.text = self._input.val();
            };

            /** Searches the wijcombobox drop-down list for the specified value.
            * @param {string} value Text to search in the drop-down list.
            * @param {object} eventObj The jquery event object.
            */
            wijcombobox.prototype.search = function (value, eventObj, filtering) {
                if (typeof filtering === "undefined") { filtering = true; }
                var self = this, o = self.options, datasource = self.innerData, d, isBind;

                window.clearTimeout(self.closing);
                d = {
                    value: value,
                    e: eventObj,
                    self: self
                };

                // load data when data is not loaded yet
                // or datasource is using a proxy to obtain data.
                if (datasource !== null || self._comboDiv) {
                    //update 2012/9/14
                    isBind = self._isBind();

                    // check index will skip search event
                    if (eventObj !== "checkindex") {
                        if (self._trigger("search", eventObj, { datasrc: datasource, term: d }) === false) {
                            return;
                        }
                        datasource = self.innerData;
                    }

                    if ($.isArray(datasource) || isBind || self._comboDiv || (!self._usingRemoteData() && datasource.items && $.isArray(datasource.items) && datasource.items.length > 0)) {
                        self._hideShowArrow(false);
                        self._onListLoaded(datasource, d, filtering);
                    } else if (!isBind && $.isArray(o.dataSource)) {
                        return;
                    } else {
                        if (self._usingRemoteData() && eventObj !== undefined && value.length < o.minLength) {
                            return;
                        }
                        self._hideShowArrow(false);

                        // update for: datasource loaded event don't fired
                        // in combobox
                        datasource.loaded = function (e, data) {
                            //need to re initialize the dropdown list
                            //datasource condition the data is get by proxy
                            self.listHasCreated = false;
                            self._createDropDownList(e);

                            //self._onListLoaded(self.items, data);
                            self._onListLoaded(e, data, filtering);
                            if (self.originalDataSourceLoaded) {
                                self.originalDataSourceLoaded(e, data);
                            }
                        };
                        datasource.load(d);
                    }
                }
            };

            /** Get the select item(s) in combobox.
            * @remarks
            *        when using multiple mode, it will return array object.
            *        If no item is selected, it will return null or empty array.
            * @returns {array} array object or empty array.
            */
            wijcombobox.prototype.getSelectedItems = function () {
                var o = this.options;
                if (o.selectionMode === "single") {
                    return this.selectedItem;
                } else {
                    return this.selectedItems;
                }
            };

            //for bind data
            wijcombobox.prototype._isBind = function () {
                var o = this.options, data = o.data;

                if (data !== null && data.label && data.label.bind) {
                    return true;
                }
                return false;
            };

            wijcombobox.prototype._getMappingItems = function () {
                var o = this.options, dataSource = o.dataSource, data = o.data, mappingItems, labelKey, valueKey;
                if (!dataSource || !data) {
                    return null;
                }

                if (!data.label || !data.label.bind || !data.value || !data.value.bind) {
                    return null;
                }

                labelKey = data.label.bind;
                valueKey = data.value.bind;

                //1.Array
                if (dataSource && dataSource.length !== 0) {
                    mappingItems = [];

                    $.each(dataSource, function (i, item) {
                        mappingItems.push({ label: item[labelKey], value: item[valueKey] });
                    });

                    return mappingItems;
                }
                return null;
            };

            //end for bind data
            wijcombobox.prototype._clearSelection = function (notfiredTextChanged) {
                var self = this, o = self.options;

                if (o.selectionMode === "single") {
                    if (self.selectedItem) {
                        self.selectedItem.selected = false;
                        self.selectedItem = null;
                    }
                } else {
                    if (self.selectedItems) {
                        $.each(self.selectedItems, function (index, item) {
                            if (item && item.selected) {
                                item.selected = false;
                            }
                        });
                        self.selectedItem = null;
                        self.selectedItems = [];
                    }
                }
                o.selectedValue = null;

                //self._input.val("");
                self._setInputText("", notfiredTextChanged);
                //o.text = self._input.val();for #33666 issue
            };

            wijcombobox.prototype._usingRemoteData = function () {
                var o = this.options.data, r = false;
                if (!$.isArray(o) && o !== null && o.proxy) {
                    r = true;
                }
                return r;
            };

            wijcombobox.prototype._hideShowArrow = function (show) {
                // hide arrow to show
                var self = this, input = self.element, arrow = self._triggerArrow;

                if (arrow !== undefined) {
                    arrow[show ? "show" : "hide"]();
                }
                input[show ? "removeClass" : "addClass"]("wijmo-wijcombobox-loading");
            };

            wijcombobox.prototype._onListLoaded = function (datasource, data, filtering) {
                var self = data.self, ele = self._input, o = self.options, wijCSS = this.options.wijCSS, searchTerm = data.value, items, idx, itemsToRender, olditem, oldIndex;

                if (!datasource) {
                    items = null;
                } else {
                    items = $.isArray(datasource) ? datasource : datasource.items;
                }

                self.items = items;
                if (data.e === "checkindex") {
                    idx = o.selectedIndex;

                    if (o.selectionMode === "multiple" && $.isArray(idx)) {
                        self.selectedItems = [];
                        $.each(idx, function (i, n) {
                            var itm = items[n];
                            itm.selected = true;
                            self.selectedItems.push(itm);
                        });
                        self._selectedItemsToInputVal(self.selectedItems);
                    } else {
                        items[idx].selected = true;
                        self.selectedItem = items[idx];
                        ele.val(self.selectedItem.label);
                    }
                    self._hideShowArrow(true);
                    return;
                }

                // fixed the issue 42893, if the selected item's label is empty, here should
                // not reset the selection.
                if (filtering && ele.val() === "") {
                    olditem = this.selectedItem;
                    if (olditem && olditem.label !== "") {
                        oldIndex = o.selectedIndex;
                        self._clearSelection();
                        self._setSelectedIndex(-1);
                        self._triggerChangeEvents(olditem, oldIndex);
                        self.menu.deactivate();
                    }
                }

                // only fileter result when using local data.
                if (!self._usingRemoteData() && items) {
                    /*update for improving performance
                    self._filter(items, searchTerm);
                    itemsToRender = $.grep(items, function (item1) {
                    return !o.autoFilter || item1.match;
                    });*/
                    itemsToRender = items;
                } else {
                    self._topHit = null;
                    itemsToRender = items;
                }
                if ((itemsToRender && itemsToRender.length > 0) || self._comboDiv) {
                    // open dropdown list
                    if (self._openlist(itemsToRender, data, searchTerm)) {
                        // move the trigger dropdown open event to openlist.
                        //self._trigger("open");
                        self._addInputFocus(true, wijCSS.stateFocus);
                    }
                } else {
                    self.close(null, true);
                }
                self._hideShowArrow(true);
            };

            /** Closes drop-down list.
            * @param {?EventObj} event The jquery event object.
            * @param {?boolean} skipAnimation A value indicating whehter to skip animation.
            */
            wijcombobox.prototype.close = function (event, skipAnimation) {
                var self = this, menu, wijCSS = this.options.wijCSS, hidingAnimation, hidingStyle;
                menu = self.menu;

                self._dropDownHeight = menu.element.outerHeight();
                self._dropDownWidth = menu.element.outerWidth();

                window.clearTimeout(self.closing);

                // test parent element is need, hidingAnimation
                // because some effect will wrap the target element.
                if (menu.element.is(":visible") && !menu.element.is(":animated") && !menu.element.parent().is(":animated")) {
                    self._trigger("close", event);
                    self._comboElement.attribute("aria-expanded", "false");
                    menu.deactivate();
                    hidingAnimation = self.options.hidingAnimation;

                    //add for size animation by wuhao 2011/7/16
                    if (hidingAnimation && (hidingAnimation.effect === "size" || hidingAnimation.animated === "size")) {
                        hidingAnimation.options = $.extend({
                            to: {
                                width: 0,
                                height: 0
                            }
                        }, hidingAnimation.options);
                    }
                    hidingStyle = menu.element.attr("style");

                    //end for size animation
                    if (skipAnimation !== true && hidingAnimation) {
                        menu.element.hide(hidingAnimation.effect || hidingAnimation.animated, hidingAnimation.options, hidingAnimation.speed || hidingAnimation.duration, function () {
                            menu.element.removeAttr("style").attr("style", hidingStyle).hide();
                            if (hidingAnimation.callback) {
                                hidingAnimation.callback.apply(this, arguments);
                            }
                        });
                    } else {
                        menu.element.hide();
                    }

                    self._addInputFocus(false, wijCSS.stateFocus);

                    //$(document).unbind("click", self.closeOnClick);
                    $(document).unbind("mouseup", self.closeOnClick);
                    self._inputBlurCausedByListItemClick = false;
                }
            };

            wijcombobox.prototype._change = function () {
                // TODO: finish _change event.
                var self = this, o = self.options, f = o.forceSelectionText, m = o.selectionMode, ele = self._input, t = ele.val(), itm = self.selectedItem, items = self.selectedItems, oldIndex, innerData = self.innerData, inputIndex = -1;

                oldIndex = (o.selectedIndex || o.selectedIndex > -1) ? o.selectedIndex : -1;

                if (f) {
                    if (m === "single") {
                        if (itm !== null && itm !== undefined) {
                            if (itm.label !== t) {
                                //ele.val(itm.label);
                                self._setInputText(itm.label);
                            }
                        } else {
                            //ele.val("");
                            self._setInputText("");
                        }
                    }
                } else {
                    //update for inputed non-listed value,
                    //update selected index and selected value
                    if (m === "single") {
                        var labelNotEqualsT = false;
                        if (itm !== null && itm !== undefined) {
                            labelNotEqualsT = (itm.label) ? (itm.label.toString() !== t) : ("" !== t);
                        }

                        if ((!itm && t !== "") || labelNotEqualsT) {
                            if (self.selectedItem !== null && self.selectedItem !== undefined) {
                                self.selectedItem.selected = false;

                                self.menu.unselectItems(o.selectedIndex);
                            }
                            inputIndex = self._checkTextInItems(t);
                            if (inputIndex === -1) {
                                self.selectedItem = null;
                                o.selectedIndex = -1;
                                o.selectedValue = null;
                                o.inputTextInDropDownList = false;
                            } else {
                                if (innerData) {
                                    innerData = $.isArray(innerData) ? innerData : innerData.items;
                                    self.selectedItem = innerData[inputIndex];
                                    o.selectedIndex = inputIndex;
                                    o.selectedValue = self.selectedItem.value;
                                    o.inputTextInDropDownList = true;
                                }
                            }

                            //o.text = self._input.val();
                            self._setInputText(self._input.val());

                            self._triggerChangeEvents(itm, oldIndex);
                        } else {
                            self._setInputText(t);
                        }
                    }
                }

                //Todo: when input something to combobox,
                //the text will restore in multiple mode
                //Maybe it need to be adjusted.
                if (m === "multiple") {
                    //update for add issue: when iseditable is false
                    //click the all the combobox, the dropdown list will open
                    //self._selectedItemsToInputVal(self.selectedItems);
                    if (!self.selectedItems || self.selectedItems.length === 0) {
                        items = [itm];
                    }
                    self._selectedItemsToInputVal(items);
                }
            };

            wijcombobox.prototype._checkTextInItems = function (text) {
                var data = this.items, index = -1;

                if (text && !!data && !!data.length) {
                    $.each(data, function (i, item) {
                        if (item && item.label && item.label.toString() === text) {
                            index = i;
                            return false;
                        }
                    });
                }

                return index;
            };

            wijcombobox.prototype._openlist = function (items, data, searchTerm) {
                var self = data.self, o = self.options, eventObj = data.e, keypress, pressDELETEKey, textWidth, menuElement = self.menu.element, verticalBorder = 2, headerHeight = 0, dropDownHeight, origCloseOnClick, h, showingAnimation, showingStyle, showingSize, inputValueLength = $.trim(self._input.val()).length, keyCode = wijmo.getKeyCodeEnum(), zIndex, needHighlightMatching = false, innerData, updatePositionTimer, alreadyOpen = false;

                keypress = self._keypress = !!eventObj;
                pressDELETEKey = (eventObj !== undefined) && (eventObj.keyCode === keyCode.BACKSPACE || eventObj.keyCode === keyCode.DELETE);

                alreadyOpen = menuElement.is(":visible");

                if ($.ui) {
                    menuElement.zIndex(self.element.zIndex() + 100);
                } else {
                    zIndex = parseInt(self.element.css("zIndex"), 10);
                    if (isNaN(zIndex)) {
                        zIndex = 0;
                    }
                    menuElement.css("zIndex", zIndex + 100);
                }

                //update for 32309 issue
                if (!self.listHasCreated) {
                    self._createDropDownList();
                }

                if (self.innerData) {
                    if ($.isArray(self.innerData)) {
                        innerData = self.innerData;
                    } else {
                        innerData = self.innerData.items;
                    }
                }
                if (!innerData || innerData.length === 0) {
                    return false;
                }

                /* for improving performance
                if (self._comboDiv) {
                //update for case 20689 at 2012/4/11
                if (!self.listHasCreated) {
                //update for issue 24130 at 2012/7/20
                //self.menu.setTemplateItems(items);
                self.menu.setTemplateItems(o.data);
                self.menu.renderList();
                self.listHasCreated = true;
                }
                } else {
                if (!self.listHasCreated) {
                self.menu.setItems(items);
                self.menu.renderList();
                self.listHasCreated = true;
                }
                }*/
                //update for issue 24130 at 2012/7/20
                if (!self._usingRemoteData() && searchTerm !== null && searchTerm !== undefined) {
                    needHighlightMatching = self._keypress && o.isEditable && o.columns.length === 0 && o.highlightMatching && inputValueLength > 0;

                    //if down key press condition for 33017 issue at 2013/1/8
                    if (eventObj && eventObj.keyCode === keyCode.DOWN && searchTerm.length === 0 && inputValueLength > 0) {
                        self._topHit = self.menu.filterItems(self._input.val(), false, needHighlightMatching);
                    } else {
                        self._topHit = self.menu.filterItems(searchTerm, o.autoFilter, needHighlightMatching);
                    }

                    //can't find the matched items
                    if (self._topHit === null && self.innerData && $("li[wijhidden]", self.menu.element).length === self.innerData.length) {
                        self.close(null, true);
                        return false;
                    }
                }

                // show dropdown
                menuElement.show();
                textWidth = self._handleAdjustWidthOptions();

                dropDownHeight = o.dropdownHeight;

                if (menuElement.children(".wijmo-wijsuperpanel-header")) {
                    headerHeight = menuElement.children(".wijmo-wijsuperpanel-header").outerHeight() || 0;
                }

                //end for fixing bug 15778
                h = self._menuUL.outerHeight() + verticalBorder + headerHeight;

                if (h < dropDownHeight) {
                    // The exist scrollbar will be removed, width of ul element will increase, it means that the height of ul also will change.
                    // In this case, increase ul width firstly, and get a correct ul height for the wijlist element.
                    self._menuUL.setOutWidth(textWidth);
                    h = self._menuUL.outerHeight() + verticalBorder + headerHeight;
                } else {
                    h = dropDownHeight;
                }

                menuElement.setOutHeight(h);
                self.menu.refreshSuperPanel();
                self._positionList();
                if (!keypress && self.selectedItem !== undefined) {
                    self.menu.activate(null, self.selectedItem, true);
                }
                if (keypress && !pressDELETEKey) {
                    if (o.isEditable) {
                        self._runAutoComplete();
                    } else {
                        self.menu.activate(null, self._topHit, true);
                    }
                } else {
                    showingAnimation = self.options.showingAnimation;
                    if (o.showingAnimation !== null && !pressDELETEKey) {
                        self.menu.element.hide();
                        showingSize = {
                            from: { width: 0, height: 0 },
                            to: {
                                width: self._dropDownWidth || menuElement.outerWidth(),
                                height: self._dropDownHeight || menuElement.outerHeight()
                            }
                        };
                        if (showingAnimation && (showingAnimation.effect === "size" || showingAnimation.animated === "size")) {
                            showingAnimation.options = $.extend(showingSize, showingAnimation.options);
                        }
                        showingStyle = menuElement.attr("style");

                        //end for size animation
                        menuElement.show(showingAnimation.effect || showingAnimation.animated, showingAnimation.options, showingAnimation.speed || showingAnimation.duration, function () {
                            //add for size animation by wuhao 2011/7/16
                            menuElement.removeAttr("style").attr("style", showingStyle).show();

                            //end for size animation
                            if (showingAnimation.callback) {
                                showingAnimation.callback.apply(this, arguments);
                            }

                            if ($.browser.msie) {
                                menuElement.css("filter", "");
                            }
                        });
                    }
                }
                if (!self.hasOwnProperty("closeOnClick")) {
                    origCloseOnClick = self.closeOnClick;
                    self.closeOnClick = function (e) {
                        return origCloseOnClick(e);
                    };
                }

                if (!alreadyOpen) {
                    self._trigger("open");
                    self._comboElement.attribute("aria-expanded", "true");
                }

                //update for issue 2012/6/14: place combobox in expander
                //open the dropdown, then collapse the expander
                //the dropdown is still open
                //$(document).bind("click", self, self.closeOnClick);
                $(document).bind("mouseup", self, self.closeOnClick);

                if (o.ensureDropDownOnBody) {
                    $(window).bind("resize.wijcombobox", function () {
                        //maybe need to update the position of dropdown
                        //because combobox may change its position after window resize.
                        if (updatePositionTimer) {
                            clearTimeout(updatePositionTimer);
                        }
                        updatePositionTimer = setTimeout(function () {
                            self._positionList();
                        }, 100);
                    });
                }
                return true;
            };

            /** @ignore */
            wijcombobox.prototype.closeOnClick = function (e) {
                var self = e.data, wijCSS = self.options.wijCSS, offset, t = e.target;

                if (!$.contains(self._comboElement[0], t) && !$.contains(self.menu.element[0], t)) {
                    if ($.support.isTouchEnabled && $.support.isTouchEnabled()) {
                        offset = self.menu.element.offset();
                        if (e.pageX < offset.left || e.pageX > offset.left + self.menu.element.width() || e.pageY < offset.top || e.pageY > offset.top + self.menu.element.height()) {
                            self.close();
                        }
                    } else {
                        self.close();
                    }
                    $("." + wijCSS.comboboxWrapperCss, self._comboElement[0]).removeClass(wijCSS.stateHover).removeClass(wijCSS.stateFocus);
                    $("." + wijCSS.comboboxTriggerCss, self._comboElement[0]).removeClass(wijCSS.stateHover).removeClass(wijCSS.stateFocus);
                }

                if (self.options.ensureDropDownOnBody) {
                    $(window).unbind("resize.wijcombobox");
                }
            };

            wijcombobox.prototype._positionList = function () {
                var self = this, defaultPosition, positionOptions = self.options.dropDownListPosition;
                defaultPosition = {
                    my: "left top",
                    at: "left bottom",
                    of: self._comboElement,
                    collision: "none"
                };
                defaultPosition = $.extend(defaultPosition, positionOptions);
                self.menu.element.position(defaultPosition);
            };

            wijcombobox.prototype._runAutoComplete = function () {
                var self = this, ele = self._input, topHit = self._topHit, oldText, fullText, start, end;
                if (!self.options.autoComplete || topHit === null || topHit === undefined) {
                    return;
                }
                self.menu.activate(null, topHit, true);
                oldText = ele.val();
                fullText = topHit.label;
                ele.val(fullText);
                start = oldText.length;
                end = fullText.length;
                self._selectText(start, end, ele);
            };

            wijcombobox.prototype._selectText = function (start, end, input) {
                var v = input.val(), inputElement = input.get(0), range;
                if (v.length > 0) {
                    if (inputElement.setSelectionRange !== undefined) {
                        inputElement.setSelectionRange(start, end);
                    } else if (inputElement.createTextRange !== undefined) {
                        range = inputElement.createTextRange();
                        range.moveStart("character", start);
                        range.moveEnd("character", end - v.length);
                        range.select();
                    }
                }
            };

            wijcombobox.prototype._move = function (direction, event) {
                if (!this.menu.element.is(":visible")) {
                    this.search("", event);
                    return;
                }
                if (this.menu.first() && /^previous/.test(direction) || this.menu.last() && /^next/.test(direction)) {
                    //update for fixing bug 15964 by wuhao
                    //this.menu.deactivate();
                    //end for bug 15964.
                    return;
                }
                this.menu[direction](event);
            };

            wijcombobox.prototype._escapeRegex = function (value) {
                if (value === undefined) {
                    return value;
                }
                return value.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1");
            };

            wijcombobox.prototype._filter = function (array, searchTerm) {
                var term1 = this._escapeRegex(searchTerm), matcher, topHit = null;

                /// TODO : start with or contains and case sensitive.
                if (!array) {
                    return null;
                }
                matcher = new RegExp(term1, "i");
                $.each(array, function (index, item) {
                    if (term1 === undefined || term1.length === 0) {
                        item.match = true;
                        return;
                    }
                    var matchResult = matcher.exec(item.label);
                    if (matchResult === null) {
                        item.match = false;
                    } else {
                        if (topHit === null && matchResult.index === 0) {
                            topHit = item;
                        }
                        item.match = matchResult.index >= 0;
                    }
                });
                this._topHit = topHit;
                return array;
            };

            wijcombobox.prototype._getMaxListItemWidth = function () {
                var $div = $("<div>").addClass("wijmo-wijcombobox-list ui-widget").appendTo(document.body), $ul = this.menu.element.find("ul").clone().css("width", "").appendTo($div), width = $ul.outerWidth();

                $div.remove();
                return width;
            };

            wijcombobox.prototype._setComboWidth = function (width) {
                this._comboElement.width(width);
                if (this._triggerArrow) {
                    width -= this._triggerArrow.outerWidth();
                }
                this._input.width(width);
            };

            wijcombobox.prototype._setDropdownWidth = function (width) {
                var $list = this.menu.element, padding = $list.css("padding");
                $list.css("padding", "0px");
                $list.setOutWidth(width);
                $list.css("padding", padding);
            };

            wijcombobox.prototype._getComboWidth = function () {
                return this._comboElement.outerWidth();
            };

            wijcombobox.prototype._getDropdownWidth = function () {
                return this.menu.element.outerWidth();
            };
            return wijcombobox;
        })(wijmo.wijmoWidget);
        combobox.wijcombobox = wijcombobox;

        var wijcombobox_options = (function () {
            function wijcombobox_options() {
                /** Selector option for auto self initialization. This option is internal.
                * @ignore
                */
                this.initSelector = ":jqmData(role='wijcombobox')";
                /**
                * @ignore
                */
                this.wijCSS = {
                    comboboxCss: "wijmo-wijcombobox",
                    comboboxWrapperCss: "wijmo-wijcombobox-wrapper",
                    comoboboxInputCss: "wijmo-wijcombobox-input",
                    comboboxListCss: "wijmo-wijcombobox-list",
                    comboboxTriggerCss: "wijmo-wijcombobox-trigger"
                };
                /** wijdataview to which this wijcombobox is bound.
                * @type {wijdataview}
                * @remarks
                *   This option is used if this wijcombobox is bound to a wijdataview.
                *   In that case, you can also specify a mapping option to select the properties to bind to,
                *   and the data option returns an array of objects containing
                *   value and label property values determined by that mapping.
                */
                this.dataSource = null;
                /** A value that specifies the underlying data source provider of wijcombobox.
                * @type {wijdatasource|Array}
                * @remarks
                *   This option could either be a wijdatasource object
                *   or an Object Array containing an item such as
                *   {label: "label text", value: "value"}.
                * @example
                *        var testArray = [
                *            {label: 'c++',value: 'c++'},
                *            {label: 'java',value: 'java'},
                *            {label: 'php',value: 'php'}
                *        ];
                *        $("#tags").wijcombobox({
                *            data: testArray
                *        });
                */
                this.data = null;
                /** A value that specifies the text in the wijcombobox label.*/
                this.labelText = null;
                /** A value that determines the minimum length of text
                *   that can be entered in the wijcombobox text box to issue an AJAX request.
                */
                this.minLength = 4;
                /** A value that determines the duration (in milliseconds) of the time
                *   to delay before autocomplete begins after typing stops.
                */
                this.delay = 300;
                /** A value that specifies the animation options for a drop-down list
                *   when it is visible.
                * @example
                *       var animationOptions = {
                *           animated: "Drop",
                *           duration: 1000
                *       };
                *       $("#tags").wijcombobox("option", "showingAnimation", animationOptions)
                });
                */
                this.showingAnimation = null;
                /** A value that specifies the animation options such as the animation effect and
                *   duration for the drop-down list when it is hidden.
                * @example
                *       var animationOptions = {
                *           animated: "Drop",
                *           duration: 1000
                *       };
                *       $("#tags").wijcombobox("option", "hidingAnimation", animationOptions)
                */
                this.hidingAnimation = null;
                /** A value that determines whether to show the trigger of wijcombobox.*/
                this.showTrigger = true;
                /** A value that specifies the position of the drop-down list trigger.
                * @remarks
                *        possible value: right or left
                */
                this.triggerPosition = "right";
                /**  A value that specifies the height of the drop-down list.
                * @remarks
                *       If the total height of all items is less than the value of this option,
                *       it will use the total height of items as the height of the drop-down list.
                */
                this.dropdownHeight = 300;
                /** A value that specifies the width of the drop-down list.
                * @type {number|string}
                * @remarks
                *       When this option is set to "auto", the width of the drop-down
                *       list is equal to the width of wijcombobox.
                *       When this option is set to "fit", the width of the drop-down
                *       list will fit the widest item independently.
                */
                this.dropdownWidth = "auto";
                /** A value that determines whether to select the item when the item gains focus or is activated. */
                this.selectOnItemFocus = false;
                /** A value determines whether to shorten the drop-down list items
                *   by matching the text in the textbox after typing.
                */
                this.autoFilter = true;
                /** A value that determines whether to start the auto-complete
                *   function after typing in the text if a match exists.
                */
                this.autoComplete = true;
                /** A value that determines whether to highlight the keywords in an item.
                * @remarks
                *       If "abc" is typed in the textbox,
                *       all "abc" matches are highlighted in the drop-down list.
                */
                this.highlightMatching = true;
                /** A value that specifies the position options of the drop-down list.
                *   The default value of the "of" options is the input of wijcombobox.
                * @example
                *    var positionOptions = {my:"right", at:"top"};
                *   //specifies the position options of the drop-down list on "right, top" of combobox.
                *   $("#tags").wijcombobox("option", "dropDownListPosition", positionOptions)
                */
                this.dropDownListPosition = {};
                /** An array that specifies the column collections of wijcombobox.
                * @example
                *       $("#tags").wijcombobox("option", "columns", [
                *           {name: 'header1', width: 150},
                *           {name: 'header2', width: 150},
                *           {name: 'header3', width: 150}
                *       ]);
                */
                this.columns = [];
                /** A value that specifies the selection mode of wijcombobox.
                * @remarks
                *       Possible options are: "single" and "multiple".
                */
                this.selectionMode = "single";
                /** A value that specifies the separator for
                *   the multiple selected items text in the textbox.
                */
                this.multipleSelectionSeparator = ",";
                /** A value that determines whether to check the input text against
                *   the text of the selected item when the focus blurs.
                * @remarks
                *       If the text does not match any item, input text will restore
                *       to text the selected item or empty if no item is selected.
                */
                this.forceSelectionText = false;
                /** A function called when any item in list is selected.
                * @event
                * @dataKey {element} element LI element with this item.
                * @dataKey {object} list wijlist instance.
                * @dataKey {string} label Label of item.
                * @dataKey {object} value Value of item.
                * @dataKey {string} text Could be set in handler to override rendered label of item.
                */
                this.select = null;
                /** A value that determines whether input is editable.*/
                this.isEditable = true;
                /** A value that specifies the index of the item to select when using single mode.
                * @type {number|array}
                * @remarks
                *       If the selectionMode is "multiple", then this option could be set
                *       to an array of Number which contains the indices of the items to select.
                *       If no item is selected, it will return -1.
                * @example
                *  //To get the selected item using the selected index:
                *      var selectedIndex = $("# tags ").wijcombobox("option","selectedIndex");
                *      var selectedItem = $("# tags ").wijcombobox("option","data")[selectedIndex];
                *  // To set the selected item using the selected index:
                *      $("#tags").wijcombobox("option"," selectedIndex", 5);
                */
                this.selectedIndex = -1;
                /** A value that specifies the value of the item to select when using single mode.
                * @type {number|string|object}
                * @remarks
                *       If no item is selected, it will return null.
                */
                this.selectedValue = null;
                /** A value that specifies the input text of the combobox is in dropdown list or not.
                * @remarks
                *       It's readonly option, if user typed text is not in dropdown list, it returns false;
                *       if user selects a item form the dropdown list or typed text in dropdown list, it returns true.
                */
                this.inputTextInDropDownList = false;
                /** A value that specifies the input text of the combobox.
                * @type {string}
                * @remarks
                *       When set the text by code, it will not affect the selectedIndex and selectedValue.
                */
                this.text = null;
                /** A value indicating the dropdown element will be append to the body or combobox container.
                * @remarks
                *       If the value is true, the dropdown list will be appended to body element.
                *       else it will append to the combobox container.
                */
                this.ensureDropDownOnBody = true;
                /** This event is triggered when the drop-down list is opened.
                * @event
                */
                this.open = null;
                /** This event is triggered when the drop-down list is closed.
                * @event
                */
                this.close = null;
                /** A value added to the width of the original HTML select element to account
                *   for the scroll bar width of the drop-down list.
                * @remarks
                *       Unit for this value is pixel.
                *       Because the width of the scroll bar may be different between browsers
                *       if wijcombobox is initialized with the width of the HTML select element,
                *       the text may be hidden by the scroll bar of wijcombobox.
                */
                this.selectElementWidthFix = 6;
                /** This event is triggered when a user searches an item in the drop-down list either
                *  by typing in the textbox or by calling the search method of wijcombobox.
                * @event
                * @dataKey {datasource} datasrc The datasource of wijcombobox.
                * @dataKey {string} term The text to search.
                */
                this.search = null;
                /** The event is obsolete event.
                *  A function called when select item is changed.
                * @event
                * @param {Object} e The jQuery.Event object.
                * @param {IselectedEventArgs} data The data with this event.
                */
                this.changed = null;
                /** This event is triggered when the text of the combobox is changed.
                * @event
                * @dataKey {string} oldText The old text of combobox.
                * @dataKey {string} newText The new text of combobox.
                */
                this.textChanged = null;
                /** This event is triggered when the selected index of the combobox is changed.
                * @event
                * @param {Object} e The jQuery.Event object.
                * @param {IselectedEventArgs} data The data with this event.
                */
                this.selectedIndexChanged = null;
                /** A function called when the selected index of the comboBox is about to change.
                *  Cancellable. If return false, the select operation will be canceled.
                * @event
                * @param {Object} e The jQuery.Event object.
                * @param {IselectedEventArgs} data The data with this event.
                */
                this.selectedIndexChanging = null;
                /** A value that determines the object that contains the options of wijlist.*/
                this.listOptions = null;
                /** A value that determines whether to fit the width of combobox to that of the dropdown.
                * @type {boolean}
                */
                this.adjustComboWidth = false;
            }
            return wijcombobox_options;
        })();
        ;
        wijcombobox.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijcombobox_options());
        $.wijmo.registerWidget("wijcombobox", wijcombobox.prototype);

        //prevent jqm's default behavior for <input> markup.
        if ($.mobile && $.mobile.textinput && $.mobile.textinput.initSelector) {
            $.mobile.textinput.initSelector = $.map($.mobile.textinput.initSelector.split(","), function (s) {
                return s + ":not(:jqmData(role='wijcombobox'))";
            }).join(",");
        }

        
    })(wijmo.combobox || (wijmo.combobox = {}));
    var combobox = wijmo.combobox;
})(wijmo || (wijmo = {}));

;
var wijmo;
(function (wijmo) {
    (function (input) {
        /** @ignore */
        var CharType = (function () {
            function CharType() {
                /// <summary>
                ///   Indicates that the character is not of a particular category.
                /// </summary>
                this.OtherChar = 0x0000;
                /// <summary>
                ///   Indicates that the character is a control code.
                /// </summary>
                this.Control = 0x0001;
                /// <summary>
                ///   Indicates that the character is a numeric digit.
                /// </summary>
                this.Numeric = 0x0002;
                /// <summary>
                ///   Indicates that the character is a mathematical symbol.
                /// </summary>
                this.MathSymbol = 0x0003;
                /// <summary>
                ///   Indicates that the character is a symbol.
                /// </summary>
                this.Symbol = 0x0004;
                /// <summary>
                ///   Indicates that the character is a punctuation. ( Open &amp; Close )
                /// </summary>
                this.Punctuation = 0x0005;
                /// <summary>
                ///   Indicates that the character is a space character.
                /// </summary>
                this.Space = 0x0006;
                /// <summary>
                ///   Indicates that the character is an upper case letter.
                /// </summary>
                this.UpperCase = 0x0007;
                /// <summary>
                ///   Indicates that the character is a lower case letter.
                /// </summary>
                this.LowerCase = 0x0008;
                /// <summary>
                ///   Indicates that the character is a Japanese Katakana character.
                /// </summary>
                this.Katakana = 0x0009;
                /// <summary>
                ///   Indicates that the character is a Japanese Hiragana character.
                /// </summary>
                this.Hiragana = 0x000a;
                /// <summary>
                ///   Indicates that the character is a CJK punctuation.
                /// </summary>
                this.FarEastPunctation = 0x000b;
                /// <summary>
                ///   Indicates that the character is a Hangal character.
                /// </summary>
                this.Hangul = 0x000c;
                /// <summary>
                ///   Indicates that the character is of full width.
                /// </summary>
                this.FullWidth = 0x8000;
            }
            return CharType;
        })();
        input.CharType = CharType;

        /** @ignore */
        var CharCategory = (function () {
            function CharCategory() {
                // Min & Max values ----------------------------------
                ///   Represents the smallest possible value of a Char.
                ///   This field is constant.
                this.MinValue = '\u0000';
                ///   Represents the largest possible value of a Char.
                ///   This field is constant.
                this.MaxValue = '\uffff';
                //Full/HalfWidth characters (different cultures)------
                this.ANSISTART = 0x0000;
                this.ANSIEND = 0x00ff;
                this.BOTHWIDTHSTART = 0xff00;
                this.BOTHWIDTHEND = 0xffef;
                this.FULLALPHASTART = 0xff01;
                this.FULLUPPERSTART = 0xff21;
                this.FULLUPPEREND = 0xff3a;
                this.FULLALPHAEND = 0xff5e;
                this.CJKHALFSYMBOLSTART = 0xff61;
                this.CJKHALFSYMBOLEND = 0xff64;
                this.KANAHALFSTART = 0xff65;
                this.KANAHALFEND = 0xff9f;
                this.HANGULHALFSTART = 0xffa0;
                this.HANGULHALFEND = 0xffdc;
                this.FULLSYMBOLSTART = 0xffe0;
                this.FULLSYMBOLEND = 0xffe6;
                this.HALFPUNCTSTART = 0xffe8;
                this.HALFPUNCTEND = 0xffee;
                // Voiced characters (Japanese)------------------------
                this.KATAKANA_VOICED = '\uff9e';
                this.KATAKANA_SEMIVOICED = '\uff9f';
                //Others-----------------------------------------------
                this.Tab = '\u0009';
                this.Space = '\u0020';
                //>>> Static Data (tables) ----------------------------
                // Character Groups...
                ///   Character groups (character codes) based on Unicode 3.1.
                this._charstarts = [
                    '\u0000',
                    '\u0080',
                    '\u0100',
                    '\u0180',
                    '\u0250',
                    '\u02b0',
                    '\u0300',
                    '\u0370',
                    '\u0400',
                    '\u0530',
                    '\u0590',
                    '\u0600',
                    '\u0700',
                    '\u0780',
                    '\u0900',
                    '\u0980',
                    '\u0a00',
                    '\u0a80',
                    '\u0b00',
                    '\u0b80',
                    '\u0c00',
                    '\u0c80',
                    '\u0d00',
                    '\u0d80',
                    '\u0e00',
                    '\u0e80',
                    '\u0f00',
                    '\u1000',
                    '\u10a0',
                    '\u1100',
                    '\u1200',
                    '\u13a0',
                    '\u1400',
                    '\u1680',
                    '\u16a0',
                    '\u1780',
                    '\u1800',
                    '\u1e00',
                    '\u1f00',
                    '\u2000',
                    '\u2070',
                    '\u20a0',
                    '\u20d0',
                    '\u2100',
                    '\u2150',
                    '\u2190',
                    '\u2200',
                    '\u2300',
                    '\u2400',
                    '\u2440',
                    '\u2460',
                    '\u2500',
                    '\u2580',
                    '\u25a0',
                    '\u2600',
                    '\u2700',
                    '\u2800',
                    '\u2e80',
                    '\u2f00',
                    '\u2ff0',
                    '\u3000',
                    '\u3040',
                    '\u30a0',
                    '\u3100',
                    '\u3130',
                    '\u3190',
                    '\u31a0',
                    '\u3200',
                    '\u3300',
                    '\u3400',
                    '\u4e00',
                    '\ua000',
                    '\ua490',
                    '\uac00',
                    '\uf900',
                    '\ufb00',
                    '\ufb50',
                    '\ufe20',
                    '\ufe30',
                    '\ufe50',
                    '\ufe70',
                    '\uff00',
                    '\ufff0'
                ];
                //Character Block Categories...
                ///   Character blocks categorized base on the Unicode standard.
                this.Blocks = [
                    'BASIC_LATIN',
                    'LATIN_1_SUPPLEMENT',
                    'LATIN_EXTENDED_A',
                    'LATIN_EXTENDED_B',
                    'IPA_EXTENSIONS',
                    'SPACING_MODIFIER_LETTERS',
                    'COMBINING_DIACRITICAL_MARKS',
                    'GREEK',
                    'CYRILLIC',
                    'ARMENIAN',
                    'HEBREW',
                    'ARABIC',
                    'SYRIAC',
                    'THAANA',
                    'DEVANAGARI',
                    'BENGALI',
                    'GURMUKHI',
                    'GUJARATI',
                    'ORIYA',
                    'TAMIL',
                    'TELUGU',
                    'KANNADA',
                    'MALAYALAM',
                    'SINHALA',
                    'THAI',
                    'LAO',
                    'TIBETAN',
                    'MYANMAR',
                    'GEORGIAN',
                    'HANGUL_JAMO',
                    'ETHIOPIC',
                    'CHEROKEE',
                    'UNIFIED_CANADIAN_ABORIGINAL_SYLLABIC',
                    'OGHAM',
                    'RUNIC',
                    'KUMER',
                    'MONGOLIAN',
                    'LATIN_EXTENDED_ADDITIONAL',
                    'GREEK_EXTENDED',
                    'GENERAL_PUNCTUATION',
                    'SUPERSCRIPTS_AND_SUBSCRIPTS',
                    'CURRENCY_SYMBOLS',
                    'COMBINING_MARKS_FOR_SYMBOLS',
                    'LETTERLIKE_SYMBOLS',
                    'NUMBER_FORMS',
                    'ARROWS',
                    'MATHEMATICAL_OPERATORS',
                    'MISCELLANEOUS_TECHNICAL',
                    'CONTROL_PICTURES',
                    'OPTICAL_CHARACTER_RECOGNITION',
                    'ENCLOSED_ALPHANUMERICS',
                    'BOX_DRAWING',
                    'BLOCK_ELEMENTS',
                    'GEOMETRIC_SHAPES',
                    'MISCELLANEOUS_SYMBOLS',
                    'DINGBATS',
                    'BRAILLE_PATTERNS',
                    'CJK_RADICALS_SUPPLEMENT',
                    'KANGXI_RADICALS',
                    'IDEOGRAPHIC_DESCRIPTION_CHARACTERS',
                    'CJK_SYMBOLS_AND_PUNCTUATION',
                    'HIRAGANA',
                    'KATAKANA',
                    'BOPOMOFO',
                    'HANGUL_COMPATIBILITY_JAMO',
                    'KANBUN',
                    'BOPOMOFO_EXTENDED',
                    'ENCLOSED_CJK_LETTERS_AND_MONTHS',
                    'CJK_COMPATIBILITY',
                    'CJK_UNIFIED_IDEOGRAPHS_EXTENSION',
                    'CJK_UNIFIED_IDEOGRAPHS',
                    'YI_SYLLABLES',
                    'YI_RADICALS',
                    'HANGUL_SYLLABLES',
                    'CJK_COMPATIBILITY_IDEOGRAPHS',
                    'ALPHABETIC_PRESENTATION_FORMS',
                    'ARABIC_PRESENTATION_FORMS_A',
                    'COMBINING_HALF_MARKS',
                    'CJK_COMPATIBILITY_FORMS',
                    'SMALL_FORM_VARIANTS',
                    'ARABIC_PRESENTATION_FORMS_B',
                    'HALFWIDTH_AND_FULLWIDTH_FORMS',
                    'SPECIALS'
                ];
                // Multi width character block mapping table...
                ///   Table of multi-width character blocks.
                this._fullhalfblocks = [
                    '\uff01',
                    '\uff10',
                    '\uff1a',
                    '\uff21',
                    '\uff3b',
                    '\uff41',
                    '\uff5b',
                    '\uff61',
                    '\uff65',
                    '\uffa0',
                    '\uffe0',
                    '\uffe8'
                ];
                // Half width Katakana map table...
                ///   Mapping table of full width Katakana.
                this._halfkana = [
                    '\u30fb', '\u30f2',
                    '\u30a1', '\u30a3', '\u30a5', '\u30a7', '\u30a9',
                    '\u30e3', '\u30e5', '\u30e7',
                    '\u30c3', '\u30fc',
                    '\u30a2', '\u30a4', '\u30a6', '\u30a8', '\u30aa',
                    '\u30ab', '\u30ad', '\u30af', '\u30b1', '\u30b3',
                    '\u30b5', '\u30b7', '\u30b9', '\u30bb', '\u30bd',
                    '\u30bf', '\u30c1', '\u30c4', '\u30c6', '\u30c8',
                    '\u30ca', '\u30cb', '\u30cc', '\u30cd', '\u30ce',
                    '\u30cf', '\u30d2', '\u30d5', '\u30d8', '\u30db',
                    '\u30de', '\u30df', '\u30e0', '\u30e1', '\u30e2',
                    '\u30e4', '\u30e6', '\u30e8',
                    '\u30e9', '\u30ea', '\u30eb', '\u30ec', '\u30ed',
                    '\u30ef', '\u30f3',
                    '\u3099', '\u309a'
                ];
                // Full width Katakana map table...
                ///   Mapping table of half-width Katakana.
                this._fullkana = [
                    '\uff67', '\uff71', '\uff68', '\uff72', '\uff69', '\uff73',
                    '\uff6a', '\uff74', '\uff6b', '\uff75',
                    '\uff76', '\uff76', '\uff77', '\uff77', '\uff78', '\uff78',
                    '\uff79', '\uff79', '\uff7a', '\uff7a',
                    '\uff7b', '\uff7b', '\uff7c', '\uff7c', '\uff7d', '\uff7d',
                    '\uff7e', '\uff7e', '\uff7f', '\uff7f',
                    '\uff80', '\uff80', '\uff81', '\uff81', '\uff6f', '\uff82',
                    '\uff82', '\uff83', '\uff83', '\uff84', '\uff84',
                    '\uff85', '\uff86', '\uff87', '\uff88', '\uff89',
                    '\uff8a', '\uff8a', '\uff8a', '\uff8b', '\uff8b', '\uff8b',
                    '\uff8c', '\uff8c', '\uff8c', '\uff8d', '\uff8d', '\uff8d',
                    '\uff8e', '\uff8e', '\uff8e',
                    '\uff8f', '\uff90', '\uff91', '\uff92', '\uff93',
                    '\uff6c', '\uff94', '\uff6d', '\uff95', '\uff6e', '\uff96',
                    '\uff97', '\uff98', '\uff99', '\uff9a', '\uff9b',
                    '\uff9c', '\uff9c', '\uff68', '\uff6a', '\uff66', '\uff9d',
                    '\uff73', '\uff76', '\uff79', '\uff9c', '\uff68', '\uff6a',
                    '\uff66',
                    '\uff65', '\uff70'
                ];
                this._fullkanaSmall = [
                    '\uff67', '\uff68', '\uff69', '\uff6a', '\uff6b',
                    '\uff6c', '\uff6d', '\uff6e', '\uff6f'
                ];
                // Voiced (accent) map table (Japanese)...
                ///   Mapping table for accents for the Japanese language.
                this._accentkana = [
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
                    -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
                    -1, 1, -1, 1, 0, -1, 1, -1, 1, -1, 1,
                    0, 0, 0, 0, 0,
                    -3, 1, 2, -3, 1, 2, -3, 1, 2, -3, 1, 2, -3, 1, 2,
                    0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 0,
                    1, 0, 0, 1, 1, 1,
                    1,
                    0, 0
                ];
                // Special quotations for FarEast...
                this._feQuotes = ['\u2018', '\u2019', '\u201c', '\u201d'];
                // Katakana & Hiragana mixed characters (Japanese)...
                this._jpnMixed = ['\u30fc'];
                // Full / Half width special character map table...
                this._jpnSpecialFull = [
                    '\u3000',
                    '\u3001',
                    '\u3002',
                    '\u300c',
                    '\u300d',
                    '\u201c',
                    '\u201d',
                    '\u2018',
                    '\u2019',
                    '\u309b',
                    '\u309c',
                    '\uffe5'
                ];
                this._jpnSpecialHalf = [
                    '\u0020',
                    '\uff64',
                    '\uff61',
                    '\uff62',
                    '\uff63',
                    '\u0022',
                    '\u0022',
                    '\u0027',
                    '\u0027',
                    '\uff9e',
                    '\uff9f',
                    '\u00a5'
                ];
                var _charType = new CharType();
                this._mwtable = [
                    _charType.Symbol | _charType.FullWidth,
                    _charType.Numeric | _charType.FullWidth,
                    _charType.Symbol | _charType.FullWidth,
                    _charType.UpperCase | _charType.FullWidth,
                    _charType.Symbol | _charType.FullWidth,
                    _charType.LowerCase | _charType.FullWidth,
                    _charType.Symbol | _charType.FullWidth,
                    _charType.FarEastPunctation,
                    _charType.Katakana,
                    _charType.Hangul,
                    _charType.Symbol | _charType.FullWidth,
                    _charType.Symbol
                ];
            }
            return CharCategory;
        })();
        input.CharCategory = CharCategory;

        /** @ignore */
        var CharProcess = (function () {
            function CharProcess() {
                this.CharCategory = new CharCategory();
                this.Ctype = new CharType();
            }
            CharProcess.prototype.ToHalfKatakana = function (c) {
                var result = "";
                if (this.IsFullWidth(c)) {
                    if (this.IsKatakana(c)) {
                        var katakana = c;
                        var n = katakana.charCodeAt(0) - (this.CharCategory._charstarts[62].charCodeAt(0) + 1);
                        if (n < 0 || n > 91) {
                            return katakana;
                        }
                        katakana = this.CharCategory._fullkana[n];

                        var accent = this.CharCategory._accentkana[n];

                        if (accent > 0) {
                            //accent == 1 ? this.CharCategory.KATAKANA_VOICED.charCodeAt(0) : this.CharCategory.KATAKANA_SEMIVOICED.charCodeAt(0) ;
                            katakana = katakana + String.fromCharCode(accent == 1 ? this.CharCategory.KATAKANA_VOICED.charCodeAt(0) : this.CharCategory.KATAKANA_SEMIVOICED.charCodeAt(0));
                        }
                        result = katakana;
                    } else if (this.IsHiragana(c)) {
                        var katakana = String.fromCharCode(c.charCodeAt(0) - this.CharCategory._charstarts[61].charCodeAt(0) + this.CharCategory._charstarts[62].charCodeAt(0));
                        var n = katakana.charCodeAt(0) - (this.CharCategory._charstarts[62].charCodeAt(0) + 1);
                        if (n < 0 || n > 91) {
                            return katakana;
                        }
                        katakana = this.CharCategory._fullkana[n];

                        var accent = this.CharCategory._accentkana[n];

                        if (accent > 0) {
                            //accent == 1 ? this.CharCategory.KATAKANA_VOICED.charCodeAt(0) : this.CharCategory.KATAKANA_SEMIVOICED.charCodeAt(0) ;
                            katakana = katakana + String.fromCharCode(accent == 1 ? this.CharCategory.KATAKANA_VOICED.charCodeAt(0) : this.CharCategory.KATAKANA_SEMIVOICED.charCodeAt(0));
                        }
                        result = katakana;
                    }
                } else {
                    if (this.IsKatakana(c)) {
                        result = c;
                    }
                }

                return result;
            };

            CharProcess.prototype.GetCharType = function (c) {
                var ctype = this.Ctype.OtherChar;
                var block = this.BelongTo(c);

                if (c == '\u007f' || ('\u0000' <= c && c <= '\u001f') || ('\u0080' <= c && c <= '\u009f'))
                    return this.Ctype.Control;

                if ('A' <= c && c <= 'Z')
                    return this.Ctype.UpperCase;

                if ('a' <= c && c <= 'z')
                    return this.Ctype.LowerCase;

                if ('0' <= c && c <= '9')
                    return this.Ctype.Numeric;

                //modified by sj
                //the logic that charex call textfilter is wrong
                //	var tFilter = new TextFilter(true,true,"");
                //	if (tFilter.IsSymbol(c))
                //	{
                //		ctype = this.Ctype.Symbol;
                //	}
                if (this.IsFullWidthSymbol(c) || this.IsHalfWidthSymbol(c)) {
                    ctype = this.Ctype.Symbol;
                }

                //end by sj
                if (c.charCodeAt(0) == 8216 || c.charCodeAt(0) == 8217 || c.charCodeAt(0) == 8220 || c.charCodeAt(0) == 8221)
                    ctype = this.Ctype.Punctuation;

                if (c.charCodeAt(0) == 12288)
                    ctype = this.Ctype.Space;

                switch (this.CharCategory.Blocks[block]) {
                    case 'HALFWIDTH_AND_FULLWIDTH_FORMS':
                        return this.MultiWidthDetails(c);
                    case 'KATAKANA':
                        return this.Ctype.Katakana | this.Ctype.FullWidth;
                    case 'HIRAGANA':
                        return this.Ctype.Hiragana | this.Ctype.FullWidth;
                }

                if (this.IsFarEastBlock(block, c))
                    ctype |= this.Ctype.FullWidth;

                return ctype;
            };

            CharProcess.prototype.IsCharOfType = function (c, type) {
                return this.GetCharType(c) == type;
            };

            CharProcess.prototype.IsMultiWidth = function (c) {
                var block = this.BelongTo(c);
                var category = this.CharCategory.Blocks[block];
                return (category == 'KATAKANA' || category == 'CJK_SYMBOLS_AND_PUNCTUATION' || category == 'HALFWIDTH_AND_FULLWIDTH_FORMS' || (category == 'BASIC_LATIN' && c >= '\u0020'));
            };

            CharProcess.prototype.IsFullWidthSymbol = function (c) {
                for (var i = 0; i < CharProcess.FullWidthSymbolArray.length; i++) {
                    if (c === CharProcess.FullWidthSymbolArray[i]) {
                        return true;
                    }
                }
                return false;
            };

            CharProcess.prototype.IsHalfWidthSymbol = function (c) {
                for (var i = 0; i < CharProcess.HalfWidthSymbolArray.length; i++) {
                    if (c === CharProcess.HalfWidthSymbolArray[i]) {
                        return true;
                    }
                }
                return false;
            };

            CharProcess.prototype.IsFullWidth = function (c) {
                if (this.IsFullWidthSymbol(c)) {
                    return true;
                }

                if (this.IsHalfWidthSymbol(c)) {
                    return false;
                }

                var block = this.BelongTo(c);

                var bFullWidth = this.IsFarEastBlock(block, c);
                if (this.CharCategory.Blocks[block] == 'HALFWIDTH_AND_FULLWIDTH_FORMS')
                    bFullWidth = ((this.MultiWidthDetails(c) & this.Ctype.FullWidth) == this.Ctype.FullWidth);

                return bFullWidth;
            };

            CharProcess.prototype.IsSurrogatePair = function (c) {
                if (c.charCodeAt(0) >= '\uD800'.charCodeAt(0) && c.charCodeAt(0) <= '\uDBFF'.charCodeAt(0) && c.charCodeAt(1) >= '\uDC00'.charCodeAt(0) && c.charCodeAt(1) <= '\uDFFF'.charCodeAt(0)) {
                    return true;
                }

                return false;
            };

            CharProcess.prototype.IsSurrogate = function (c) {
                return c != null && ((c.charCodeAt(0) >= '\uD800'.charCodeAt(0)) && c.charCodeAt(0) <= '\uDFFF'.charCodeAt(0));
            };

            CharProcess.prototype.IsOther = function (c) {
                return ((this.GetCharType(c) & ~this.Ctype.FullWidth) == this.Ctype.OtherChar);
            };

            CharProcess.prototype.IsControl = function (c) {
                return ((this.GetCharType(c) & ~this.Ctype.FullWidth) == this.Ctype.Control);
            };

            CharProcess.prototype.IsKatakana = function (c) {
                return ((this.GetCharType(c) & ~this.Ctype.FullWidth) == this.Ctype.Katakana);
            };

            CharProcess.prototype.IsSmallHalfKatakana = function (c) {
                var _halfkanaSmall = new Array('\u30a1', '\u30a3', '\u30a5', '\u30a7', '\u30a9', '\u30e3', '\u30e5', '\u30e7', '\u30c3', '\u30ee');

                var c1 = c;
                if (c.charCodeAt(0) > this.CharCategory.KANAHALFSTART) {
                    c1 = this.CharCategory._halfkana[c.charCodeAt(0) - this.CharCategory.KANAHALFSTART];
                }
                for (var i = 0; i < _halfkanaSmall.length; i++) {
                    if (c1 == _halfkanaSmall[i]) {
                        return true;
                    }
                }
                return false;
            };

            CharProcess.prototype.IsHiragana = function (c) {
                return (((this.GetCharType(c) & ~this.Ctype.FullWidth) == this.Ctype.Hiragana) || (this.CharCategory._jpnMixed[0] == c));
                //--------------------------------------------------------------------------------------------------
            };

            CharProcess.prototype.IsShiftJIS = function (c) {
                //var unicode = c.charCodeAt(0);
                //var offset = Math.floor(unicode / 8);
                //var mod = unicode % 8;
                //var flagString = CharProcess.ShiftJISCode.substr(offset * 2, 2);
                //var binaryString = parseInt(flagString, 16).toString(2);
                //while (binaryString.length < 8)
                //{
                //    binaryString = "0" + binaryString;
                //}
                //if (binaryString.substr(mod, 1) == "1")
                //{
                //    return true;
                //}
                return false;
            };

            CharProcess.prototype.IsJISX0208 = function (c) {
                //var unicode = c.charCodeAt(0);
                //var offset = Math.floor(unicode / 8);
                //var mod = unicode % 8;
                //var flagString = CharProcess.JISX0208Code.substr(offset * 2, 2);
                //var binaryString = parseInt(flagString, 16).toString(2);
                //while (binaryString.length < 8)
                //{
                //    binaryString = "0" + binaryString;
                //}
                //if (binaryString.substr(mod, 1) == "1")
                //{
                //    return true;
                //}
                return false;
            };

            CharProcess.prototype.IsDigit = function (c) {
                return ((this.GetCharType(c) & ~this.Ctype.FullWidth) == this.Ctype.Numeric);
            };

            CharProcess.prototype.IsPunctuation = function (c) {
                return ((this.GetCharType(c) & ~this.Ctype.FullWidth) == this.Ctype.Punctuation);
            };

            CharProcess.prototype.IsMathSymbol = function (c) {
                return ((this.GetCharType(c) & ~this.Ctype.FullWidth) == this.Ctype.MathSymbol);
            };

            CharProcess.prototype.IsSymbol = function (c) {
                return ((this.GetCharType(c) & ~this.Ctype.FullWidth) == this.Ctype.Symbol);
            };

            CharProcess.prototype.IsLower = function (c) {
                return ((this.GetCharType(c) & ~this.Ctype.FullWidth) == this.Ctype.LowerCase);
            };

            CharProcess.prototype.IsUpper = function (c) {
                return ((this.GetCharType(c) & ~this.Ctype.FullWidth) == this.Ctype.UpperCase);
            };

            CharProcess.prototype.IsDigitOrSymbol = function (c) {
                return (this.IsDigit(c) || this.IsMathSymbol(c));
            };

            CharProcess.prototype.IsAlphabet = function (c) {
                return (this.IsUpper(c) || this.IsLower(c));
            };

            CharProcess.prototype.IsAlphaOrDigit = function (c) {
                return (this.IsUpper(c) || this.IsLower(c) || this.IsDigit(c));
            };

            CharProcess.prototype.IsUpperKana = function (c) {
                return !this.IsLowerKana(c);
            };

            CharProcess.prototype.IsLowerKana = function (c) {
                return (CharProcess.LowerKana.search(c) != -1);
            };

            CharProcess.prototype.HasLowerKana = function (c) {
                return (CharProcess.UpperKana.search(c) != -1 || this.IsLowerKana(c));
            };

            CharProcess.prototype.ToUpperKana = function (c) {
                var index = CharProcess.LowerKana.search(c);
                return (index == -1) ? c : CharProcess.UpperKana.substr(index, 1);
            };

            CharProcess.prototype.ToLowerKana = function (c) {
                var index = CharProcess.UpperKana.search(c);
                if (index >= CharProcess.UpperKana.length - 4 && index < CharProcess.UpperKana.length) {
                    return c;
                }

                return (index == -1) ? c : CharProcess.LowerKana.substr(index, 1);
            };

            CharProcess.prototype.ToLower = function (c) {
                if (this.IsUpper(c))
                    return String.fromCharCode(c.charCodeAt(0) + 32);
                return c;
            };

            CharProcess.prototype.ToUpper = function (c) {
                if (this.IsLower(c))
                    return String.fromCharCode(c.charCodeAt(0) - 32);
                return c;
            };

            CharProcess.prototype.IsSpace = function (c) {
                return c == '\u0020' || c === '\u3000';
            };

            CharProcess.prototype.ToFullWidth = function (c) {
                var retObj = { text: "", processedAll: false };
                retObj.text = c;
                retObj.processedAll = false;

                if (c.length == 0)
                    return retObj;

                var c1 = c.substring(0, 1);

                if (this.IsMultiWidth(c1)) {
                    //
                    // Latin basic characters can be directly converted
                    // by making a few shifts...
                    //
                    if (c1 < this.CharCategory._charstarts[1]) {
                        //
                        // Funny why 'space' was left out of this category.
                        //
                        if (c1 == '\u0020') {
                            retObj.text = '\u3000';
                            return retObj;
                        }
                        var temp = '\u0021';
                        retObj.text = String.fromCharCode(c1.charCodeAt(0) - temp.charCodeAt(0) + (this.CharCategory._charstarts[81].charCodeAt(0) + 1)); //Blocks.HALFWIDTH_AND_FULLWIDTH_FORMS
                        return retObj;
                    }

                    //
                    //- pickup a direct map from the table...
                    //
                    if ((this.MultiWidthDetails(c1) & this.Ctype.Katakana) == this.Ctype.Katakana) {
                        if (c1.charCodeAt(0) < this.CharCategory.KANAHALFSTART) {
                            var c2 = this.GetFullHalfWidthSpecialChar(c1, true);
                            retObj.text = (c2 !== "") ? c2 : c1;
                            return retObj;
                        }
                        c1 = this.CharCategory._halfkana[c1.charCodeAt(0) - this.CharCategory.KANAHALFSTART];

                        //
                        // Handle the soundex here....
                        //
                        if (c.length < 2) {
                            retObj.text = c1;
                            return retObj;
                        }

                        var daku = c.charCodeAt(1) - (this.CharCategory.KATAKANA_VOICED.charCodeAt(0) - 1);
                        if (daku == 1 || daku == 2) {
                            retObj.processedAll = true;

                            var accent = this.CharCategory._accentkana[(c1.charCodeAt(0) - (this.CharCategory._charstarts[62].charCodeAt(0) + 1))];

                            if (accent != 0) {
                                if ((Math.abs(accent) & 2) == daku)
                                    c1 = String.fromCharCode(c1.charCodeAt(0) + 1);
                                c1 = String.fromCharCode(c1.charCodeAt(0) + 1);
                            }
                        }

                        //add by sj for bug 2955
                        if (daku == 1 && c1 == '\u30A6') {
                            c1 = '\u30F4';
                        }
                        //end by sj
                    }
                }
                retObj.text = c1;
                return retObj;
                //return c1;
            };

            CharProcess.prototype.ToHalfWidth = function (c) {
                //
                // Need to return only the first character.
                //
                return this.ToHalfWidthEx(c);
            };

            CharProcess.prototype.ToHalfWidthEx = function (c) {
                var ctype = this.GetCharType(c);

                var multiWidth = this.IsMultiWidth(c);

                //
                // First filter out half width characters and characters that
                // are not of CJK groups.
                if ((ctype & this.Ctype.FullWidth) == this.Ctype.FullWidth) {
                    switch (ctype & ~this.Ctype.FullWidth) {
                        case this.Ctype.Punctuation:
                        case this.Ctype.UpperCase:
                        case this.Ctype.LowerCase:
                        case this.Ctype.Symbol:
                        case this.Ctype.Numeric:
                        case this.Ctype.MathSymbol:
                             {
                                var c1 = this.GetFullHalfWidthSpecialChar(c, false);
                                if (c1 !== "")
                                    c = c1;
                                else {
                                    if (multiWidth) {
                                        var temp = '\u0021';

                                        //c = (char)(( c - (_charstarts[(int)Blocks.HALFWIDTH_AND_FULLWIDTH_FORMS] + 1) ) + '\u0021');
                                        c = String.fromCharCode(c.charCodeAt(0) - (this.CharCategory._charstarts[81].charCodeAt(0) + 1) + temp.charCodeAt(0)); //Blocks.HALFWIDTH_AND_FULLWIDTH_FORMS
                                    }
                                }
                            }
                            break;

                        case this.Ctype.Katakana:
                             {
                                var n = c.charCodeAt(0) - (this.CharCategory._charstarts[62].charCodeAt(0) + 1);
                                if (n < 0 || n > 91) {
                                    return c;
                                }
                                c = this.CharCategory._fullkana[n];

                                var accent = this.CharCategory._accentkana[n];

                                if (accent > 0) {
                                    //accent == 1 ? this.CharCategory.KATAKANA_VOICED.charCodeAt(0) : this.CharCategory.KATAKANA_SEMIVOICED.charCodeAt(0) ;
                                    c = c + String.fromCharCode(accent == 1 ? this.CharCategory.KATAKANA_VOICED.charCodeAt(0) : this.CharCategory.KATAKANA_SEMIVOICED.charCodeAt(0));
                                    return c;
                                }
                                //return new char[] { c, accent == 1 ? KATAKANA_VOICED : KATAKANA_SEMIVOICED };
                            }
                            break;

                        case this.Ctype.Space:
                            c = '\u0020';
                            break;

                        case this.Ctype.Hangul:
                            break;
                    }
                }

                return c;
            };
            CharProcess.prototype.ToKatakana = function (c) {
                //
                // Simply return the character if it isn't a hiragana.
                //
                if (!this.IsCharOfType(c, this.Ctype.Hiragana | this.Ctype.FullWidth))
                    return c;

                //
                // Need to handle special characters here...
                //
                var c1 = this.GetFullHalfWidthSpecialChar(c, false);

                //			if( c == '\u309b' || c == '\u309c' )
                //				return (char)('\uff9e' + (c - '\u309b'));
                if (c1 !== "")
                    return c1;

                //return (char)( c - _charstarts[(int)Blocks.HIRAGANA] + _charstarts[(int)Blocks.KATAKANA] );
                return String.fromCharCode(c.charCodeAt(0) - this.CharCategory._charstarts[61].charCodeAt(0) + this.CharCategory._charstarts[62].charCodeAt(0));
            };

            CharProcess.prototype.ToHiragana = function (c) {
                //
                // Simply return the character if it isn't a hiragana.
                if (!this.IsKatakana(c))
                    return c;

                // Convert to fullwidth Katakana.
                if (!this.IsFullWidth(c))
                    c = this.ToFullWidth(c).text;

                //validate
                if (!this.IsCharOfType(c, this.Ctype.Katakana | this.Ctype.FullWidth))
                    return c;

                //
                // Some fullwidth Katakana characters can't be expressed in Hiragaga
                // so mask it out.
                //
                //modified by sj for NKOI-8C7E84AA2
                //if (c >= '\u30f6' && c <= '\u30ff')
                //	return c;
                if (c >= '\u30f7' && c <= '\u30ff')
                    return c;

                if (c == '\u30f5')
                    return '\u304b';
                if (c == '\u30f6')
                    return '\u3051';

                //end by sj
                //return (char)( c - _charstarts[(int)Blocks.KATAKANA] + _charstarts[(int)Blocks.HIRAGANA] );
                return String.fromCharCode(c.charCodeAt(0) + this.CharCategory._charstarts[61].charCodeAt(0) - this.CharCategory._charstarts[62].charCodeAt(0));
            };

            CharProcess.prototype.ToBigHalfKatakana = function (c) {
                if (!this.IsSmallHalfKatakana(c))
                    return c;

                var c1 = this.CharCategory._halfkana[c.charCodeAt(0) - this.CharCategory.KANAHALFSTART];
                c1 = String.fromCharCode(c1.charCodeAt(0) + 1);
                return c1;
            };

            CharProcess.prototype.BelongTo = function (c) {
                var bottom = 0;
                var top = 83;
                var current = top >> 1;

                while (top - bottom > 1) {
                    if (c >= this.CharCategory._charstarts[current])
                        bottom = current;
                    else
                        top = current;
                    current = (top + bottom) >> 1;
                }

                return current;
            };

            CharProcess.prototype.MultiWidthDetails = function (c) {
                var bottom = 0;
                var top = this.CharCategory._fullhalfblocks.length;
                var current = top >> 1;

                while (top - bottom > 1) {
                    if (c >= this.CharCategory._fullhalfblocks[current])
                        bottom = current;
                    else
                        top = current;
                    current = (top + bottom) >> 1;
                }
                return this.CharCategory._mwtable[current];
            };

            CharProcess.prototype.IsFarEastBlock = function (block, c) {
                switch (this.CharCategory.Blocks[block]) {
                    case 'CJK_COMPATIBILITY':
                    case 'CJK_COMPATIBILITY_FORMS':
                    case 'CJK_COMPATIBILITY_IDEOGRAPHS':
                    case 'CJK_RADICALS_SUPPLEMENT':
                    case 'CJK_SYMBOLS_AND_PUNCTUATION':
                    case 'CJK_UNIFIED_IDEOGRAPHS':
                    case 'CJK_UNIFIED_IDEOGRAPHS_EXTENSION':
                    case 'HALFWIDTH_AND_FULLWIDTH_FORMS':
                    case 'BOPOMOFO':
                    case 'BOPOMOFO_EXTENDED':
                    case 'HIRAGANA':
                    case 'KATAKANA':
                    case 'KANBUN':
                    case 'HANGUL_COMPATIBILITY_JAMO':
                    case 'HANGUL_JAMO':
                    case 'HANGUL_SYLLABLES':
                        return true;

                    default:
                        for (var i = 0; i < this.CharCategory._feQuotes.length; i++) {
                            if (c == this.CharCategory._feQuotes[i]) {
                                return true;
                            }
                        }

                        if (c.charCodeAt(0) > 255) {
                            return true;
                        }

                        if (c.charCodeAt(0) == 8216 || c.charCodeAt(0) == 8217 || c.charCodeAt(0) == 8220 || c.charCodeAt(0) == 8221)
                            return true;

                        break;
                }
                return false;
            };

            CharProcess.prototype.GetFullHalfWidthSpecialChar = function (c, toFull) {
                if (toFull == true) {
                    var srctable = this.CharCategory._jpnSpecialHalf;
                    var desttable = this.CharCategory._jpnSpecialFull;
                } else {
                    var srctable = this.CharCategory._jpnSpecialFull;
                    var desttable = this.CharCategory._jpnSpecialHalf;
                }

                var found = -1;
                var tempIndex = 0;
                while (tempIndex < srctable.length) {
                    if (srctable[tempIndex] == c) {
                        found = tempIndex;
                        break;
                    }
                    tempIndex++;
                }

                if (found != -1) {
                    if (tempIndex < desttable.length) {
                        return desttable[tempIndex];
                    }
                }
                return "";
            };
            CharProcess.LowerKana = "\u3041\u3043\u3045\u3047\u3049\u3063\u3083\u3085\u3087\u308e\u30a1\u30a3\u30a5\u30a7\u30a9\u30c3\u30e3\u30e5\u30e7\u30ee\uff67\uff68\uff69\uff6a\uff6b\uff6c\uff6d\uff6e\uff6f\u30F5\u30F6\u3095\u3096";
            CharProcess.UpperKana = "\u3042\u3044\u3046\u3048\u304a\u3064\u3084\u3086\u3088\u308f\u30a2\u30a4\u30a6\u30a8\u30aa\u30c4\u30e4\u30e6\u30e8\u30ef\uff71\uff72\uff73\uff74\uff75\uff94\uff95\uff96\uff82\u30AB\u30B1\u304B\u3051";

            CharProcess.FullWidthSymbolArray = [
                '\u3001',
                '\u3002',
                '\uFF0C',
                '\uFF0E',
                '\u30FB',
                '\uFF1A',
                '\uFF1B',
                '\uFF1F',
                '\uFF01',
                '\u309B',
                '\u309C',
                '\u00B4',
                '\uFF40',
                '\u00A8',
                '\uFF3E',
                '\uFFE3',
                '\uFF3F',
                '\u30FD',
                '\u30FE',
                '\u309D',
                '\u309E',
                '\u3003',
                '\u4EDD',
                '\u3005',
                '\u3006',
                '\u3007',
                '\u30FC',
                '\u2014',
                '\u2010',
                '\uFF0F',
                '\u301C',
                '\u2016',
                '\uFF5C',
                '\u2026',
                '\u2025',
                '\u2018',
                '\u2019',
                '\u201C',
                '\u201D',
                '\uFF08',
                '\uFF09',
                '\u3014',
                '\u3015',
                '\uFF3B',
                '\uFF3D',
                '\uFF5B',
                '\uFF5D',
                '\u3008',
                '\u3009',
                '\u300A',
                '\u300B',
                '\u300C',
                '\u300D',
                '\u300E',
                '\u300F',
                '\u3010',
                '\u3011',
                '\uFF0B',
                '\u2212',
                '\u00B1',
                '\u00D7',
                '\u00F7',
                '\uFF1D',
                '\u2260',
                '\uFF1C',
                '\uFF1E',
                '\u2266',
                '\u2267',
                '\u221E',
                '\u2234',
                '\u2642',
                '\u2640',
                '\u00B0',
                '\u2032',
                '\u2033',
                '\u2103',
                '\uFFE5',
                '\uFF04',
                '\u00A2',
                '\u00A3',
                '\uFF05',
                '\uFF03',
                '\uFF06',
                '\uFF0A',
                '\uFF20',
                '\u00A7',
                '\u2606',
                '\u2605',
                '\u25CB',
                '\u25CF',
                '\u25CE',
                '\u25C7',
                '\u25C6',
                '\u25A1',
                '\u25A0',
                '\u25B3',
                '\u25B2',
                '\u25BD',
                '\u25BC',
                '\u203B',
                '\u3012',
                '\u2192',
                '\u2190',
                '\u2191',
                '\u2193',
                '\u3013',
                '\uFF07',
                '\uFF02',
                '\uFF0D',
                '\u3033',
                '\u3034',
                '\u3035',
                '\u303B',
                '\u303C',
                '\u30FF',
                '\u309F',
                '\u2208',
                '\u220B',
                '\u2286',
                '\u2287',
                '\u2282',
                '\u2283',
                '\u222A',
                '\u2229',
                '\u2284',
                '\u2285',
                '\u228A',
                '\u228B',
                '\u2209',
                '\u2205',
                '\u2305',
                '\u2306',
                '\u2227',
                '\u2228',
                '\u00AC',
                '\u21D2',
                '\u21D4',
                '\u2200',
                '\u2203',
                '\u2295',
                '\u2296',
                '\u2297',
                '\u2225',
                '\u2226',
                '\u2985',
                '\u2986',
                '\u3018',
                '\u3019',
                '\u3016',
                '\u3017',
                '\u2220',
                '\u22A5',
                '\u2312',
                '\u2202',
                '\u2207',
                '\u2261',
                '\u2252',
                '\u226A',
                '\u226B',
                '\u221A',
                '\u223D',
                '\u221D',
                '\u2235',
                '\u222B',
                '\u222C',
                '\u2262',
                '\u2243',
                '\u2245',
                '\u2248',
                '\u2276',
                '\u2277',
                '\u2194',
                '\u212B',
                '\u2030',
                '\u266F',
                '\u266D',
                '\u266A',
                '\u2020',
                '\u2021',
                '\u00B6',
                '\u266E',
                '\u266B',
                '\u266C',
                '\u2669',
                '\u25EF',
                '\uFF3C',
                '\uFF5E',
                '\uFFE0',
                '\uFFE1',
                '\uFFE2',
                '\u2015'
            ];

            CharProcess.HalfWidthSymbolArray = [
                '\u005C',
                '\u007E',
                '\u0021',
                '\u0022',
                '\u0023',
                '\u0024',
                '\u0025',
                '\u0026',
                '\u0027',
                '\u0028',
                '\u0029',
                '\u002A',
                '\u002B',
                '\u002C',
                '\u002D',
                '\u002E',
                '\u002F',
                '\u003A',
                '\u003B',
                '\u003C',
                '\u003D',
                '\u003E',
                '\u003F',
                '\u0040',
                '\u005B',
                '\u005D',
                '\u005E',
                '\u005F',
                '\u0060',
                '\u007B',
                '\u007C',
                '\u007D',
                '\uFF61',
                '\uFF62',
                '\uFF63',
                '\uFF64',
                '\uFF65',
                '\u00A1',
                '\u00A4',
                '\u00A5'
            ];

            CharProcess.CharEx = new CharProcess();
            return CharProcess;
        })();
        input.CharProcess = CharProcess;
    })(wijmo.input || (wijmo.input = {}));
    var input = wijmo.input;
})(wijmo || (wijmo = {}));
;
var wijmo;
(function (wijmo) {
    (function (input) {
        /** @ignore */
        var CharInfo = (function () {
            function CharInfo() {
            }
            CharInfo.Getbyte64 = function (s, i) {
                var idx = CharInfo.ALPHA.indexOf(s.charAt(i));
                if (idx == -1) {
                    throw "Cannot decode base64";
                }
                return idx;
            };
            CharInfo.Decode = function (s) {
                if (window.atob !== undefined) {
                    return window.atob(s);
                }

                // convert to string
                s = "" + s;
                var getbyte64 = CharInfo.Getbyte64;
                var pads, i, b10;
                var imax = s.length;
                if (imax == 0) {
                    return s;
                }

                if (imax % 4 != 0) {
                    throw "Cannot decode base64";
                }

                pads = 0;
                if (s.charAt(imax - 1) == CharInfo.PADCHAR) {
                    pads = 1;
                    if (s.charAt(imax - 2) == CharInfo.PADCHAR) {
                        pads = 2;
                    }

                    // either way, we want to ignore this last block
                    imax -= 4;
                }

                var x = [];
                for (i = 0; i < imax; i += 4) {
                    b10 = (getbyte64(s, i) << 18) | (getbyte64(s, i + 1) << 12) | (getbyte64(s, i + 2) << 6) | getbyte64(s, i + 3);
                    x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 0xff, b10 & 0xff));
                }

                switch (pads) {
                    case 1:
                        b10 = (getbyte64(s, i) << 18) | (getbyte64(s, i + 1) << 12) | (getbyte64(s, i + 2) << 6);
                        x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 0xff));
                        break;
                    case 2:
                        b10 = (getbyte64(s, i) << 18) | (getbyte64(s, i + 1) << 12);
                        x.push(String.fromCharCode(b10 >> 16));
                        break;
                }
                return x.join('');
            };

            CharInfo.prototype.getbyte = function (s, i) {
                var x = s.charCodeAt(i);
                if (x > 255) {
                    throw "INVALID_CHARACTER_ERR: DOM Exception 5";
                }
                return x;
            };

            CharInfo.DecodeCharInfo = function () {
                var str = CharInfo.Decode(CharInfo._base64CharInfo);
                var numArr = [];
                var i = 0;
                for (i = 0; i < str.length; i += 2) {
                    var num = (str.charCodeAt(i + 1) * 256) + str.charCodeAt(i);
                    numArr.push(num);
                }
                var tempResult = [];
                for (i = 0; i < numArr.length; i++) {
                    if (numArr[i] != 0xfffe) {
                        tempResult.push(numArr[i]);
                    } else {
                        var number = numArr[i + 1];
                        for (var j = 1; j < number; j++) {
                            tempResult.push(numArr[i - 1]);
                        }
                        i++;
                    }
                }
                for (i = 0; i < tempResult.length; i += 2) {
                    var val = (tempResult[i + 1] * 65536) + tempResult[i];
                    CharInfo._charInfo.push(val);
                }
            };

            CharInfo.GetByte = function (index) {
                if (CharInfo._charInfo.length === 0) {
                    CharInfo.DecodeCharInfo();
                }
                var i = Math.floor(index / 4);
                var j = index % 4;
                var value = CharInfo._charInfo[i];
                switch (j) {
                    case 0:
                        return value & 0xff;
                    case 1:
                        return (value >> 8) & 0xff;
                    case 2:
                        return (value >> 16) & 0xff;
                    case 3:
                        return (value >> 24) & 0xff;
                }
            };

            CharInfo.GetShortValue = function (index) {
                var i = CharInfo.GetByte(index);
                var j = CharInfo.GetByte(index + 1);
                return j * 256 + i;
            };

            CharInfo.GetIntValue = function (index) {
                var a = CharInfo.GetByte(index);
                var b = CharInfo.GetByte(index + 1);
                var c = CharInfo.GetByte(index + 2);
                var d = CharInfo.GetByte(index + 3);
                return d * 65535 * 256 + c * 65535 + b * 256 + a;
            };
            CharInfo.PADCHAR = "=";
            CharInfo.ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';

            CharInfo._charInfo = [];

            CharInfo._base64CharInfo = " ";
            return CharInfo;
        })();
        input.CharInfo = CharInfo;

        /** @ignore */
        var CharUnicodeInfo = (function () {
            function CharUnicodeInfo() {
            }
            CharUnicodeInfo.InitTable = function () {
                CharUnicodeInfo.globalizationResourceBytePtr = 0;
                CharUnicodeInfo.headerPtr = CharUnicodeInfo.globalizationResourceBytePtr;
                CharUnicodeInfo.s_pCategoryLevel1Index = CharInfo.GetIntValue(CharUnicodeInfo.globalizationResourceBytePtr + 40);
                CharUnicodeInfo.s_pCategoriesValue = CharInfo.GetIntValue(CharUnicodeInfo.globalizationResourceBytePtr + 0x2c);
                CharUnicodeInfo.s_pNumericLevel1Index = CharInfo.GetIntValue(CharUnicodeInfo.globalizationResourceBytePtr + 0x30);
                CharUnicodeInfo.s_pNumericValues = CharInfo.GetIntValue(CharUnicodeInfo.globalizationResourceBytePtr + 0x38);
                CharUnicodeInfo.s_pDigitValues = CharInfo.GetIntValue(CharUnicodeInfo.globalizationResourceBytePtr + 0x34);
            };

            CharUnicodeInfo.InternalConvertToUtf32 = function (s, index, charLength) {
                charLength.length = 1;
                if (index < (s.length - 1)) {
                    var num = s.charCodeAt(index) - 0xd800;
                    if ((num >= 0) && (num <= 0x3ff)) {
                        var num2 = s.charCodeAt(index + 1) - 0xdc00;
                        if ((num2 >= 0) && (num2 <= 0x3ff)) {
                            charLength.length++;
                            return (((num * 0x400) + num2) + 0x10000);
                        }
                    }
                }
                return s.charCodeAt(index);
            };

            CharUnicodeInfo.InternalGeteCategoryValue = function (ch, offset) {
                if (offset === undefined || offset === null) {
                    offset = 0;
                }
                var num = CharInfo.GetShortValue(CharUnicodeInfo.s_pCategoryLevel1Index + 2 * (ch >> 8));
                num = CharInfo.GetShortValue(CharUnicodeInfo.s_pCategoryLevel1Index + 2 * (num + ((ch >> 4) & 15)));
                var numPtr = CharUnicodeInfo.s_pCategoryLevel1Index + 2 * num;
                var num2 = CharInfo.GetByte(numPtr + (ch & 15));
                return CharInfo.GetByte(CharUnicodeInfo.s_pCategoriesValue + (num2 * 2) + offset);
            };

            CharUnicodeInfo.InternalGetUnicodeCategory = function (str, index, charLength) {
                var utf32 = CharUnicodeInfo.InternalConvertToUtf32(str, index, charLength);

                return CharUnicodeInfo.InternalGeteCategoryValue(utf32, 0);
            };

            CharUnicodeInfo.IsCombiningCategory = function (uc) {
                if ((uc !== 5 /* NonSpacingMark */) && (uc !== 6 /* SpacingCombiningMark */)) {
                    return (uc === 7 /* EnclosingMark */);
                }
                return true;
            };
            return CharUnicodeInfo;
        })();
        input.CharUnicodeInfo = CharUnicodeInfo;

        CharUnicodeInfo.InitTable();

        /** @ignore */
        (function (UnicodeCategory) {
            UnicodeCategory[UnicodeCategory["ClosePunctuation"] = 0x15] = "ClosePunctuation";
            UnicodeCategory[UnicodeCategory["ConnectorPunctuation"] = 0x12] = "ConnectorPunctuation";
            UnicodeCategory[UnicodeCategory["Control"] = 14] = "Control";
            UnicodeCategory[UnicodeCategory["CurrencySymbol"] = 0x1a] = "CurrencySymbol";
            UnicodeCategory[UnicodeCategory["DashPunctuation"] = 0x13] = "DashPunctuation";
            UnicodeCategory[UnicodeCategory["DecimalDigitNumber"] = 8] = "DecimalDigitNumber";
            UnicodeCategory[UnicodeCategory["EnclosingMark"] = 7] = "EnclosingMark";
            UnicodeCategory[UnicodeCategory["FinalQuotePunctuation"] = 0x17] = "FinalQuotePunctuation";
            UnicodeCategory[UnicodeCategory["Format"] = 15] = "Format";
            UnicodeCategory[UnicodeCategory["InitialQuotePunctuation"] = 0x16] = "InitialQuotePunctuation";
            UnicodeCategory[UnicodeCategory["LetterNumber"] = 9] = "LetterNumber";
            UnicodeCategory[UnicodeCategory["LineSeparator"] = 12] = "LineSeparator";
            UnicodeCategory[UnicodeCategory["LowercaseLetter"] = 1] = "LowercaseLetter";
            UnicodeCategory[UnicodeCategory["MathSymbol"] = 0x19] = "MathSymbol";
            UnicodeCategory[UnicodeCategory["ModifierLetter"] = 3] = "ModifierLetter";
            UnicodeCategory[UnicodeCategory["ModifierSymbol"] = 0x1b] = "ModifierSymbol";
            UnicodeCategory[UnicodeCategory["NonSpacingMark"] = 5] = "NonSpacingMark";
            UnicodeCategory[UnicodeCategory["OpenPunctuation"] = 20] = "OpenPunctuation";
            UnicodeCategory[UnicodeCategory["OtherLetter"] = 4] = "OtherLetter";
            UnicodeCategory[UnicodeCategory["OtherNotAssigned"] = 0x1d] = "OtherNotAssigned";
            UnicodeCategory[UnicodeCategory["OtherNumber"] = 10] = "OtherNumber";
            UnicodeCategory[UnicodeCategory["OtherPunctuation"] = 0x18] = "OtherPunctuation";
            UnicodeCategory[UnicodeCategory["OtherSymbol"] = 0x1c] = "OtherSymbol";
            UnicodeCategory[UnicodeCategory["ParagraphSeparator"] = 13] = "ParagraphSeparator";
            UnicodeCategory[UnicodeCategory["PrivateUse"] = 0x11] = "PrivateUse";
            UnicodeCategory[UnicodeCategory["SpaceSeparator"] = 11] = "SpaceSeparator";
            UnicodeCategory[UnicodeCategory["SpacingCombiningMark"] = 6] = "SpacingCombiningMark";
            UnicodeCategory[UnicodeCategory["Surrogate"] = 0x10] = "Surrogate";
            UnicodeCategory[UnicodeCategory["TitlecaseLetter"] = 2] = "TitlecaseLetter";
            UnicodeCategory[UnicodeCategory["UppercaseLetter"] = 0] = "UppercaseLetter";
        })(input.UnicodeCategory || (input.UnicodeCategory = {}));
        var UnicodeCategory = input.UnicodeCategory;

        /** @ignore */
        var StringInfo = (function () {
            function StringInfo() {
            }
            StringInfo.GetNextTextElement = function (str, index, ref) {
                var num2;
                if (str == null) {
                    throw "ArgumentNullException";
                }
                var length = str.length;
                if ((index < 0) || (index >= length)) {
                    if (index != length) {
                        throw "ArgumentOutOfRangeException";
                    }
                    return "";
                }
                var charLengh = {};
                var ucCurrent = CharUnicodeInfo.InternalGetUnicodeCategory(str, index, charLengh);
                num2 = charLengh.length;
                var elementLen = StringInfo.GetCurrentTextElementLen(str, index, length, ucCurrent, num2, ref);
                ref.length = elementLen;
                return str.substr(index, elementLen);
            };
            StringInfo.GetCurrentTextElementLen = function (str, index, len, ucCurrent, currentCharCount, ref) {
                var num;
                if ((index + currentCharCount) === len) {
                    return currentCharCount;
                }
                var charLength = {};
                var uc = CharUnicodeInfo.InternalGetUnicodeCategory(str, index + currentCharCount, charLength);
                num = charLength.length;
                if (((!CharUnicodeInfo.IsCombiningCategory(uc) || CharUnicodeInfo.IsCombiningCategory(ucCurrent)) || ((ucCurrent === 15 /* Format */) || (ucCurrent === 14 /* Control */))) || ((ucCurrent === 29 /* OtherNotAssigned */) || (ucCurrent === 16 /* Surrogate */))) {
                    var num3 = currentCharCount;
                    ref.ucCurrent = uc;
                    ref.currentCharCount = num;
                    return num3;
                }
                var num2 = index;
                index += currentCharCount + num;
                while (index < len) {
                    var charLength = {};
                    uc = CharUnicodeInfo.InternalGetUnicodeCategory(str, index, charLength);
                    num = charLength.length;
                    if (!CharUnicodeInfo.IsCombiningCategory(uc)) {
                        ref.ucCurrent = uc;
                        ref.currentCharCount = num;
                        break;
                    }
                    index += num;
                }
                return (index - num2);
            };

            StringInfo.GetTextElement = function (str) {
                var result = [];
                var index = 0;
                while (index < str.length) {
                    var ref = {};
                    var element = StringInfo.GetNextTextElement(str, index, ref);
                    result.push(element);
                    index += ref.length;
                }
                return result;
            };
            return StringInfo;
        })();
        input.StringInfo = StringInfo;

        /** @ignore */
        var StringCache = (function () {
            function StringCache() {
            }
            StringCache.AddElementCache = function (str, element) {
                if (StringCache.TextElementCacheCount > 500) {
                    StringCache.TextElementCache = {};
                    StringCache.TextElementCacheCount = 0;
                }

                StringCache.TextElementCache[str] = element;
                StringCache.TextElementCacheCount++;
            };
            StringCache.TextElementCache = {};
            StringCache.TextElementCacheCount = 0;
            return StringCache;
        })();
        input.StringCache = StringCache;

        /** @ignore */
        String.prototype.GetStandardPosition = function (position, start) {
            this.CreateSurrogateArray();
            var newValue = position;
            if (StringCache.TextElementArray !== null && position > 0) {
                var maxIndex = Math.min(position, StringCache.TextElementArray.length);
                var totalElementSize = 0;
                for (var i = 0; i < maxIndex; i++) {
                    totalElementSize += StringCache.TextElementArray[i].length;
                }
                newValue = totalElementSize;
            }
            return newValue;
        };

        /** @ignore */
        String.prototype.CreateSurrogateArray = function () {
            if (StringCache.TextElementArray === undefined || StringCache._InnerValue.toString() != this.toString()) {
                StringCache._InnerValue = this;

                //save position of surrogate pair
                var elementCol = StringCache.TextElementCache[this];
                if (elementCol === undefined) {
                    elementCol = StringInfo.GetTextElement(this);

                    // Improve performance.
                    StringCache.AddElementCache(this, elementCol);
                }
                if (elementCol.length === this.length) {
                    StringCache.TextElementArray = null;
                } else {
                    StringCache.TextElementArray = elementCol;
                    StringCache.MultiCharExit = false;
                    for (var i = 0; i < elementCol.length; i++) {
                        if (elementCol[i].length > 2) {
                            StringCache.MultiCharExit = true;
                            break;
                        }
                    }
                }
            }
        };

        /** @ignore */
        String.prototype.GetLength = function () {
            this.CreateSurrogateArray();
            var newLength = this.length;
            if (StringCache.TextElementArray !== null) {
                newLength = StringCache.TextElementArray.length;
            }

            return newLength;
        };

        /** @ignore */
        String.prototype.Substring = function (start, end) {
            this.CreateSurrogateArray();

            if (start >= end) {
                return "";
            }
            var newValue = this.substring(start, end);
            if (StringCache.TextElementArray !== null) {
                start = Math.max(0, start);
                end = Math.min(StringCache.TextElementArray.length, end);
                var result = [];
                for (var i = start; i < end; i++) {
                    result.push(StringCache.TextElementArray[i]);
                }
                newValue = result.join("");
            }

            return newValue;
        };

        /** @ignore */
        String.prototype.IndexOf = function (findtext, startindex) {
            this.CreateSurrogateArray();

            var newValue = this.indexOf(findtext, startindex);
            if (StringCache.TextElementArray !== null && newValue > 0) {
                var totalLength = 0;
                for (var i = 0; i < StringCache.TextElementArray.length; i++) {
                    totalLength += StringCache.TextElementArray[i].length;
                    if (totalLength == newValue) {
                        newValue = i + 1;
                        break;
                    }
                }
            }

            if (StringCache.TextElementArray !== null && newValue >= 0) {
                if (this.Substring(newValue, newValue + findtext.GetLength()).length != findtext.length) {
                    newValue = -1;
                }
            }
            return newValue;
        };

        /** @ignore */
        String.prototype.LastIndexOf = function (text) {
            this.CreateSurrogateArray();
            var newValue = this.lastIndexOf(text);
            if (StringCache.TextElementArray !== null && newValue > 0) {
                var totalLength = 0;
                for (var i = 0; i < StringCache.TextElementArray.length; i++) {
                    totalLength += StringCache.TextElementArray[i];
                    if (totalLength == newValue) {
                        newValue = i + 1;
                        break;
                    }
                }
            }

            if (StringCache.TextElementArray !== null && newValue >= 0) {
                if (this.Substring(newValue, newValue + text.GetLength()).length != text.length) {
                    newValue = -1;
                }
            }
            return newValue;
        };

        /** @ignore */
        String.prototype.CharAt = function (position) {
            this.CreateSurrogateArray();
            var newValue = this.charAt(position);
            if (StringCache.TextElementArray !== null) {
                if (position >= 0 && position < StringCache.TextElementArray.length) {
                    newValue = StringCache.TextElementArray[position];
                } else {
                    newValue = "";
                }
            }

            return newValue;
        };

        /** @ignore */
        String.prototype.startWith = function (str) {
            if (str == null || str == "" || this.length == 0 || str.length > this.length)
                return false;
            if (this.substr(0, str.length) == str)
                return true;
            else
                return false;
        };

        /** @ignore */
        String.prototype.IsNulOrEmpty = function (str) {
            return str == null || str == "";
        };
    })(wijmo.input || (wijmo.input = {}));
    var input = wijmo.input;
})(wijmo || (wijmo = {}));

;
;
/// <reference path="../external/declarations/globalize.d.ts"/>
/// <reference path="../Base/jquery.wijmo.widget.ts"/>
/// <reference path="../wijpopup/jquery.wijmo.wijpopup.ts"/>
/// <reference path="../wijlist/jquery.wijmo.wijlist.ts"/>
/// <reference path="../wijsuperpanel/jquery.wijmo.wijsuperpanel.ts"/>
/// <reference path="jquery.wijmo.wijcharex.ts" />
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*globals Globalize window jQuery wijInputResult document*/
    (function (input) {
        var $ = jQuery, jqKeyCode = wijmo.getKeyCodeEnum();

        /** @widget */
        var wijinputcore = (function (_super) {
            __extends(wijinputcore, _super);
            function wijinputcore() {
                _super.apply(this, arguments);
                this._wasPopupShowing = false;
                this._imeCompostiing = false;
                this._blurTimeout = null;
                this._boundMouseWheel = false;
                this._blockNextTriggerClickedEvent = false;
            }
            wijinputcore.prototype._elemWithClasses = function (elem, classes) {
                if (typeof classes === "undefined") { classes = []; }
                return $(elem).addClass(classes.join(" "));
            };
            wijinputcore.prototype._divWithClasses = function () {
                var classes = [];
                for (var _i = 0; _i < (arguments.length - 0); _i++) {
                    classes[_i] = arguments[_i + 0];
                }
                return this._elemWithClasses("<div/>", classes);
            };
            wijinputcore.prototype._spanWithClasses = function () {
                var classes = [];
                for (var _i = 0; _i < (arguments.length - 0); _i++) {
                    classes[_i] = arguments[_i + 0];
                }
                return this._elemWithClasses("<span/>", classes);
            };

            wijinputcore.prototype._horizontalBorderWidth = function (elem) {
                return elem.leftBorderWidth() + elem.rightBorderWidth();
            };
            wijinputcore.prototype._verticalBorderWidth = function (elem) {
                return elem.topBorderWidth() + elem.bottomBorderWidth();
            };
            wijinputcore.prototype._create = function () {
                var _this = this;
                try  {
                    var focused = document.activeElement == this.element[0];
                } catch (e) {
                }

                var hBorder = this._horizontalBorderWidth(this.element);
                var vBorder = this._verticalBorderWidth(this.element);
                if (this.element[0].tagName.toLowerCase() !== 'input' && this.element[0].tagName.toLowerCase() !== 'textarea') {
                    throw "Target element is not a INPUT";
                }

                this._creationDate = new Date();

                // enable touch support:
                if (window.wijmoApplyWijTouchUtilEvents) {
                    $ = window.wijmoApplyWijTouchUtilEvents($);
                }

                if (this.element.is(":hidden") && this.element.wijAddVisibilityObserver) {
                    this.element.wijAddVisibilityObserver(function () {
                        _this._destroy();
                        _this._create();
                        if (_this.element.wijRemoveVisibilityObserver) {
                            _this.element.wijRemoveVisibilityObserver();
                        }
                    }, "wijinput");
                }

                this.element.data("widgetName", this.widgetName);

                //$.effects.save(this.element, ['width', 'height']);
                if ($.effects && $.effects.save) {
                    $.effects.save(this.element, ['width', 'height']);
                } else if ($.save) {
                    $.save(this.element, ['width', 'height']);
                }

                var wijCSS = this.options.wijCSS;
                this.element.wrap("<div><span/></div");
                this.wrapper = this.element.parent();
                this.outerDiv = this.wrapper.parent();
                this.outerDiv.addClass([wijCSS.wijinput, wijCSS.widget, wijCSS.helperClearFix, wijCSS.stateDefault, wijCSS.cornerAll].join(" "));
                this.wrapper.addClass(wijCSS.wijinputWrapper);

                this.element.addClass(wijCSS.wijinputInput).addClass(wijCSS.cornerAll).attr('role', 'textbox');

                if (this.options.showTrigger != undefined) {
                    this.options.showDropDownButton = this.options.showTrigger;
                }

                this._createDropDownAndSpin();
                this._initialize();

                if (focused) {
                    $(function () {
                        return _this.element.focus().wijtextselection(0, _this.element.val().length);
                    });
                }

                // We need to move width and height from the <input/> to the outer <div/> because the input must span the parent wrapper.
                // It must be done if A dimension is set in the style attribute, hence the "if" statements
                // The a dimension is in pixels, it must be adjusted according to the input's and div's border/margin/padding.
                // The input's total border size must be calcualted before changing the classes, hence variables hBorder and vBorder.
                var style = this.element[0].style;
                if (style.width) {
                    if (this._isInPercents(style.width)) {
                        this.outerDiv.width(style.width);
                    } else {
                        this.outerDiv.width(this.element.width() + hBorder - this._horizontalBorderWidth(this.outerDiv));
                    }
                    this.element.width("");
                }
                if (style.height) {
                    if (this._isInPercents(style.height)) {
                        this.outerDiv.height(style.height);
                    } else {
                        this.outerDiv.height(this.element.height() + vBorder - this._verticalBorderWidth(this.outerDiv));
                    }
                    this.element.height(this.outerDiv.height() - (parseInt(this.wrapper.css('padding-top')) + parseInt(this.wrapper.css('padding-bottom'))));
                    this.wrapper.height(style.height);
                }

                //For implement the task#151923.
                //Input widgets are placed inside a form, so we need create a hidden field
                //for this input control to transfer the input value when do form submit.
                var ele = this.element, form = ele.closest("form");
                if (form && form.length > 0 && ele.attr('name')) {
                    this._hiddenInput = $("<input type='hidden'>").appendTo(form).attr('name', ele.attr('name'));
                    if (ele.attr('value')) {
                        this._hiddenInput.attr('value', ele.attr('value'));
                    }
                    ele.removeAttr('name');
                }

                _super.prototype._create.call(this);
            };

            wijinputcore.prototype._createDropDownAndSpin = function () {
                this._createDropDownAndSpinElement();
                this._createDropDownAndSpinStyle();
                this._createDropDownAndSpinLayout();
            };

            wijinputcore.prototype._createDropDownAndSpinElement = function () {
                var wijCSS = this.options.wijCSS;
                var spinnerAlign = this.options.spinnerAlign;
                var leftSpinnerBtn = spinnerAlign === 'verticalLeft';
                var leftDropDownBtn = this.options.dropDownButtonAlign === 'left';
                var showSpinner = this.options.showSpinner;
                var showDropDownButton = this._isDropDownButtonShown();

                if (this.options.buttonAlign != null) {
                    leftSpinnerBtn = this.options.buttonAlign == 'left';
                    leftDropDownBtn = this.options.buttonAlign == 'left';
                    spinnerAlign = this.options.buttonAlign == 'left' ? "verticalLeft" : "verticalRight";
                }

                this.triggerBtn = null;
                this.spinUpElement = null;
                this.spinDownElement = null;

                this.outerDiv.css("overflow", "hidden");

                if (showDropDownButton) {
                    var cornerCSS = leftDropDownBtn ? wijCSS.cornerLeft : wijCSS.cornerRight;
                    this.triggerBtn = this._divWithClasses(wijCSS.wijinputTrigger, wijCSS.stateDefault, cornerCSS).append(this._spanWithClasses(wijCSS.icon, wijCSS.iconArrowDown)).attr('role', 'button');
                }

                if (showSpinner) {
                    this.spinnerLeft = this._divWithClasses(wijCSS.wijinputSpinnerLeft, wijCSS.wijinputButton);
                    this.spinnerRight = this._divWithClasses(wijCSS.wijinputSpinnerRight, wijCSS.wijinputButton);

                    if (spinnerAlign === "verticalLeft" || spinnerAlign === "verticalRight") {
                        this.spinUpElement = this._divWithClasses(wijCSS.stateDefault, wijCSS.wijinputSpinUp).append(this._spanWithClasses(wijCSS.icon, wijCSS.iconArrowUp)).css({ "padding": "0px" });

                        this.spinDownElement = this._divWithClasses(wijCSS.stateDefault, wijCSS.wijinputSpinDown).append(this._spanWithClasses(wijCSS.icon, wijCSS.iconArrowDown)).css({ "padding": "0px" });
                    } else {
                        this.spinUpElement = this._divWithClasses(wijCSS.stateDefault, wijCSS.wijinputSpin).append(this._spanWithClasses(wijCSS.icon, wijCSS.iconPlus, wijCSS.glyphIcon, wijCSS.glyphIconPlus)).css({ "padding": "0px" });
                        this.spinDownElement = this._divWithClasses(wijCSS.stateDefault, wijCSS.wijinputSpin).append(this._spanWithClasses(wijCSS.icon, wijCSS.iconMinus, wijCSS.glyphIcon, wijCSS.glyphIconMinus)).css({ "padding": "0px" });
                    }

                    this.element.attr('role', 'spinner');
                }
            };

            wijinputcore.prototype._createDropDownAndSpinStyle = function () {
                var wijCSS = this.options.wijCSS;
                var spinnerAlign = this.options.spinnerAlign;
                var leftSpinnerBtn = this.options.spinnerAlign === 'verticalLeft';
                var leftDropDownBtn = this.options.dropDownButtonAlign === 'left';
                var showSpinner = this.options.showSpinner;
                var showDropDownButton = this._isDropDownButtonShown();

                if (this.options.buttonAlign != null) {
                    leftSpinnerBtn = this.options.buttonAlign == 'left';
                    leftDropDownBtn = this.options.buttonAlign == 'left';
                    spinnerAlign = this.options.buttonAlign == 'left' ? "verticalLeft" : "verticalRight";
                }

                //Flag CSS
                if (showDropDownButton && showSpinner) {
                    if (leftDropDownBtn) {
                        switch (spinnerAlign) {
                            case "verticalLeft":
                                this.outerDiv.addClass(wijCSS.inputSpinnerTriggerLeft);
                                break;
                            case "verticalRight":
                                this.outerDiv.addClass(wijCSS.inputTriggerLeft);
                                this.outerDiv.addClass(wijCSS.inputSpinnerRight);
                                break;
                            case "horizontalDownLeft":
                            case "horizontalUpLeft":
                                this.outerDiv.addClass(wijCSS.inputSpinnerTriggerLeft);
                                this.outerDiv.addClass(wijCSS.inputSpinnerRight);
                                break;
                        }
                    } else {
                        switch (spinnerAlign) {
                            case "verticalLeft":
                                this.outerDiv.addClass(wijCSS.inputTriggerRight);
                                this.outerDiv.addClass(wijCSS.inputSpinnerLeft);
                                break;
                            case "verticalRight":
                                this.outerDiv.addClass(wijCSS.inputSpinnerTriggerRight);
                                break;
                            case "horizontalDownLeft":
                            case "horizontalUpLeft":
                                this.outerDiv.addClass(wijCSS.inputSpinnerTriggerRight);
                                this.outerDiv.addClass(wijCSS.inputSpinnerLeft);
                                break;
                        }
                    }
                } else if (showDropDownButton) {
                    if (leftDropDownBtn) {
                        this.outerDiv.addClass(wijCSS.inputTriggerLeft);
                    } else {
                        this.outerDiv.addClass(wijCSS.inputTriggerRight);
                    }
                } else if (showSpinner) {
                    switch (spinnerAlign) {
                        case "verticalLeft":
                            this.outerDiv.addClass(wijCSS.inputSpinnerLeft);
                            break;
                        case "verticalRight":
                            this.outerDiv.addClass(wijCSS.inputSpinnerRight);
                            break;
                        case "horizontalDownLeft":
                        case "horizontalUpLeft":
                            this.outerDiv.addClass(wijCSS.inputSpinnerLeft);
                            this.outerDiv.addClass(wijCSS.inputSpinnerRight);
                            break;
                    }
                }

                //Corner CSS
                if (showDropDownButton && showSpinner) {
                    if (leftDropDownBtn) {
                        switch (spinnerAlign) {
                            case "verticalRight":
                                this.spinUpElement.addClass(wijCSS.cornerTR);
                                this.spinDownElement.addClass(wijCSS.cornerBR);
                                break;
                            case "horizontalDownLeft":
                                this.spinUpElement.addClass(wijCSS.cornerRight);
                                break;
                            case "horizontalUpLeft":
                                this.spinDownElement.addClass(wijCSS.cornerRight);
                                break;
                        }
                    } else {
                        switch (spinnerAlign) {
                            case "verticalLeft":
                                this.spinUpElement.addClass(wijCSS.cornerTL);
                                this.spinDownElement.addClass(wijCSS.cornerBL);
                                break;
                            case "horizontalDownLeft":
                                this.spinDownElement.addClass(wijCSS.cornerLeft);
                                break;
                            case "horizontalUpLeft":
                                this.spinUpElement.addClass(wijCSS.cornerLeft);
                                break;
                        }
                    }
                } else if (showSpinner) {
                    switch (spinnerAlign) {
                        case "verticalLeft":
                            this.spinUpElement.addClass(wijCSS.cornerTL);
                            this.spinDownElement.addClass(wijCSS.cornerBL);
                            break;
                        case "verticalRight":
                            this.spinUpElement.addClass(wijCSS.cornerTR);
                            this.spinDownElement.addClass(wijCSS.cornerBR);
                            break;
                        case "horizontalDownLeft":
                            this.spinDownElement.addClass(wijCSS.cornerLeft);
                            this.spinUpElement.addClass(wijCSS.cornerRight);
                            break;
                        case "horizontalUpLeft":
                            this.spinUpElement.addClass(wijCSS.cornerLeft);
                            this.spinDownElement.addClass(wijCSS.cornerRight);
                            break;
                    }
                }
            };

            wijinputcore.prototype._createDropDownAndSpinLayout = function () {
                var spinnerAlign = this.options.spinnerAlign;
                var showSpinner = this.options.showSpinner;
                var showDropDownButton = this._isDropDownButtonShown();

                if (this.options.buttonAlign != null) {
                    spinnerAlign = this.options.buttonAlign == 'left' ? "verticalLeft" : "verticalRight";
                }

                if (showDropDownButton) {
                    this.triggerBtn.appendTo(this.outerDiv);
                }

                if (showSpinner) {
                    switch (spinnerAlign) {
                        case "verticalLeft":
                            this.spinnerLeft.append(this.spinUpElement).append(this.spinDownElement).appendTo(this.outerDiv);
                            break;
                        case "verticalRight":
                            this.spinnerRight.append(this.spinUpElement).append(this.spinDownElement).appendTo(this.outerDiv);
                            break;
                        case "horizontalDownLeft":
                            this.spinnerLeft.append(this.spinDownElement).appendTo(this.outerDiv);
                            this.spinnerRight.append(this.spinUpElement).appendTo(this.outerDiv);
                            break;
                        case "horizontalUpLeft":
                            this.spinnerLeft.append(this.spinUpElement).appendTo(this.outerDiv);
                            this.spinnerRight.append(this.spinDownElement).appendTo(this.outerDiv);
                            break;
                    }
                }
            };

            wijinputcore.prototype._isDropDownButtonShown = function () {
                var showTrigger = this.options.showTrigger;
                if (showTrigger === undefined) {
                    showTrigger = false;
                }
                return showTrigger || this.options.showDropDownButton;
            };

            wijinputcore.prototype._isInPercents = function (size) {
                return size.match(/%$/);
            };

            wijinputcore.prototype._createTextProvider = function () {
                return undefined;
            };

            wijinputcore.prototype._beginUpdate = function () {
            };

            wijinputcore.prototype._endUpdate = function () {
                var _this = this;
                if (this.element.mousewheel && !this._boundMouseWheel) {
                    this.element.mousewheel(function (e, delta) {
                        if (_this.isFocused() && _this._doSpin(delta > 0, false)) {
                            e.preventDefault();
                        }
                    });
                    this._boundMouseWheel = true;
                }
            };

            wijinputcore.prototype._isPopupShowing = function () {
                return !!this._comboDiv && this._comboDiv.wijpopup("isVisible");
            };

            wijinputcore.prototype._onTriggerMouseDown = function (evt) {
                if (this._wasPopupShowing) {
                    this._blockNextTriggerClickedEvent = true;
                }
            };

            wijinputcore.prototype._onTriggerMouseUp = function (evt) {
            };

            wijinputcore.prototype._onTriggerClicked = function () {
                if (this._blockNextTriggerClickedEvent) {
                    this._blockNextTriggerClickedEvent = false;
                    return;
                }
                if (this._popupVisible()) {
                    this._hidePopup();
                } else {
                    this._showPopup();
                }
            };
            wijinputcore.prototype._showPopup = function () {
                return this._popupComboList();
            };
            wijinputcore.prototype._hidePopup = function () {
                this._comboDiv.wijpopup('hide');
            };

            wijinputcore.prototype._initialize = function () {
                var _this = this;
                this.element.data('initializing', true);
                this._trigger('initializing');

                this.element.data('preText', this.element.val());
                this.element.data('elementValue', this.element.val());
                this.element.data('errorstate', false);
                this.element.data('breakSpinner', true);
                this.element.data('prevSelection', null);
                this.element.data('simulating', false);

                this._createTextProvider();
                this._beginUpdate();

                var options = this.options, isLeftButton = function (e) {
                    return (!e.which ? e.button : e.which) === 1;
                }, spinButtonDown = function (e) {
                    if (_this._isDisabled()) {
                        return;
                    }
                    if (!isLeftButton(e)) {
                        return;
                    }
                    if (_this.options.disableUserInput) {
                        return;
                    }
                    _this._deferClearBlurTimeout();
                    _this._trySetFocus();
                    if (CoreUtility.IsFireFox4OrLater()) {
                        _this._stopEvent(e);
                    }

                    _this.element.data('breakSpinner', false);
                    _this._addState('active', $(_this));
                    _this._doSpin($(e.currentTarget).hasClass(options.wijCSS.wijinputSpinUp) || $('.' + options.wijCSS.iconPlus, e.currentTarget).length > 0, true);
                }, spinButtonUp = function (e) {
                    if (_this._isDisabled()) {
                        return;
                    }
                    if (!isLeftButton(e)) {
                        return;
                    }
                    if (_this.options.disableUserInput) {
                        return;
                    }
                    _this._stopSpin();
                    _this._removeState('active', $(_this));
                };

                if (this.triggerBtn && !options.disabledState) {
                    this.triggerBtn.bind({
                        'mouseover': function () {
                            if (_this._isDisabled()) {
                                return;
                            }
                            _this._addState('hover', $(_this));
                        },
                        'mouseout': function () {
                            if (_this._isDisabled()) {
                                return;
                            }
                            _this._removeState('hover', $(_this));
                        },
                        'mousedown': function (e) {
                            if (_this._isDisabled()) {
                                return;
                            }
                            if (!isLeftButton(e)) {
                                return;
                            }
                            _this._stopEvent(e);
                            _this._addState('active', $(_this));
                            _this._trigger('triggerMouseDown');
                            _this._trigger('dropDownButtonMouseDown');
                            _this._onTriggerMouseDown(e);
                        },
                        'mouseup': function (e) {
                            _this._onTriggerMouseUp(e);
                        },
                        'click': function (e) {
                            if (_this._isDisabled()) {
                                return;
                            }
                            _this._stopEvent(e);
                            _this._stopSpin();
                            _this._removeState('active', $(_this));
                            _this._trigger('triggerMouseUp');
                            _this._trigger('dropDownButtonMouseUp');
                            _this._onTriggerClicked();
                            if (!CoreUtility.IsPad()) {
                                _this._trySetFocus();
                            }
                        }
                    });
                }

                if (this.spinUpElement && !options.disabledState) {
                    this.spinUpElement.bind({
                        'mouseover': function () {
                            if (_this._isDisabled()) {
                                return;
                            }
                            _this._addState('hover', $(_this));
                        },
                        'mouseout': function () {
                            if (_this._isDisabled()) {
                                return;
                            }
                            _this._removeState('hover', $(_this));
                            _this._removeState('active', $(_this));
                            _this._stopSpin();
                        },
                        'mousedown': spinButtonDown,
                        'mouseup': spinButtonUp
                    });
                }

                if (this.spinDownElement && !options.disabledState) {
                    this.spinDownElement.bind({
                        'mouseover': function () {
                            if (_this._isDisabled()) {
                                return;
                            }
                            _this._addState('hover', $(_this));
                        },
                        'mouseout': function () {
                            if (_this._isDisabled()) {
                                return;
                            }
                            _this._removeState('hover', $(_this));
                            _this._removeState('active', $(_this));
                            _this._stopSpin();
                        },
                        'mousedown': spinButtonDown,
                        'mouseup': spinButtonUp
                    });
                }

                this._attachInputEvent();
                this.element.data('initializing', false);

                this._resetData();
                this._endUpdate();
                this._updateText();

                if (this.options.imeMode) {
                    this.element.css("ime-mode", this.options.imeMode);
                }

                this.element.data('initialized', true);
                this._trigger('initialized');
            };

            wijinputcore.prototype._attachInputEvent = function () {
                this.element.bind({
                    'focus.wijinput': $.proxy(this._onFocus, this),
                    'beforedeactivate.wijinput': $.proxy(this._onBeforeDeactivate, this),
                    'blur.wijinput': $.proxy(this._onBlur, this),
                    'mousedown.wijinput': $.proxy(this._onMouseDown, this),
                    'mouseup.wijinput': $.proxy(this._onMouseUp, this),
                    'keypress.wijinput': $.proxy(this._onKeyPress, this),
                    'keydown.wijinput': $.proxy(this._onKeyDown, this),
                    'keyup.wijinput': $.proxy(this._onKeyUp, this),
                    'compositionstart.wijinput': $.proxy(this._onCompositionStart, this),
                    'compositionend.wijinput': $.proxy(this._onCompositionEnd, this),
                    'change.wijinput': $.proxy(this._onChange, this),
                    'paste.wijinput': $.proxy(this._onPaste, this),
                    'drop.wijinput': $.proxy(this._onDrop, this)
                });

                this.element.bind('propertychange.wijinput input.wijinput', $.proxy(this._onInput, this));
            };

            wijinputcore.prototype._detachInputEvent = function () {
                this.element.unbind('.wijinput');
            };

            wijinputcore.prototype._init = function () {
                if (this.element.attr("readOnly")) {
                    this.options.readonly = true;
                }
                if (this.options.readonly === true) {
                    this.options.disableUserInput = true;
                }
                if (this.options.readonly === true || this.options.disableUserInput === true) {
                    this.element.attr('readOnly', true);
                }

                if (this.options.placeholder != null) {
                    this.options.nullText = this.options.placeholder;
                }
            };

            wijinputcore.prototype._showNullText = function () {
                return !!this.options.nullText || this.options.nullText === "";
            };

            wijinputcore.prototype._setOption = function (key, value) {
                switch (key) {
                    case 'readonly':
                        this._super(key, value);
                        key = "disableUserInput";
                        break;
                    case 'placeholder':
                        this._super(key, value);
                        key = 'nullText';
                        break;
                    case 'showTrigger':
                        this.options.showTrigger = value;
                        this.options.showDropDownButton = value;
                        break;
                }

                this._super(key, value);

                switch (key) {
                    case 'spinnerAlign':
                    case 'dropDownButtonAlign':
                    case 'showDropDownButton':
                    case 'buttonAlign':
                    case 'showTrigger':
                    case 'showSpinner':
                        this._destroy();
                        this._create();
                        break;

                    case 'showNullText':
                    case 'nullText':
                        this._updateText();
                        break;

                    case 'imeMode':
                        this.element.css("ime-mode", this.options.imeMode);
                        break;

                    case 'disableUserInput':
                        this.element.attr('readOnly', value);
                        break;
                    case 'pickers':
                        this._deleteComboDiv();
                        break;
                }
            };

            wijinputcore.prototype._innerDisable = function () {
                _super.prototype._innerDisable.call(this);
                this._toggleDisableInput(true);
            };

            wijinputcore.prototype._innerEnable = function () {
                _super.prototype._innerEnable.call(this);
                this._toggleDisableInput(false);
            };

            wijinputcore.prototype._toggleDisableInput = function (disabled) {
                var stateDisabled = this.options.wijCSS.stateDisabled;
                this.element.attr('disabled', disabled);

                this.element.toggleClass(stateDisabled, disabled);
                if (this.triggerBtn) {
                    this.triggerBtn.toggleClass(stateDisabled, disabled);
                }

                if (this.spinUpElement) {
                    this.spinUpElement.toggleClass(stateDisabled, disabled);
                }

                if (this.spinDownElement) {
                    this.spinDownElement.toggleClass(stateDisabled, disabled);
                }
            };

            /** Destroy the widget.
            */
            wijinputcore.prototype.destroy = function () {
                this._super();
                if (this._comboDiv) {
                    this._comboDiv.remove();
                }

                if (this.outerDiv) {
                    this.outerDiv.remove();
                }

                if (this._hiddenInput) {
                    this._hiddenInput.remove();
                }

                if (this.spinnerLeft) {
                    this.spinnerLeft.remove();
                }
                if (this.spinnerRight) {
                    this.spinnerRight.remove();
                }
                if (this.spinDownElement) {
                    this.spinDownElement.remove();
                }
                if (this.spinUpElement) {
                    this.spinUpElement.remove();
                }
                this._destroy();
            };

            /** Open the dropdown list.
            */
            wijinputcore.prototype.drop = function () {
                this._onTriggerClicked();
            };

            /** Get a boolean value indicates that whether the widget has been destroyed.
            */
            wijinputcore.prototype.isDestroyed = function () {
                return !this.outerDiv;
            };

            wijinputcore.prototype._destroy = function () {
                if (this.isDestroyed())
                    return;
                this.wrapper = undefined;
                this.outerDiv = undefined;

                this._detachInputEvent();

                this.element.removeData('errorstate').removeData('breakSpinner').removeData('prevSelection').removeData('simulating').removeData('isPassword').removeClass(this.options.wijCSS.wijinputInput).removeAttr('role').removeAttribute('aria-valuemin').removeAttribute('aria-valuemax').removeAttribute('aria-valuenow');

                this.element.parent().replaceWith(this.element);
                this.element.parent().replaceWith(this.element);

                //$.effects.restore(this.element, ['width', 'height']);
                if ($.effects && $.effects.restore) {
                    $.effects.restore(this.element, ['width', 'height']);
                } else if ($.restore) {
                    $.restore(this.element, ['width', 'height']);
                }

                // DaryLuo 2014/03/05 fix bug 50664.
                this.triggerBtn = undefined;
                this.spinnerLeft = undefined;
                this.spinnerRight = undefined;
                this.spinDownElement = undefined;
                this.spinUpElement = undefined;
                this._clearBlurTimeout();
            };

            /** Gets element this widget is associated.
            */
            wijinputcore.prototype.widget = function () {
                return this.outerDiv || this._super();
            };

            wijinputcore.prototype._getCulture = function (name) {
                if (!Globalize) {
                    return null;
                }
                var cal = $.extend(true, {}, Globalize.findClosestCulture(name || this.options.culture) || Globalize.findClosestCulture("default"));
                if (this.options.cultureCalendar !== '' && this.options.cultureCalendar !== 'standard') {
                    $.extend(cal.calendar, cal.calendars[this.options.cultureCalendar || 'standard']);
                }
                return cal;
            };

            wijinputcore.prototype._addState = function (state, el) {
                if (el.is(':not(.ui-state-disabled)')) {
                    el.addClass(this.options.wijCSS.getState(state));
                }
            };

            wijinputcore.prototype._removeState = function (state, el) {
                el.removeClass(this.options.wijCSS.getState(state));
            };

            wijinputcore.prototype._isInitialized = function () {
                return !this.element.data('initializing');
            };

            wijinputcore.prototype._setData = function (val) {
                this.setText(val);
            };

            wijinputcore.prototype._resetData = function () {
            };

            wijinputcore.prototype._validateData = function () {
            };

            /** Gets the text displayed in the input box.
            */
            wijinputcore.prototype.getText = function () {
                if (!this._isInitialized()) {
                    return this.element.val();
                }
                return this._textProvider.toString(true, false, false);
            };

            /** Sets the text displayed in the input box.
            * @example
            * // This example sets text of a wijinputcore to "Hello"
            * $(".selector").wijinputcore("setText", "Hello");
            */
            wijinputcore.prototype.setText = function (value) {
                if (!this._isInitialized()) {
                    this.element.val(value);
                } else {
                    this._textProvider.setText(value);
                    if (value !== "" && this.element.val() !== this.options.nullText) {
                        this.element.data('isShowNullText', false);
                    }
                    this._updateText();
                }
            };

            /** Gets the text value when the container form is posted back to server.
            */
            wijinputcore.prototype.getPostValue = function () {
                if (!this._isInitialized()) {
                    return this.element.val();
                }
                return this._textProvider.toString(true, false, true);
            };

            /** Selects a range of text in the widget.
            * @param {Number} start Start of the range.
            * @param {Number} end End of the range.
            * @example
            * // Select first two symbols in a wijinputcore
            * $(".selector").wijinputdate("selectText", 0, 2);
            */
            wijinputcore.prototype.selectText = function (start, end) {
                var _this = this;
                if (typeof start === "undefined") { start = 0; }
                if (typeof end === "undefined") { end = this.getText().length; }
                if (isNaN(start)) {
                    start = 0;
                }
                if (isNaN(end)) {
                    end = 0;
                }
                if (CoreUtility.IsFireFox4OrLater()) {
                    this.focus();
                }
                if (this.element.is(':disabled')) {
                    return;
                }
                this.isSelectingFromAPI = true;
                this.element.wijtextselection(start, end);
                setTimeout(function () {
                    return _this.isSelectingFromAPI = false;
                }, 100);
            };

            /** Set the focus to the widget.
            */
            wijinputcore.prototype.focus = function () {
                if (this.element.is(':disabled')) {
                    return;
                }
                this.element.get(0).focus();
            };

            /** Determines whether the widget has the focus.
            */
            wijinputcore.prototype.isFocused = function () {
                if (!this.outerDiv) {
                    return false;
                }

                return this.outerDiv.hasClass(this.options.wijCSS.stateFocus);
            };

            /** Gets the selected text.
            */
            wijinputcore.prototype.getSelectedText = function () {
                if (this.isFocused()) {
                    return this.element.wijtextselection().text;
                } else {
                    if (this.element.data('prevSelection')) {
                        var start = this.element.data('prevSelection').start, end = this.element.data('prevSelection').end;
                        return this.element.val().substring(start, end);
                    } else {
                        return "";
                    }
                }
            };

            wijinputcore.prototype._raiseTextChanged = function () {
                var txt = this.element.val(), preText = this.element.data('preText');
                if (!!this.element.data('initialized') && preText !== txt) {
                    if (this._hiddenInput) {
                        this._hiddenInput.val(this.getPostValue());
                    }

                    this._trigger('textChanged', null, { text: txt });
                    this.element.data('changed', true);
                }

                this.element.data('preText', txt);
            };

            wijinputcore.prototype._raiseDataChanged = function () {
            };

            wijinputcore.prototype._allowEdit = function () {
                return !this.element.is(':disabled');
            };

            wijinputcore.prototype._updateText = function (keepSelection) {
                if (typeof keepSelection === "undefined") { keepSelection = false; }
                if (!this._isInitialized()) {
                    return;
                }

                // default is false
                keepSelection = !!keepSelection;

                var range;
                if (this.element.data('selectionbeforeblur') !== undefined) {
                    range = this.element.data('selectionbeforeblur');
                    this.element.removeData('selectionbeforeblur');
                } else {
                    try  {
                        range = this.element.wijtextselection();
                    } catch (e) {
                    }
                }
                var opt = this.options;

                if (this.isDeleteAll && this._showNullText()) {
                    this.isDeleteAll = false;
                    opt.date = null;
                    this.element.val(opt.nullText);
                } else {
                    this.element.val(this._textProvider.toString());
                    this.options.text = this._textProvider.toString(true, false, false);
                }

                if (!this.element.is(':disabled')) {
                    if (keepSelection) {
                        this.selectText(range.start, range.end);
                    }
                    this.element.data('prevSelection', range);
                }

                this._raiseTextChanged();
                this._raiseDataChanged();
            };

            wijinputcore.prototype._trySetFocus = function () {
                if (document.activeElement !== this.element[0]) {
                    try  {
                        if (!this.options.disableUserInput) {
                            this.element.focus();
                        }
                    } catch (e) {
                    }
                }
            };

            wijinputcore.prototype._deleteSelText = function (backSpace) {
                if (typeof backSpace === "undefined") { backSpace = false; }
                if (!this._allowEdit()) {
                    return;
                }
                var selRange = this.element.wijtextselection();

                if (backSpace) {
                    if (selRange.end < 1)
                        return;
                    if (selRange.end === selRange.start) {
                        selRange.start--;
                    }
                }
                selRange.end--;
                if (selRange.end < selRange.start) {
                    selRange.end = selRange.start;
                }

                var rh = new input.wijInputResult();
                this._textProvider.removeAt(selRange.start, selRange.end, rh);
                this._updateText();
                this.selectText(rh.testPosition, rh.testPosition);
            };

            wijinputcore.prototype._fireIvalidInputEvent = function (chr) {
                var _this = this;
                var invalidInputResult = this._trigger('invalidInput', null, { widget: this, char: chr });
                if ($.isFunction(this.options.invalidInput) && invalidInputResult === true) {
                    return;
                }
                if (!this.element.data('errorstate')) {
                    var cls = this.options.invalidClass || this.options.wijCSS.stateError;
                    this.element.data('errorstate', true);

                    window.setTimeout(function () {
                        if (_this.outerDiv) {
                            _this.outerDiv.removeClass(cls);
                        }
                        _this.element.data('errorstate', false);
                    }, 200);
                    this.outerDiv.addClass(cls);
                }
            };

            wijinputcore.prototype._onInput = function (e) {
                var isIOS = window.navigator.userAgent.match(/iPhone|iPad|iPod/i);
                if (isIOS) {
                    if (this.element.data("hasInput") === true && !this._imeCompostiing) {
                        this.element.data("hasInput", false);
                        this._simulate();
                    }
                    return;
                }
                if (!this._isSimulating() || !this.element.data('ime') || this.element.data("isComposingIME")) {
                    if (this.element.data("isComposingIME")) {
                        this.element.data("simulationPending", true);
                    }
                    return;
                }
                this._simulate();
            };

            wijinputcore.prototype._keyDownPreview = function (e) {
                var key = e.keyCode || e.which;

                if (e.ctrlKey === true && key === 88) {
                    return true;
                }
                if (e.ctrlKey === true && key === 90) {
                    return true;
                }
                return false;
            };

            wijinputcore.prototype._onDoubleByteCharacter = function () {
                var prev = this.element.data("lastDbsState");
                var curSel = this.element.wijtextselection();
                var curText = this.element.val();

                if (this.element.data("isComposingIME") && prev && prev.selection.start === curSel.start && prev.Text === curText) {
                    // nothing changed. The input must be accepted
                    this.element.removeData("lastDbsState");
                    this._simulateOnCompositionEnd();
                } else {
                    this.element.data("lastDbsState", { selection: curSel, text: curText });
                    this._onCompositionStart();
                }
            };
            wijinputcore.prototype._onCompositionStart = function () {
                var isIOS = window.navigator.userAgent.match(/iPhone|iPad|iPod/i);
                if (isIOS) {
                    this._imeCompostiing = true;
                    this._beforeSimulate(true);
                    return;
                }
                if (this.element.data("isComposingIME"))
                    return;
                this.element.data("isComposingIME", true);
                this._beforeSimulate(true);
            };
            wijinputcore.prototype._onCompositionEnd = function () {
                var isIOS = window.navigator.userAgent.match(/iPhone|iPad|iPod/i);
                if (isIOS) {
                    this._imeCompostiing = false;
                    this.element.data("hasInput", true);
                    return;
                }
                this._simulateOnCompositionEnd();
            };
            wijinputcore.prototype._simulateOnCompositionEnd = function () {
                if (!this.element.data("isComposingIME"))
                    return;

                this.element.data("isComposingIME", false);
                if (this._isInitialized() && (!this._textProvider || !this._textProvider.noMask)) {
                    this._simulateIfPending();
                }
            };

            wijinputcore.prototype._simulateIfPending = function () {
                if (this.element.data("simulationPending") && this.element.data("lastSelection")) {
                    this._simulate();
                }
            };

            wijinputcore.prototype._beforeSimulate = function (ime) {
                if (typeof ime === "undefined") { ime = false; }
                if (!this.element.data('lastSelection')) {
                    this.element.data('lastSelection', this.element.wijtextselection());
                    this.element.data('lastValue', this.element.val());
                }

                this.element.data('ime', ime);
                this.element.data('simulating', true);
            };

            wijinputcore.prototype._isSimulating = function () {
                return this.element.data('simulating');
            };

            wijinputcore.prototype._simulate = function (text) {
                var self = this;
                var str = null;

                this.element.data("simulationPending", false);

                if (typeof text === "string") {
                    str = text;
                } else {
                    var range = this.element.wijtextselection();
                    var start = this.element.data('lastSelection').start;
                    var end = range.end;

                    if (end >= start) {
                        str = this.element.val().substring(start, end);
                    }
                }

                if (str) {
                    window.setTimeout(function () {
                        if (self._isLastValueNull()) {
                            return;
                        }
                        self.element.val(self.element.data('lastValue'));
                        var lastSel = self.element.data('lastSelection');
                        self.element.wijtextselection(lastSel);
                        self._batchKeyPress = true;
                        self.element.data('simulating', false);
                        var e = jQuery.Event('keypress');
                        e.ctrlKey = e.altKey = false;
                        for (var i = 0; i < str.length; i++) {
                            e.which = e.charCode = e.keyCode = str.charCodeAt(i);
                            self._nextChar = i === str.length - 1 ? "" : str.charAt(i + 1);
                            self._onKeyPress(e);
                            self._nextChar = "";

                            var appendChar = self._appendChar;
                            if (appendChar && appendChar.length > 0) {
                                self._appendChar = "";
                                e.which = e.charCode = e.keyCode = appendChar.charCodeAt(i);
                                self._onKeyPress(e);
                            }
                            if (self._skipNextChar) {
                                i++;
                                self._skipNextChar = false;
                            }
                        }

                        self._batchKeyPress = false;
                        self._endSimulate();
                    }, 1);
                }
            };

            wijinputcore.prototype._isLastValueNull = function () {
                return !this.element.data('lastValue');
            };

            wijinputcore.prototype._endSimulate = function () {
                this._simulateIfPending();
                this.element.removeData('ime');
                this.element.removeData('lastSelection');
                this.element.removeData('lastValue');
            };

            wijinputcore.prototype._processKeyForDropDownList = function (e) {
                var k = this._getKeyCode(e);
                if (e.altKey && (k === jqKeyCode.UP || k === jqKeyCode.DOWN)) {
                    this._onTriggerClicked();
                    this._stopEvent(e);
                    return true;
                }
                if (k === jqKeyCode.ESCAPE) {
                    if (this._wasPopupShowing) {
                        this._hidePopup();
                        this._stopEvent(e);
                        return true;
                    }
                }

                if (this._wasPopupShowing && this._comboDiv !== undefined) {
                    if (k === jqKeyCode.DOWN) {
                        try  {
                            this._comboDiv.wijlist('next');
                        } catch (ee) {
                        }
                        this._stopEvent(e);
                        return true;
                    } else if (k === jqKeyCode.UP) {
                        try  {
                            this._comboDiv.wijlist('previous');
                        } catch (ee) {
                        }
                        this._stopEvent(e);
                        return true;
                    } else if (k === jqKeyCode.ENTER) {
                        this._comboDiv.wijlist('select');

                        // DaryLuo 2014/07/07 fix bug 71663.
                        // Here we only prevent default behavior, but still left the event bubble up.
                        e.preventDefault();

                        //this._stopEvent(e);
                        return true;
                    } else if (k === jqKeyCode.PAGE_DOWN) {
                        try  {
                            this._comboDiv.wijlist('nextPage');
                        } catch (ee) {
                        }
                        this._stopEvent(e);
                        return true;
                    } else if (k === jqKeyCode.PAGE_UP) {
                        try  {
                            this._comboDiv.wijlist('previousPage');
                        } catch (ee) {
                        }
                        this._stopEvent(e);
                        return true;
                    }
                }
            };

            wijinputcore.prototype._processKeyOnNoMask = function (e) {
                var k = this._getKeyCode(e);
                if (k === jqKeyCode.ENTER) {
                    this._onEnterDown(e);
                    if (this.options.autoPostBack) {
                        this._stopEvent(e);
                    }
                }
                if (k === jqKeyCode.LEFT || k === jqKeyCode.RIGHT) {
                    if (this._processLeftRightKey(k === jqKeyCode.LEFT)) {
                        this._stopEvent(e);
                        return;
                    }
                }

                this._processKeyForDropDownList(e);
            };

            wijinputcore.prototype._onKeyDown = function (e) {
                var isIOS = window.navigator.userAgent.match(/iPhone|iPad|iPod/i);
                if (isIOS && this._imeCompostiing) {
                    return;
                }
                this.element.data('prevSelection', null);
                this._deleteKeyDown = false;

                if (!this._isInitialized()) {
                    return;
                }

                if (this._textProvider && !!this._textProvider.noMask) {
                    this._processKeyOnNoMask(e);
                    return;
                }
                var k = this._getKeyCode(e);

                if (k === 229) {
                    this._onDoubleByteCharacter();
                    return;
                }
                this._simulateOnCompositionEnd();

                if (this.options.disableUserInput) {
                    if (k === jqKeyCode.TAB) {
                        if (this._processTabKey(e)) {
                            this._stopEvent(e);
                        }
                    } else {
                        this._stopEvent(e);
                    }
                    return;
                }

                if (this._keyDownPreview(e)) {
                    this._stopEvent(e);
                    return;
                }
                if (this._processKeyForDropDownList(e)) {
                    return;
                }

                switch (k) {
                    case jqKeyCode.UP:
                        this._doSpin(true, false);
                        this._stopEvent(e);
                        return;
                    case jqKeyCode.DOWN:
                        this._doSpin(false, false);
                        this._stopEvent(e);
                        return;
                    case jqKeyCode.LEFT:
                    case jqKeyCode.RIGHT:
                        if (this._processLeftRightKey(k === jqKeyCode.LEFT)) {
                            this._trigger('keyExit');
                            this._stopEvent(e);
                        }
                        return;
                    case jqKeyCode.TAB:
                        if (this._processTabKey(e)) {
                            this._stopEvent(e);
                        }
                        return;
                }

                if (e.ctrlKey) {
                    switch (k) {
                        case jqKeyCode.INSERT:
                        case 67:
                            return;
                        default:
                            break;
                    }
                }
                if (e.ctrlKey || e.altKey) {
                    return;
                }

                switch (k) {
                    case 112:
                    case 113:
                    case 114:
                    case 115:
                    case 116:
                    case 117:
                    case jqKeyCode.TAB:
                    case jqKeyCode.CAPSLOCK:
                    case jqKeyCode.END:
                    case jqKeyCode.HOME:
                    case jqKeyCode.CTRL:
                    case jqKeyCode.SHIFT:
                        return;
                    case jqKeyCode.BACKSPACE:
                        this._deleteSelText(true);
                        this._stopEvent(e);
                        return;
                    case jqKeyCode.DELETE:
                        this._deleteSelText(false);
                        this._stopEvent(e);
                        this._deleteKeyDown = true;
                        return;
                    case jqKeyCode.ENTER:
                        this._onEnterDown(e);
                        if (this.options.autoPostBack) {
                            this._stopEvent(e);
                        }
                        break;
                    case jqKeyCode.ESCAPE:
                        this._stopEvent(e);
                        window.setTimeout($.proxy(this._resetData, this), 1);
                        return;
                    case jqKeyCode.PAGE_UP:
                    case jqKeyCode.PAGE_DOWN:
                    case jqKeyCode.ALT:
                        this._stopEvent(e);
                        return;
                }
            };

            wijinputcore.prototype._onEnterDown = function (e) {
                if (this.options.hideEnter) {
                    this._stopEvent(e);
                }
            };

            wijinputcore.prototype._onKeyUp = function (e) {
                var isIOS = window.navigator.userAgent.match(/iPhone|iPad|iPod/i);
                if (isIOS && this._imeCompostiing) {
                    return;
                }
                if (this._textProvider && !!this._textProvider.noMask) {
                    return;
                }

                var key = this._getKeyCode(e);

                if (this._isSimulating()) {
                    if (key === jqKeyCode.ENTER) {
                        this._simulateOnCompositionEnd();
                    }
                    return;
                }

                if (!this._isInitialized()) {
                    return;
                }
                if (key === jqKeyCode.ENTER || key === jqKeyCode.ESCAPE) {
                    return;
                }

                if (this.options.disableUserInput) {
                    this._raiseTextChanged();
                    this._raiseDataChanged();
                    return;
                }

                this._stopEvent(e);
            };

            wijinputcore.prototype._getKeyCode = function (e) {
                var userAgent = window.navigator.userAgent;
                if ((userAgent.indexOf('iPod') !== -1 || userAgent.indexOf('iPhone') !== -1) && e.which === 127) {
                    return 8;
                }
                return e.keyCode || e.which;
            };

            wijinputcore.prototype._keyPressPreview = function (e) {
                return false;
            };

            wijinputcore.prototype._onKeyPress = function (e) {
                if (this._isSimulating() || (this._textProvider && !!this._textProvider.noMask)) {
                    return;
                }
                var isIOS = window.navigator.userAgent.match(/iPhone|iPad|iPod/i);
                if (isIOS && this._imeCompostiing) {
                    return;
                }
                this.element.data('prevSelection', null);

                if (this.options.disableUserInput) {
                    return;
                }
                if (!this._allowEdit()) {
                    return;
                }

                if (e.ctrlKey && e.keyCode === 119) {
                    this._onPaste(e);
                    return;
                }

                var key = e.keyCode || e.which;

                if (CoreUtility.IsFireFox4OrLater()) {
                    switch (e.keyCode) {
                        case jqKeyCode.UP:
                        case jqKeyCode.DOWN:
                        case jqKeyCode.LEFT:
                        case jqKeyCode.RIGHT:
                        case jqKeyCode.HOME:
                        case jqKeyCode.END:
                            return;
                    }
                }

                switch (key) {
                    case 0:
                    case jqKeyCode.TAB:
                        //case jqKeyCode.UP:
                        //case jqKeyCode.DOWN:
                        //case jqKeyCode.LEFT:
                        //case jqKeyCode.RIGHT:
                        return;

                    case jqKeyCode.BACKSPACE:
                        this._stopEvent(e);
                        return;

                    case jqKeyCode.DELETE:
                        if (this._deleteKeyDown) {
                            this._stopEvent(e);
                            return;
                        }
                        break;

                    case jqKeyCode.ENTER:
                        if (this.options.hideEnter) {
                            this._stopEvent(e);
                        }
                        return;
                }

                if (e.ctrlKey || e.altKey) {
                    if (key !== jqKeyCode.SPACE) {
                        return;
                    }
                }

                if (this._keyPressPreview(e)) {
                    return;
                }
                var isIOS = window.navigator.userAgent.match(/iPhone|iPad|iPod/i);

                if (isIOS && !this._batchKeyPress) {
                    this.element.data("hasInput", true);
                    this._beforeSimulate(true);
                    return;
                }

                var ch = String.fromCharCode(key);

                var rh = this._textProvider.replaceWith(this.element.wijtextselection(), ch);
                if (rh) {
                    this._updateText();
                    this.selectText(rh.testPosition + 1, rh.testPosition + 1);
                    this.element.data('prevSelection', { start: rh.testPosition + 1, end: rh.testPosition + 1 });
                } else {
                    this._fireIvalidInputEvent(ch);
                }
                if (!this._batchKeyPress) {
                    this._stopEvent(e);
                }
            };

            wijinputcore.prototype._isNullText = function (val) {
                val = val || this.element.val();
                return this._showNullText() && val === this.options.nullText;
            };

            wijinputcore.prototype._doFocus = function () {
                var selRange = this.element.wijtextselection();
                var sta = selRange.start;
                this._updateText();
                var s = this.element.val();
                if (s.length === sta) {
                    sta = 0;
                }
                if (!$.browser.safari) {
                    this.selectText(sta, sta);
                }
            };

            wijinputcore.prototype._afterFocused = function () {
                if (this._isNullText()) {
                    this._doFocus();
                }
            };

            wijinputcore.prototype._onFocus = function (e) {
                if (this.options.disableUserInput) {
                    return;
                }

                this.outerDiv.addClass(this.options.wijCSS.getState('focus'));

                if (!this.element.data('breakSpinner')) {
                    return;
                }

                if (!this._isInitialized()) {
                    return;
                }
                if (!this._allowEdit()) {
                    return;
                }

                if (this.isSelectingFromAPI) {
                    return;
                }
                if (!this.element.data('focusNotCalledFirstTime')) {
                    this.element.data('focusNotCalledFirstTime', new Date().getTime());
                }
                this._afterFocused();
            };

            wijinputcore.prototype._onBeforeDeactivate = function (e) {
                if (this.options.disableUserInput) {
                    return;
                }
                if (!this.element.data('breakSpinner')) {
                    return;
                }
                if (!this._isInitialized()) {
                    return;
                }
                if (!this._allowEdit()) {
                    return;
                }

                this.element.data('selectionbeforeblur', this.element.wijtextselection());
            };

            wijinputcore.prototype._onBlur = function (e) {
                var _this = this;
                if (this.options.disableUserInput) {
                    return;
                }
                this._simulateOnCompositionEnd();

                if (!this.element.data('breakSpinner')) {
                    this.element.get(0).focus();
                    if (this.element.data('prevSelection')) {
                        var curPos = this.element.data('prevSelection').start;
                        if (curPos !== undefined && curPos !== null) {
                            this.selectText(curPos, curPos);
                        }
                    }
                    return;
                }
                this._clearBlurTimeout();

                this._blurTimeout = setTimeout(function () {
                    _this._blurTimeout = null;

                    //Add comments by Ryanwu@20160520.
                    //For fixing the issue#151957,152107.
                    //if (this._isComboListVisible()) {
                    //return;
                    //}
                    if (_this._popupVisible()) {
                        _this._hidePopup();
                    }

                    //end by RyanWu@20160520.
                    _this._removeState('focus', _this.outerDiv);

                    if (!_this._isInitialized()) {
                        return;
                    }

                    _this.element.data('value', _this.element.val());
                    _this._updateTextOnLostFocus();
                }, 100);
            };

            wijinputcore.prototype._updateTextOnLostFocus = function () {
                var _this = this;
                window.setTimeout(function () {
                    _this._onChange();
                    _this._updateText();
                    _this._validateData();

                    if (_this.element.data('changed')) {
                        _this.element.data('changed', false);
                        if (!_this._popupVisible()) {
                            _this._trigger('change');
                            _this.element.data("customRaiseChange", true);
                            try  {
                                _this.element.change();
                            } finally {
                                _this.element.data("customRaiseChange", false);
                            }
                        }
                    }
                }, 100);
            };

            wijinputcore.prototype._popupVisible = function () {
                return this._wasPopupShowing;
            };

            wijinputcore.prototype._onMouseDown = function (e) {
                if (!this._isInitialized()) {
                    return;
                }
                if (this.element.is(':disabled')) {
                    return;
                }

                if (CoreUtility.IsMouseDownOnClearButton(e)) {
                    var isFocused = false;
                    try  {
                        isFocused = document.activeElement === e.target;
                    } catch (ee) {
                    }
                    this.element.data("focusedWhenMouseDown", isFocused);
                    this.element.data('mouseDownOnClearButton', true);
                    return;
                }
            };

            wijinputcore.prototype._onMouseUp = function (e) {
                if (!this._isInitialized()) {
                    return;
                }
                if (this.element.is(':disabled')) {
                    return;
                }

                if (CoreUtility.IsMouseDownOnClearButton(e) && this.element.data('mouseDownOnClearButton') && this.element.data('focusedWhenMouseDown') === true) {
                    if (!this.options.disableUserInput) {
                        var self = this;
                        setTimeout(function () {
                            self._processClearButton();
                        }, 0);
                    }
                    this.element.data('mouseDownOnClearButton', false);
                    return;
                }
                this.element.data('mouseDownOnClearButton', false);
                this.element.data('focusedWhenMouseDown', false);

                var selRange = this.element.wijtextselection();
                this.element.data('prevSelection', selRange);

                // fixed an issue of IE10(browser mode IE9), when runs in this mode,
                // the input element will show clear button at the right side of the input element.
                // click the button, the widget's text value will not cleared.
                if (this.element.val() == '') {
                    return;
                }
                var self = this;

                // Wait for it....
                setTimeout(function () {
                    if (self.element.val() == '') {
                        self.setText("");
                    }
                }, 5);

                if (this.element.data('isFocusSelecting')) {
                    this.element.data('isFocusSelecting', false);
                    e.preventDefault();
                }
            };

            wijinputcore.prototype._onChange = function () {
                if (!this.element) {
                    return;
                }
                var val = this.element.val();
                var txt = this.getText();
                if (txt !== val) {
                    this.setText(val);
                }
            };

            wijinputcore.prototype._onPaste = function (e) {
                if (this._textProvider && !!this._textProvider.noMask) {
                    return;
                }
                this._beforeSimulate();
                var self = this;
                window.setTimeout(function () {
                    self._simulate();
                }, 1);
            };

            wijinputcore.prototype._onDrop = function (e) {
                this._beforeSimulate();
                if (e.originalEvent && e.originalEvent.dataTransfer) {
                    var text = e.originalEvent.dataTransfer.getData('Text');
                    if (text) {
                        this._simulate(text);
                    }
                }
            };

            wijinputcore.prototype._stopEvent = function (e) {
                e.stopPropagation();
                e.preventDefault();
            };

            wijinputcore.prototype._calcSpinInterval = function () {
                this._repeatingCount++;
                if (this._repeatingCount > 10) {
                    return 50;
                } else if (this._repeatingCount > 4) {
                    return 100;
                } else if (this._repeatingCount > 2) {
                    return 200;
                }
                return 400;
            };

            wijinputcore.prototype._doSpin = function (up, repeating) {
                return false;
            };

            wijinputcore.prototype._stopSpin = function () {
                this.element.data('breakSpinner', true);
                this._repeatingCount = 0;

                var spintimer = this.element.data("spintimer");
                if (spintimer) {
                    clearTimeout(spintimer);
                    this.element.data("spintimer", undefined);
                }
            };

            wijinputcore.prototype._hasComboItems = function () {
                return !!this._getcomboItems() && this._getcomboItems().length;
            };

            wijinputcore.prototype._getcomboItems = function () {
                if (!!this.options.comboItems && this.options.comboItems.length > 0) {
                    return this.options.comboItems;
                }

                return this.options.pickers.list;
            };

            wijinputcore.prototype._getcomboWidth = function () {
                return this.options.comboWidth || this.options.pickers.width;
            };

            wijinputcore.prototype._getcomboHeight = function () {
                return this.options.comboHeight || this.options.pickers.height;
            };

            //Add comments by Ryanwu@20160520.
            //For fixing the issue#151957,152107.
            //_isComboListVisible(): boolean {
            //	if (!this._comboDiv) {
            //		return false;
            //	}
            //	return <any>this._comboDiv.wijpopup('isVisible');
            //}
            wijinputcore.prototype._clearBlurTimeout = function () {
                if (this._blurTimeout) {
                    clearTimeout(this._blurTimeout);
                    this._blurTimeout = null;
                }
            };

            wijinputcore.prototype._deferClearBlurTimeout = function () {
                var _this = this;
                setTimeout(function () {
                    _this._clearBlurTimeout();
                }, 50);
            };

            //end by RyanWu@20160520.
            wijinputcore.prototype._deleteComboDiv = function () {
                if (this._comboDiv == undefined) {
                    return;
                }

                this._comboDiv.wijlist("destroy");
                this._comboDiv.remove();
                delete this._comboDiv;
            };

            wijinputcore.prototype._createComboDiv = function () {
                var _this = this;
                if (this._comboDiv !== undefined) {
                    return;
                }

                this._comboDiv = $("<div></div>").appendTo(document.body).css('position', 'absolute');

                var content = this._normalize(this._getcomboItems());
                this._comboDiv.wijlist({
                    maxItemsCount: 5,
                    selected: function (event, ui) {
                        if (!_this.options.disableUserInput) {
                            _this._setData(ui.item.value);
                        }
                        _this._comboDiv.wijpopup('hide');
                        _this._trySetFocus();
                    }
                });

                this._comboDiv.wijlist('setItems', content);
                this._comboDiv.wijlist('renderList');
                this._comboDiv[0].removeAttribute("aria-activedescendant");
                this._comboDiv[0].removeAttribute("role");
                this._comboDiv[0].removeAttribute("aria-multiselectable");
            };

            wijinputcore.prototype._popupComboList = function () {
                var _this = this;
                if (!this._hasComboItems()) {
                    return false;
                }
                if (!this._allowEdit()) {
                    return false;
                }

                var divWidth = this.outerDiv.width();
                var comboWidth = this._getcomboWidth();
                var comboHeight = this._getcomboHeight();

                if (this._comboDiv != undefined) {
                    if (comboWidth && parseInt(comboWidth) !== this._comboDiv.width()) {
                        this._deleteComboDiv();
                    }
                }

                this._createComboDiv();

                // dimensions
                this._comboDiv.width(divWidth);
                this._comboDiv.wijlist("option", "autoSize", !comboHeight);
                if (comboHeight) {
                    this._comboDiv.height(comboHeight);
                }
                if (comboWidth) {
                    this._comboDiv.width(comboWidth);
                }

                this._comboDiv.wijlist("refreshSuperPanel");

                this._comboDiv.wijpopup({
                    autoHide: true,
                    hidden: function () {
                        _this._trigger('dropDownClose');
                        _this._wasPopupShowing = false;
                        _this._comboDiv.wijlist("unselectItems");
                        _this._comboDiv.wijlist("deactivate");
                    },
                    shown: function () {
                        _this._trigger('dropDownOpen');
                        _this._wasPopupShowing = true;
                    }
                });

                this._comboDiv.wijpopup('show', {
                    of: this.outerDiv,
                    offset: '0 4'
                });

                this._comboDiv.unbind("mousedown.combodiv").bind("mousedown.combodiv", function () {
                    _this._deferClearBlurTimeout();
                });
                return true;
            };

            wijinputcore.prototype._normalize = function (items) {
                // assume all items have the right format when the first item is complete
                if (items.length && items[0].label && items[0].value) {
                    return items;
                }
                return $.map(items, function (item) {
                    if (typeof item === "string") {
                        return {
                            label: item,
                            value: item
                        };
                    }
                    return $.extend({
                        label: item.label || item.value,
                        value: item.value || item.label
                    }, item);
                });
            };

            wijinputcore.prototype._processLeftRightKey = function (isLeft) {
                return false;
            };
            wijinputcore.prototype._processTabKey = function (e) {
                return false;
            };

            wijinputcore.prototype._moveControl = function (currentElement, isForward, isUseLeftRightKey) {
                var elements = CoreUtility.GetElements();
                var ret = null;
                var retInfo = {};
                if (elements.length < 2) {
                    return null;
                }

                var nextElement = CoreUtility.GetNextFocusableControl(currentElement, elements, isForward);
                var self = this;
                setTimeout(function () {
                    CoreUtility.SetElementFocus(nextElement);
                    self._trigger("keyExit");
                }, 0);
            };

            wijinputcore.prototype._processClearButton = function () {
            };
            return wijinputcore;
        })(wijmo.wijmoWidget);
        input.wijinputcore = wijinputcore;
        ;

        var wijinputClass = "wijmo-wijinput", classPrefix = wijinputClass + "-";

        var wijinputcore_options = (function () {
            function wijinputcore_options() {
                this.wijCSS = {
                    wijinput: wijinputClass,
                    wijinputInput: classPrefix + "input",
                    wijinputWrapper: classPrefix + "wrapper",
                    wijinputWrapperSpinnerLeft: classPrefix + "wrapper-spinner-left",
                    wijinputWrapperSpinnerRight: classPrefix + "wrapper-spinner-right",
                    wijinputTrigger: classPrefix + "trigger",
                    wijinputSpinnerLeft: classPrefix + "spinner-left",
                    wijinputSpinnerRight: classPrefix + "spinner-right",
                    wijinputButton: classPrefix + "button",
                    wijinputSpin: classPrefix + "spin",
                    wijinputSpinUp: classPrefix + "spinup",
                    wijinputSpinDown: classPrefix + "spindown",
                    glyphIcon: "glyphicon",
                    glyphIconPlus: "glyphicon-plus",
                    glyphIconMinus: "glyphicon-minus",
                    iconPlus: "ui-icon-plus",
                    iconMinus: "ui-icon-minus"
                };
                /** Determines the input method setting of widget.
                * Possible values are: 'auto', 'active', 'inactive', 'disabled'
                * @remarks
                * This property only take effect on IE and firefox browser.
                */
                this.imeMode = "";
                /** Determines the culture used to show values in the wijinput widget.
                */
                this.culture = '';
                /** Assigns the string value of the culture calendar that appears on the calendar.
                *   This option must work with culture option.
                */
                this.cultureCalendar = '';
                /** The CSS class applied to the widget when an invalid value is entered.
                * @remarks
                * For some property of the css, such as the color, because wijmo has set default style,
                * and it may be has a higher priority, so custom need to user a higher priority than the defualt.
                * @example
                * // This example sets the invalidClass option to "invalid".
                * .wijmo-wijinput.invalid {
                * color: red !important;
                * background-color: green !important;
                * font-size: xx-large;
                * }
                * $(".selector").wijinputcore("option", "invalidClass" "invalid");
                */
                this.invalidClass = $.wijmo.wijCSS.stateError;
                /** Determines the text displayed when the widget is blank and contains no initial text.
                * Obsoleted, use placeholder instead.
                * @ignore
                */
                this.nullText = undefined;
                /** Determines the text displayed when the widget is blank and contains no initial text.
                * @remarks
                * when the option's value is empty, the empty value will display, when the value is null, then the placeholder will not show.
                */
                this.placeholder = undefined;
                /** Shows the nullText value if the widget is blank and loses focus.
                * Obsoleted, when placeholder proerty has value, it will show the placeholder value, else not.
                * @ignore
                */
                this.showNullText = false;
                /** If true, then the browser response is disabled when the ENTER key is pressed.
                */
                this.hideEnter = false;
                /** Determines whether a user can enter a value in the wijinputdate widget.
                * Obsoleted, use readonly instead.
                * @ignore
                */
                this.disableUserInput = false;
                /** Determines whether a user can enter a value in the wijinput widget.
                * If readonly is true, user can't input value to the wijinput widget by ui operation, such as spin, pick value from pickers.
                */
                this.readonly = false;
                /** Determines the side, left or right, where the trigger or spinner buttons appear.
                * Possible values are: 'left', 'right'
                * Obsoleted, Use dropdownButtonAlign instead.
                * @ignore
                */
                this.buttonAlign = null;
                /** Determines the side, left or right, where the dropdown button appear.
                * Possible values are: 'left', 'right'
                */
                this.dropDownButtonAlign = 'right';
                /** Determines whether dropdown button is displayed.
                */
                this.showDropDownButton = false;
                /** Determines whether trigger button is displayed.
                * Obsoleted, use showDropDownButton instead.
                * @ignore
                */
                this.showTrigger = undefined;
                /** Determines whether spinner button is displayed.
                */
                this.showSpinner = false;
                /** Array of data items used to populate the drop-down list.
                * Obsoleted, use picker.list instead.
                * @ignore
                */
                this.comboItems = undefined;
                /** Determines the width of the drop-down list.
                * Obsoleted, use picker.width instead.
                * @ignore
                */
                this.comboWidth = undefined;
                /** Determines the height of the drop-down list.
                * Obsoleted, use picker.height instead.
                * @ignore
                */
                this.comboHeight = undefined;
                /** Determines whether the focus automatically moves to the next or previous
                * tab ordering control when pressing the left, right arrow keys.
                * Possible values are "none", "left", "right", "both".
                * The default value is "none".
                */
                this.blurOnLeftRightKey = "none";
                /** Determines the side, left or right, where the spinner button appear.
                * Possible values are: 'vertialLeft', 'verticalRight', 'horizontalDownLeft', 'horizontalUpLeft'.
                * The default value is 'verticalRight'.
                */
                this.spinnerAlign = "verticalRight";
                /** Determines whether the spin behavior can wrap when reaching a maximum or minimum limit.
                */
                this.allowSpinLoop = false;
                /** An object contains the settings for the dropdown list.
                * @example
                *  $(".selector").wijinputmask({
                *      pickers: {
                *          list: [
                *              { label: 'item1', value: 1 },
                *              { label: 'item2', value: 2 }
                *          ],
                *          width: 100,
                *          height: 130
                *      }
                *  });
                */
                this.pickers = {
                    list: undefined,
                    width: undefined,
                    height: undefined
                };
                /** The dropdownOpen event handler.
                * A function called before the widget's dropdown opened.
                * @event
                */
                this.dropDownOpen = null;
                /** The dropdownClose event handler.
                * A function called before the widget's dropdown closed.
                * @event
                */
                this.dropDownClose = null;
                /** The initializing event handler.
                * A function called before the widget is initialized.
                * @event
                */
                this.initializing = null;
                /** The initialized event handler.
                * A function called after the widget is initialized.
                * @event
                */
                this.initialized = null;
                /** The triggerMouseDown event handler. A function called
                * when the mouse is pressed down on the trigger button.
                * Obsoleted, use dropDownButtonMouseDown instead.
                * @ignore
                * @event
                */
                this.triggerMouseDown = null;
                /** The triggerMouseUp event handler. A function called
                * when the mouse is released on the trigger button.
                * Obsoleted, use dropDownButtonMouseUp instead.
                * @ignore
                * @event
                */
                this.triggerMouseUp = null;
                /** The dropdownButtonMouseDown event handler. A function called
                * when the mouse is pressed down on the dropdown button.
                * @event
                */
                this.dropDownButtonMouseDown = null;
                /** The dropdownButtonMouseUp event handler. A function called
                * when the mouse is released on the dropdown button.
                * @event
                */
                this.dropDownButtonMouseUp = null;
                /** Fired when the widget text is changed.
                * @event
                * @dataKey {String} text The new text.
                */
                this.textChanged = null;
                /** The invalidInput event handler. A function called
                * when invalid charactor is typed.
                * @event
                * @dataKey {String} char The newly input character.
                * @dataKey widget The widget object itself.
                */
                this.invalidInput = null;
                /** Fired when the widget lost focus and caused by the keyboard behavior.
                * @event
                */
                this.keyExit = null;
            }
            return wijinputcore_options;
        })();
        wijinputcore.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijinputcore_options());

        (function (MouseButton) {
            MouseButton[MouseButton["Default"] = -1] = "Default";
            MouseButton[MouseButton["Left"] = 0] = "Left";
            MouseButton[MouseButton["Middle"] = 1] = "Middle";
            MouseButton[MouseButton["Right"] = 2] = "Right";
        })(input.MouseButton || (input.MouseButton = {}));
        var MouseButton = input.MouseButton;
        ;

        /** @ignore */
        var CoreUtility = (function () {
            function CoreUtility() {
            }
            CoreUtility.GetBrowserType = function () {
                var ua = navigator.userAgent.toLowerCase();
                if (ua.indexOf("msie") != -1)
                    CoreUtility.ie = ua.match(/msie ([\d.]+)/)[1];
                else if (ua.indexOf("chrome") != -1) {
                    CoreUtility.chrome = ua.match(/chrome\/([\d.]+)/)[1];
                } else if (ua.indexOf("safari") != -1) {
                    var version = ua.match(/version\/([\d.]+)/);
                    if (version) {
                        CoreUtility.safari = version[1];
                    }
                } else if (ua.indexOf("firefox") != -1) {
                    CoreUtility.firefox = ua.match(/firefox\/([\d.]+)/)[1];
                } else if (ua.indexOf("opera") != -1) {
                    CoreUtility.opera = ua.match(/opera.([\d.]+)/)[1];
                }

                if (ua.indexOf("ipad") != -1 || ua.indexOf("iphone") != -1) {
                    CoreUtility.IPadAndIPhone = true;
                }

                // add by Sean Huang at 2008.11.13, for bug 10445 -->
                CoreUtility.engine = null;
                if (window.navigator.appName == "Microsoft Internet Explorer") {
                    // This is an IE browser. What mode is the engine in?
                    if (document.documentMode)
                        CoreUtility.engine = document.documentMode;
                    else {
                        CoreUtility.engine = 5; // Assume quirks mode unless proven otherwise
                        if (document.compatMode) {
                            if (document.compatMode == "CSS1Compat")
                                CoreUtility.engine = 7; // standards mode
                        }
                        if (CoreUtility.ie && CoreUtility.ie.indexOf("6") == 0) {
                            CoreUtility.engine = 6;
                        }
                    }
                    // the engine variable now contains the document compatibility mode.
                }

                if (ua.indexOf("rv:") !== -1 && ua.indexOf("firefox") === -1) {
                    // Support IE 11.
                    CoreUtility.ie = CoreUtility.engine = ua.match(/rv:([\d.]+)/)[1];
                }
            };

            CoreUtility.IsMouseDownOnClearButton = function (evt) {
                if (!CoreUtility.IsIE10OrLater()) {
                    return false;
                }

                for (var i = 0; i < document.styleSheets.length; i++) {
                    var styleSheets = document.styleSheets[i];
                    for (var j = 0; j < styleSheets.cssRules.length; j++) {
                        if (styleSheets.cssRules[j].selectorText == "::-ms-clear") {
                            if (styleSheets.cssRules[j].style.display == "none") {
                                return false;
                            }
                        }
                    }
                }

                var x = evt.offsetX;
                var y = evt.offsetY;
                var textbox = evt.srcElement || evt.target;
                var width = textbox.clientWidth;
                var height = textbox.clientHeight;
                var paddingLeft = parseInt(textbox.currentStyle.paddingLeft);
                var paddingRight = parseInt(textbox.currentStyle.paddingRight);
                if (textbox.readOnly || evt.button != 0 /* Left */) {
                    return false;
                }

                // DaryLuo 2012/09/06 fix bug 576, include padding.
                if (width - height + paddingLeft + paddingRight < CoreUtility.GetClearButtonShowThreshold(textbox)) {
                    return false;
                }
                var xx = width - height;
                if (x > xx && x <= width && y >= 0 && y < height) {
                    return true;
                } else {
                    return false;
                }
            };

            CoreUtility.CompareTextWithUnifiedNewline = function (text, textToCompare) {
                return text.replace(/(\r\n|\r)/g, "\n") != textToCompare.replace(/(\r\n|\r)/g, "\n");
            };

            CoreUtility.GetClearButtonShowThreshold = function (textinput) {
                // DaryLuo 2012/11/05 fix bug 861 in IM Web 7.0.
                // Previous I return this function to the harded value 66, in fact, it is incorrect.
                // After researched it, this value should be changed with the font.
                // The changed rule is linear.
                // When the font's unit is pixel, I got the following value.
                // The x indicated font's height, use meature method to get it.
                // The y indicated the clear button's show/hidden threshold value.
                // The I use matlab to get the changed rule. input the following script into matlabe, you will get the result.
                //x=[12 17 23  29 35  40 46 52 58 63 69 75 80],
                //y= [50 75 100 125 150 175 200 225 250 275 300 325 350],
                //p=polyfit(x,y,1),
                //xx=0:.1:100,
                //plot(x,y,'o',xx,polyval(p,xx)) ,poly2sym(p,'x')
                //r = poly2sym(p,'x')
                //vpa(r,8)
                // When the font's unit is Point, I got the following value.
                //x=[8 15 23 31 38 46 54 61 69 77 84],
                //y= [33 67 100 133 167 200 233 267 300 333 367],
                //p=polyfit(x,y,1),
                //xx=0:.1:100,
                //plot(x,y,'o',xx,polyval(p,xx)) ,poly2sym(p,'x')
                //r = poly2sym(p,'x')
                //vpa(r,8)
                var height = CoreUtility.MeasureText("ABCDQ", textinput).Height;
                var result = 4.3604432 * height - 0.76207324;
                result = Math.round(result);
                return result;
            };

            CoreUtility.GetClientOS = function () {
                // Add comments by Yang at 11:04 Sep. 6th 2007
                // For Get os information in firefox is different from IE.
                //var appVersion = navigator.appVersion;
                var appVersion;
                if (!CoreUtility.IsIE()) {
                    var osVersion = navigator.userAgent;
                    var start = osVersion.indexOf("(");
                    var end = osVersion.indexOf(")");
                    appVersion = osVersion.substring(start + 1, end);
                } else {
                    appVersion = navigator.appVersion;
                }

                // End by Yang
                if (appVersion.indexOf("NT 6.0") != -1) {
                    return "vista";
                } else if (appVersion.indexOf("NT 5.2") != -1) {
                    return "win2003";
                } else if (appVersion.indexOf("NT 5.1") != -1) {
                    return "winxp";
                } else if (appVersion.indexOf("NT 5.0") != -1) {
                    return "win2000";
                } else if (appVersion.indexOf("NT 6.1") != -1) {
                    return "Win7";
                } else if (appVersion.indexOf("NT 6.2") != -1) {
                    return "Win8";
                } else if (appVersion.indexOf("NT 6.3") != -1) {
                    // Windows 8.1
                    return "Win8";
                } else if (appVersion.indexOf("Android") != -1) {
                    return "Android";
                }
                return "unknow";
            };

            CoreUtility.MeasureText = function (text, domElement) {
                if (CoreUtility.MeasureElement === undefined) {
                    var div = document.createElement("div");
                    div.style.position = "absolute";
                    div.style.border = "solid 0px";
                    div.style.left = "-100000px";
                    div.style.top = "-100000px";
                    var textNode = window.document.createTextNode("");
                    div.appendChild(textNode);
                    document.body.appendChild(div);
                    CoreUtility.MeasureElement = div;
                    CoreUtility.MeasureTextElement = textNode;
                }
                var div = CoreUtility.MeasureElement;
                var textNode = CoreUtility.MeasureTextElement;

                if (document != null) {
                    var containsElement = document.body.contains(domElement);
                    if (!containsElement) {
                        document.body.appendChild(domElement);
                    }

                    var currentStyle = domElement.currentStyle || window.getComputedStyle(domElement, null);
                    div.style.fontFamily = currentStyle.fontFamily;
                    div.style.fontSize = currentStyle.fontSize;
                    div.style.fontStyle = currentStyle.fontStyle;
                    div.style.fontWeight = currentStyle.fontWeight;

                    if (!containsElement) {
                        document.body.removeChild(domElement);
                    }
                }

                var result = null;
                if (typeof (text) == "string") {
                    textNode.nodeValue = text;
                    result = { Width: div.clientWidth, Height: div.clientHeight };
                } else {
                    result = [];
                    for (var i = 0; i < text.length; i++) {
                        textNode.nodeValue = text[i];
                        result.push({ Width: div.clientWidth, Height: div.clientHeight });
                    }
                }

                return result;
            };

            CoreUtility.SetElementFocus = function (element) {
                element.focus();
            };

            CoreUtility.GetAllElements = function () {
                if (document.body.querySelectorAll) {
                    return document.body.querySelectorAll("button, input, object, select, textarea");
                }
                if (document.body.all) {
                    return document.body.all;
                }
                return document.body.getElementsByTagName("*");
            };

            CoreUtility.GetElements = function () {
                var elements = [];
                var obj = CoreUtility.GetAllElements();
                var index = 0;
                var rfocusable = /^(?:button|input|object|select|textarea)$/i;

                for (var i = 0; i < obj.length; i++) {
                    if ((!document.body.querySelectorAll || CoreUtility.IsIE()) && !rfocusable.test(obj[i].tagName.toLowerCase())) {
                        continue;
                    }

                    var c3 = !obj[i].disabled;
                    var c4 = obj[i].style.visibility !== "hidden";
                    var c5 = obj[i].type != "hidden" && obj[i].tabIndex != -1;
                    var c6 = obj[i].tagName.toLowerCase() == "textarea" && obj[i].tabIndex != -1;
                    var c7 = c5 || c6;

                    if (c3 && c4 && c7) {
                        elements[index++] = obj[i];
                    }
                }

                for (var i = 0; i < elements.length - 1; i++) {
                    for (var j = i + 1; j < elements.length; j++) {
                        if (elements[j].tabIndex < elements[i].tabIndex) {
                            var temp = elements[i];

                            elements[i] = elements[j];
                            elements[j] = temp;
                        }
                    }
                }
                return elements;
            };

            CoreUtility.GetNextFocusableControl = function (currentElement, elements, isForward) {
                if (typeof currentElement === "string") {
                    currentElement = document.getElementById(currentElement);
                }
                var index = 0;
                for (var i = 0; i < elements.length; i++) {
                    if (currentElement === elements[i]) {
                        if (isForward) {
                            index = (i + 1) % (elements.length);
                        } else {
                            index = (i - 1 + elements.length) % (elements.length);
                        }

                        break;
                    }
                }

                return elements[index];
            };

            CoreUtility.MoveFocus = function (curID, isForward) {
                var elements = CoreUtility.GetElements();
                var nextID = CoreUtility.GetNextFocusableControl(curID, elements, isForward);

                CoreUtility.SetElementFocus(nextID);
                return nextID;
            };

            CoreUtility.IsPad = function () {
                return CoreUtility.IPadAndIPhone || CoreUtility.IsAndroid();
            };

            CoreUtility.IsAndroid = function () {
                return CoreUtility.GetClientOS().toLowerCase() == "android";
            };

            CoreUtility.IsIE = function () {
                return CoreUtility.ie !== undefined;
            };

            CoreUtility.IsFireFox4OrLater = function () {
                return CoreUtility.firefox != null && parseFloat(CoreUtility.firefox) >= 4.0;
            };
            CoreUtility.IsIE11OrLater = function () {
                return CoreUtility.IsIE() && CoreUtility.engine >= 11;
            };
            CoreUtility.IsIE10OrLater = function () {
                return CoreUtility.IsIE() && CoreUtility.engine >= 10;
            };
            CoreUtility.IsIE9OrLater = function () {
                return CoreUtility.IsIE() && CoreUtility.engine >= 9;
            };
            CoreUtility.IsIE8OrLater = function () {
                return CoreUtility.IsIE() && CoreUtility.engine >= 8;
            };
            CoreUtility.IsIE8OrBelow = function () {
                return CoreUtility.IsIE() && CoreUtility.engine <= 8;
            };
            CoreUtility.IsIE8 = function () {
                return CoreUtility.IsIE() && CoreUtility.engine == 8;
            };
            CoreUtility.IsIE7 = function () {
                return CoreUtility.IsIE() && CoreUtility.engine == 7;
            };
            CoreUtility.IsIE7OrLater = function () {
                return CoreUtility.IsIE() && CoreUtility.engine >= 7;
            };

            CoreUtility.IsIE9 = function () {
                return CoreUtility.IsIE() && CoreUtility.engine == 9;
            };
            return CoreUtility;
        })();
        input.CoreUtility = CoreUtility;
        CoreUtility.GetBrowserType();
    })(wijmo.input || (wijmo.input = {}));
    var input = wijmo.input;
})(wijmo || (wijmo = {}));
;
/// <reference path="../external/declarations/globalize.d.ts"/>
/// <reference path="jquery.wijmo.wijstringinfo.ts"/>
/// <reference path="../Base/jquery.wijmo.widget.ts"/>
/// <reference path="jquery.wijmo.wijcharex.ts" />
/// <reference path="jquery.wijmo.wijinputcore.ts"/>
var wijmo;
(function (wijmo) {
    (function (input) {
        

        /** @ignore */
        var Utility = (function () {
            function Utility() {
            }
            //static FireEvent(oControl, eventHandler, eArgs: any, eventName: string) {
            //    oControl.owner._trigger(eventName, null, eArgs);
            //}
            Utility.FireEvent = function (oControl, eventHandler, eArgs, eventName) {
                if (!eventHandler) {
                    return false;
                }
                try  {
                    // DaryLuo 2012/10/29 fix bug 837 in IM Web 7.0.
                    eventHandler.call(window, oControl, eArgs);
                } catch (ex) {
                    return false;
                }
                return true;
            };

            Utility.FindIMControl = function (id) {
            };

            Utility.ArrayIndexOf = function (array, obj) {
                if (array.indeOf) {
                    return array.indexOf(obj);
                } else {
                    for (var i = 0; i < array.length; i++) {
                        if (array[i] === obj) {
                            return i;
                        }
                    }
                }
                return -1;
            };

            Utility.AttachEvent = function (element, type, handler, useCapture) {
                if (element !== null && element !== undefined) {
                    if (element.addEventListener) {
                        element.addEventListener(type, handler, useCapture);
                    } else if (element.attachEvent) {
                        element.attachEvent("on" + type, handler);
                    }
                }
            };

            Utility.AttachFocusEventOfDocument = function () {
                if (input.CoreUtility.IsIE8OrBelow()) {
                    Utility.AttachEvent(document, "beforeactivate", function (evt) {
                        Utility.FocusControlUpdate(evt);
                    }, true);
                } else {
                    Utility.AttachEvent(document, "focus", function (evt) {
                        Utility.FocusControlUpdate(evt);
                    }, true);
                }
            };

            Utility.FocusControlUpdate = function (evt) {
                Utility.PreviousFocusControl = Utility.FocusControl;
                Utility.FocusControl = evt.target || evt.srcElement;
            };

            Utility.ToString = function (value, length, ch, position) {
                var val = value + "";

                //It is same as String.PadLeft(int, char) in C#.
                if (ch != null) {
                    while (val.length < length) {
                        if (position) {
                            val = val + ch;
                        } else {
                            val = ch + val;
                        }
                    }

                    return val;
                }

                while (val.length < length) {
                    val += value + "";
                }

                return val;
            };

            //Added by Jeff Wu. For CursorPosition Test
            Utility.GetSelectionEndPosition = function (obj) {
                // Add comments by Yang
                // For test firefox
                if (!input.CoreUtility.IsIE() || input.CoreUtility.IsIE11OrLater()) {
                    //Commented by Kevin, Feb 17, 2009
                    //bug#1890
                    //return obj.selectionEnd;
                    var endS = 0;
                    endS = obj.selectionEnd;
                    if (obj.value) {
                        var text = obj.value.substring(0, endS);
                        endS = text.GetLength();
                    }

                    //Commented by Kevin, Feb 18, 2009
                    //bug#1894
                    var startS = 0;
                    startS = obj.selectionStart;
                    if (obj.value) {
                        var text = obj.value.substring(0, startS);
                        startS = text.GetLength();
                    }

                    if (startS > endS) {
                        endS = startS;
                    }

                    //end by Kevin
                    return endS;
                    //end by Kevin
                }

                // End by Yang
                return Utility.GetSelectionStartPosition(obj) + document.selection.createRange().text.GetLength();
            };

            Utility.GetSelectionStartPosition = function (obj) {
                if (obj.selectionStart != null) {
                    var startS = 0;
                    startS = obj.selectionStart;
                    if (obj.value) {
                        var text = obj.value.substring(0, startS);
                        startS = text.GetLength();
                    }

                    var endS = 0;
                    endS = obj.selectionEnd;
                    if (obj.value) {
                        var text = obj.value.substring(0, endS);
                        endS = text.GetLength();
                    }

                    if (endS < startS) {
                        startS = endS;
                    }

                    return startS;
                }
                try  {
                    var rng = obj.createTextRange();
                    var sng = document.selection.createRange();
                    var length = obj.value.GetLength();
                    var start = 0;
                    var end = length;
                    var i = 0;

                    while (start < end) {
                        i = Math.floor((start + end) / 2);
                        rng = obj.createTextRange();

                        var s = i;
                        var text = obj.value.Substring(0, i);
                        while (1) {
                            var index = text.IndexOf("\r\n");
                            if (index != -1) {
                                s--;
                                text = text.Substring(index + 2, text.GetLength());
                            } else {
                                break;
                            }
                        }

                        var gap = i - s;
                        s = i - gap;

                        rng.moveStart("character", s);

                        if (rng.offsetTop > sng.offsetTop) {
                            end = i;
                        } else if (rng.offsetTop < sng.offsetTop) {
                            if (start == i) {
                                return end;
                            }
                            start = i;
                        } else if (rng.offsetLeft > sng.offsetLeft) {
                            end = i;
                        } else if (rng.offsetLeft < sng.offsetLeft) {
                            if (start == i) {
                                return end;
                            }
                            start = i;
                        } else {
                            if (obj.value.Substring(i - 1, i) == "\r") {
                                i++;
                            }
                            return i;
                        }
                    }
                    return length;
                } catch (e) {
                    return 0;
                }
            };

            Utility.GetCursorPosition = function (obj, isPropertyChange) {
                if (obj == null) {
                    return -1;
                }

                // Add comments by Yang
                // For test firefox
                if (!input.CoreUtility.IsIE() || input.CoreUtility.IsIE11OrLater()) {
                    //Commented by Kevin, Feb 17, 2009
                    //bug#1890
                    //return obj.selectionStart;
                    var startS = 0;
                    startS = obj.selectionStart;
                    if (obj.value) {
                        var text = obj.value.substring(0, startS);
                        startS = text.GetLength();
                    }

                    return startS;
                    //end by Kevin
                }

                // End by Yang
                // Frank Liu fixed bug 629 at 2013/06/20.
                var caretPos = 0;
                if (document.selection) {
                    obj.focus();
                    var sel = document.selection.createRange();
                    sel.moveStart('character', -obj.value.length);
                    caretPos = sel.text.length;
                }
                return (caretPos);
            };

            Utility.GetPasteData = function (useClipboard) {
                // Add comments by Yang
                // For test firefox
                return Utility.GetDataFromClipboard(useClipboard);
            };

            Utility.GetDataFromClipboard = function (useClipboard) {
                if (useClipboard == false) {
                    return Utility.SavedText;
                }

                if (window.clipboardData) {
                    return (window.clipboardData.getData('Text'));
                } else if (Utility.CutCopyPasteEventObject !== null) {
                    if (Utility.CutCopyPasteEventObject.clipboardData !== undefined) {
                        return Utility.CutCopyPasteEventObject.clipboardData.getData("text");
                    }
                }

                //else if (window.netscape) {
                //    try {
                //        netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
                //        var clip = Components.classes['@mozilla.org/widget/clipboard;1'].createInstance(Components.interfaces.nsIClipboard);
                //        if (!clip) {
                //            return;
                //        }
                //        var trans = Components.classes['@mozilla.org/widget/transferable;1'].createInstance(Components.interfaces.nsITransferable);
                //        if (!trans) {
                //            return;
                //        }
                //        trans.addDataFlavor('text/unicode');
                //        clip.getData(trans, clip.kGlobalClipboard);
                //        var str = new Object();
                //        var len = new Object();
                //        try {
                //            trans.getTransferData('text/unicode', str, len);
                //        }
                //        catch (error) {
                //            return null;
                //        }
                //        if (str) {
                //            if (Components.interfaces.nsISupportsWString) {
                //                str = str.value.QueryInterface(Components.interfaces.nsISupportsWString);
                //            }
                //            else if (Components.interfaces.nsISupportsString) {
                //                str = str.value.QueryInterface(Components.interfaces.nsISupportsString);
                //            }
                //            else {
                //                str = null;
                //            }
                //        }
                //        if (str) {
                //            return (str.data.substring(0, len.value / 2));
                //        }
                //    }
                //    catch (e) {
                //        window.status = "about:config signed.applets.codebase_principal_support true";
                //    }
                //}
                return null;
            };

            Utility.ClearSelection = function (inputElement) {
                if (input.CoreUtility.IsIE() && !input.CoreUtility.IsIE11OrLater()) {
                    if (document.selection.createRange().text != "") {
                        document.selection.empty();
                    }
                } else {
                    if (Utility.GetSelectionText(inputElement) != "") {
                        inputElement.selectionStart = inputElement.value.length;
                        inputElement.selectionEnd = inputElement.selectionStart;
                    }
                }
            };

            Utility.GetSelectionText = function (obj) {
                if (obj.selectionStart != null) {
                    return obj.value.substring(obj.selectionStart, obj.selectionEnd);
                } else if (document.selection != null) {
                    return document.selection.createRange().text;
                } else if (document.activeElement !== null) {
                    var obj = document.activeElement;

                    //var start = Math.Min(document.activeElement.selectionStart,document.activeElement.selectionEnd);
                    //var end = Math.Max(document.activeElement.selectionStart,document.activeElement.selectionEnd);
                    var start = obj.selectionStart;
                    var end = obj.selectionEnd;
                    return obj.value.substring(start, end);
                }

                return "";
            };

            Utility.FireSystemEvent = function (obj, eventName) {
                if (input.CoreUtility.IsIE()) {
                    obj.fireEvent(eventName);
                } else {
                    var evt = document.createEvent('HTMLEvents');

                    //We must remove the eventName's first two characters "on". For example,
                    //we should remove the "onchange" to "change".
                    evt.initEvent(eventName.substring(2, eventName.length), true, true);
                    obj.dispatchEvent(evt);
                }
            };

            Utility.GetTextBoxScrollWidth = function (inputElement, unuse) {
                return input.CoreUtility.MeasureText(inputElement.value, inputElement).Width;
            };

            Utility.CheckInt = function (value, min, max) {
                var intValue = parseInt(value);
                if (isNaN(intValue)) {
                    throw "value is invalid";
                }
                if (intValue < min || intValue > max) {
                    throw value + " is out of range, should between " + min + " and " + max;
                }
                return intValue;
            };

            Utility.CheckFloat = function (value, min, max) {
                var intValue = parseFloat(value);
                if (isNaN(intValue)) {
                    throw "value is invalid";
                }
                if (value < min || value > max) {
                    throw value + " is out of range, should between " + min + " and " + max;
                }
                return intValue;
            };

            Utility.CheckDate = function (value, min, max) {
                if (!(value instanceof Date)) {
                    throw "Type is invalid";
                }
                if (isNaN(value)) {
                    throw "Date is a invalid date";
                }

                if (max != undefined) {
                    if (value < min || value > max) {
                        throw value + " is out of range, should between " + min + " and " + max;
                    }
                }
            };

            Utility.CheckBool = function (boolValue) {
                if (typeof (boolValue) === "string") {
                    if (boolValue.toLowerCase() === "true") {
                        return true;
                    }
                }
                return boolValue == true;
            };

            Utility.CheckFunction = function (fun) {
                if (fun === undefined || fun === null) {
                    return null;
                }

                if (typeof fun == "string") {
                    fun = Utility.Trim(fun);
                    if (fun.length == 0) {
                        return null;
                    }
                    try  {
                        eval("fun =" + fun);
                    } catch (e) {
                    }
                }

                if (typeof fun == "function") {
                    return fun;
                } else {
                    throw "The value is not a valid function";
                }
            };

            Utility.GetCheckElement = function () {
                if (Utility.CheckElement == null) {
                    var div = document.createElement("div");
                    Utility.CheckElement = div;
                    div.style.display = "none";
                }
                return Utility.CheckElement;
            };

            Utility.CheckString = function (str) {
                if (str == null) {
                    str = "";
                }
                if (str === undefined || (typeof (str) != "string" && !(str instanceof String))) {
                    throw str + " type is not a string.";
                }

                return str.toString();
            };

            Utility.GetCSSLength = function (length) {
                var intValue = parseInt(length);
                if (isNaN(intValue)) {
                    return 0;
                }
                return intValue;
            };

            Utility.CheckCSSLength = function (length) {
                length = Utility.CheckInt(length, 0, Math.pow(2, 31));

                if (parseInt(length) == length) {
                    length += "px";
                }
                Utility.GetCheckElement().style.width = "";
                Utility.GetCheckElement().style.width = length;
                return Utility.GetCheckElement().style.width;
            };

            Utility.CheckFontSizeValue = function (length) {
                if (parseInt(length) == length) {
                    length += "px";
                }
                Utility.GetCheckElement().style.fontSize = "";
                Utility.GetCheckElement().style.fontSize = length;
                return Utility.GetCheckElement().style.fontSize;
            };

            Utility.CheckColor = function (color) {
                Utility.GetCheckElement().style.backgroundColor = "";
                Utility.GetCheckElement().style.backgroundColor = color;
                return Utility.GetCheckElement().style.backgroundColor;
            };

            Utility.CheckImageUrl = function (url) {
                return Utility.CheckString(url);
            };

            Utility.GetCssImageUrl = function (url) {
                if (url.startWith("url(\"")) {
                    url = url.substring(5, url.length - 2);
                } else if (url.startWith("url(")) {
                    url = url.substring(4, url.length - 1);
                }
                return url;
            };

            Utility.CheckCssImageUrl = function (url) {
                if (url.length > 0 && !url.startWith("url(")) {
                    url = "url(" + url + ")";
                }
                Utility.GetCheckElement().style.backgroundImage = "";
                Utility.GetCheckElement().style.backgroundImage = url;
                return Utility.GetCheckElement().style.backgroundImage;
            };

            Utility.CheckEnum = function (type, value) {
                for (var item in type) {
                    if (type[item] == value || type[item] == value.toLowerCase()) {
                        return type[item];
                    }
                }
                throw "Enum value is invalid";
            };

            Utility.CheckChar = function (value) {
                value = Utility.CheckString(value);

                // Frank Liu fixed bug 678 at 2013/06/14.
                if (value.length !== 1) {
                    throw "Invalid value";
                    //value = value.Substring(0, 1);
                }
                return value;
            };

            Utility.GetMultipleStringEnum = function (value) {
                var valueList = value.split(" ");
                valueList.sort();
                return valueList.join(",");
            };

            Utility.CheckMultipleStringEnum = function (type, value) {
                var valueList = value.split(",");
                var result = [];
                for (var i = 0; i < valueList.length; i++) {
                    result.push(Utility.CheckEnum(type, Utility.Trim(valueList[i])));
                }
                return result.join(" ");
            };

            Utility.EncodingToHTML = function (text) {
                if (text.IndexOf("&") != -1) {
                    var tempDispText = text;
                    var tempText = "";
                    while (tempDispText.IndexOf("&") != -1) {
                        var findPosition = tempDispText.IndexOf("&");
                        tempDispText = tempDispText.replace("&", "&amp;");
                        tempText += tempDispText.Substring(0, findPosition + 5);
                        tempDispText = tempDispText.Substring(findPosition + 5, tempDispText.GetLength());
                    }
                    if (tempDispText.IndexOf("&") == -1 && tempDispText != "") {
                        tempText += tempDispText;
                    }
                    text = tempText;
                }

                while (text.IndexOf(' ') != -1) {
                    text = text.replace(" ", "&nbsp;");
                }

                while (text.IndexOf("<") != -1) {
                    text = text.replace("<", "&lt;");
                }

                while (text.IndexOf(">") != -1) {
                    text = text.replace(">", "&gt;");
                }
                return text;
            };

            Utility.DecodingFromHTML = function (text) {
                while (text.IndexOf("&nbsp;") != -1) {
                    text = text.replace("&nbsp;", " ");
                }

                while (text.IndexOf("&lt;") != -1) {
                    text = text.replace("&lt;", "<");
                }

                while (text.IndexOf("&gt;") != -1) {
                    text = text.replace("&gt;", ">");
                }

                //Modified by shenyuan at 2006-02-10 for bug #5206.
                if (text.IndexOf("&amp;") != -1) {
                    var tmpText = text;
                    var tmpResult = "";
                    while (tmpText.IndexOf("&amp;") != -1) {
                        var temPos = tmpText.IndexOf("&amp;");
                        tmpText = tmpText.replace("&amp;", "&");
                        tmpResult += tmpText.Substring(0, temPos + 1);
                        tmpText = tmpText.Substring(temPos + 1, tmpText.GetLength());
                    }
                    if (tmpText.IndexOf("&amp;") == -1 && tmpText != "") {
                        tmpResult += tmpText;
                    }
                    text = tmpResult;
                }
                return text;
            };

            Utility.IsStandCompliantModeOn = function () {
                //Commented by Kevin, Nov 11, 2008
                //fix bug#10414
                //return document.compatMode == "CSS1Compat";
                if (!input.CoreUtility.IsIE()) {
                    return document.compatMode == "CSS1Compat" || document.compatMode == "BackCompat";
                }
                return document.compatMode == "CSS1Compat";
                //end by Kevin
            };

            Utility.GetPageZoomRate = function () {
                // add by Sean Huang at 2008.11.13, for bug 10129, 10368 -->
                if (input.CoreUtility.IsIE8()) {
                    return screen.deviceXDPI / screen.logicalXDPI;
                }

                // add by Sean Huang at 2008.11.13, for bug 10129, 10368 -->
                var normalPosition = document.getElementById("gcsh_standard_control_for_get_normal_position");
                if (typeof (normalPosition) != "undefined" && normalPosition != null) {
                    return document.getElementById("gcsh_standard_control_for_get_normal_position").offsetLeft / 100;
                } else {
                    var div = document.createElement("div");
                    document.body.appendChild(div);
                    div.id = "gcsh_standard_control_for_get_normal_position";
                    div.style.visibility = "hidden";
                    div.style.left = "100px";
                    div.style.top = "1px";
                    div.style.width = "1px";
                    div.style.height = "1px";
                    div.style.position = "absolute";

                    return document.getElementById("gcsh_standard_control_for_get_normal_position").offsetLeft / 100;
                    // return 1;
                }
            };

            Utility.GetElementPosition = function (id) {
                // Frank Liu fixed bug 612 at 2013/06/09.
                // HelenLiu 2013/07/02 fix bug 742 in IM HTML5.
                if (input.CoreUtility.IsIE() || input.CoreUtility.chrome || input.CoreUtility.safari) {
                    // change by Sean Huang at 2009.04.10, for bug 2125 -->
                    //return Utility.GetElementPositionForIE(id);
                    //modified by sj for bug 12220
                    //if (Utility.engine == 8)
                    if (input.CoreUtility.IsIE8OrLater()) {
                        var pos1 = Utility.GetElementPositionForIE8(id);

                        // DaryLuo 2012.09/10 fix bug 561 in IMWeb 7.0.
                        if (pos1.Left == 0 && pos1.Top == 0) {
                            var pos2 = Utility.GetElementPositionForFireFox(id);
                            return pos2;
                        } else {
                            return pos1;
                        }
                    } else {
                        var posIE7 = Utility.GetElementPositionForIE(id);

                        //  var posIE8 = Utility.GetElementPositionForIE8(id);
                        //  var posFF = Utility.GetElementPositionForFireFox(id);
                        // DaryLuo 2012.09/10 fix bug 561 in IMWeb 7.0.
                        //  var left = Utility.ChooseMiddle(posIE7.Left, posIE8.Left, posFF.Left);
                        //  var top = Utility.ChooseMiddle(posIE7.Top, posIE8.Top, posFF.Top);
                        return { Left: posIE7.Left, Top: posIE7.Top };
                    }
                    // end of Sean Huang <--
                }

                return Utility.GetElementPositionForFireFox(id);
            };

            Utility.GetElementPositionForIE8 = function (id) {
                var element = id;
                if (typeof id == "string") {
                    element = document.getElementById(id);
                }

                var top = 0;
                var left = 0;

                if (element == null || element.self || element.nodeType === 9) {
                    return { Left: left, Top: top };
                }

                var clientRect = element.getBoundingClientRect();
                if (!clientRect) {
                    return { Left: left, Top: top };
                }
                var documentElement = element.ownerDocument.documentElement;
                left = clientRect.left + documentElement.scrollLeft;
                top = clientRect.top + documentElement.scrollTop;

                try  {
                    var f = element.ownerDocument.parentWindow.frameElement || null;
                    if (f) {
                        var offset = (f.frameBorder === "0" || f.frameBorder === "no") ? 2 : 0;
                        left += offset;
                        top += offset;
                    }
                } catch (ex) {
                }

                return { Left: left, Top: top };
            };

            Utility.GetElementPositionForIE = function (id) {
                var oElement = id;
                if (typeof id == "string") {
                    oElement = document.getElementById(id);
                }

                // For bug 3696.
                var top = 0;
                var left = 0;

                if (oElement == null) {
                    return { Left: left, Top: top };
                }

                if (oElement.offsetParent) {
                    while (oElement.offsetParent != null) {
                        var parent = oElement.offsetParent;
                        var parentTagName = parent.tagName.toLowerCase();

                        if (parentTagName != "table" && parentTagName != "body" && parentTagName != "html" && parent.clientTop && parent.clientLeft) {
                            left += parent.clientLeft;
                            top += parent.clientTop;
                        }

                        // add by Sean Huang at 2008.11.12, for bug 10064
                        // change by Sean Huang at 2008.11.13, for bug 10445 -->
                        //if (Utility.IsIE7() && parent.style.position.toLowerCase() == "relative")
                        if (input.CoreUtility.IsIE7() && parent.style.position.toLowerCase() == "relative") {
                            left += oElement.offsetLeft - oElement.scrollLeft;
                            top += oElement.offsetTop;

                            // add by Sean Huang at 2009.01.07, for bug 856 -->
                            var zoom = Utility.GetPageZoomRate();
                            if (zoom == 1) {
                                var offset = oElement.offsetTop;
                                for (var i = 0; i < parent.children.length; i++) {
                                    var o = parent.children[i];
                                    if (o == oElement) {
                                        break;
                                    } else if (o.offsetTop) {
                                        offset = o.offsetTop;
                                        break;
                                    }
                                }
                                top -= offset;
                            }
                        } else if (Utility.IsStandCompliantModeOn() && input.CoreUtility.IsIE7() && (oElement.style.position.toLowerCase() == "absolute" || oElement.style.position.toLowerCase() == "relative")) {
                            // change by Sean Huang at 2009.01.07, for bug 856 -->
                            // [original] -->
                            //  // change by Sean Huang at 2008.12.18, for bug 896 -->
                            //  //top  += (oElement.offsetTop - oElement.scrollTop) / Utility.GetPageZoomRate();
                            //  //left += (oElement.offsetLeft - oElement.scrollLeft) / Utility.GetPageZoomRate();
                            //  top  += (oElement.offsetTop - oElement.scrollTop);
                            //  left += (oElement.offsetLeft - oElement.scrollLeft);
                            //  // end of Sean Huang <--
                            // <-- [original]
                            var zoom = Utility.GetPageZoomRate();
                            top += (oElement.offsetTop - oElement.scrollTop) / zoom;
                            left += (oElement.offsetLeft - oElement.scrollLeft) / zoom;
                            // end of Sean Huang, for bug 856 <--
                        } else {
                            //Add by Jiang at Dec. 10 2008
                            //For fixed bug773
                            if ((oElement.tagName.toLowerCase() == "input" && oElement.type.toLowerCase() == "text") || oElement.tagName.toLowerCase() == "textarea") {
                                top += oElement.offsetTop;
                                left += oElement.offsetLeft;
                            } else {
                                top += oElement.offsetTop - oElement.scrollTop;
                                left += oElement.offsetLeft - oElement.scrollLeft;
                            }
                            //End by Jiang Changcheng
                        }

                        oElement = parent;
                        //end by Ryan Wu.
                    }
                } else if (oElement.left && oElement.top) {
                    left += oElement.left;
                    top += oElement.top;
                } else {
                    if (oElement.x) {
                        left += oElement.x;
                    }
                    if (oElement.y) {
                        top += oElement.y;
                    }
                }

                //Add by Ryan Wu at 11:13, Nov 2 2005. For in VS2005, body has also an offset value.
                if (oElement.style.position.toLowerCase() != "relative" && oElement.style.position.toLowerCase() != "absolute" && oElement.tagName.toLowerCase() == "body" && Utility.IsStandCompliantModeOn()) {
                    //Add comments by Ryan Wu at 9:54 Nov. 15 2006.
                    //Fix bug#6695.
                    //	    top  += oElement.offsetTop;
                    //		left += oElement.offsetLeft;
                    // change by Sean Huang at 2008.11.13, for bug 10445 -->
                    //if (!Utility.IsIE7())
                    if (!input.CoreUtility.IsIE7()) {
                        top += oElement.offsetTop;
                        left += oElement.offsetLeft;
                    } else {
                        // Add comments by Yang at 13:23 July 16th 2008
                        // For fix the bug 9755
                        //            top  += parseInt(oElement.currentStyle.marginTop);
                        //		    left += parseInt(oElement.currentStyle.marginLeft);
                        var tempTop = parseInt(oElement.currentStyle.marginTop);
                        var tempLeft = parseInt(oElement.currentStyle.marginLeft);
                        if (isNaN(tempTop)) {
                            tempTop = 0;
                        }
                        if (isNaN(tempLeft)) {
                            tempLeft = 0;
                        }
                        top += tempTop;
                        left += tempLeft;
                        // End by Yang
                    }
                    //end by Ryan Wu.
                }

                return { Left: left, Top: top };
            };

            Utility.GetElementPositionForFireFox = function (id) {
                var oElement = id;
                if (typeof id == "string") {
                    oElement = document.getElementById(id);
                }

                // For bug 3696.
                var top = 0;
                var left = 0;
                var scrollLeft = 0;
                var scrollTop = 0;

                if (oElement == null) {
                    return { Left: left, Top: top };
                }

                //Gets the offsetTop and offsetLeft.
                if (oElement.offsetParent) {
                    while (oElement.offsetParent != null) {
                        var parentTagName = oElement.offsetParent.tagName.toLowerCase();

                        if (parentTagName != "table" && parentTagName != "body" && parentTagName != "html" && parentTagName != "div" && oElement.offsetParent.clientTop && oElement.offsetParent.clientLeft) {
                            left += oElement.offsetParent.clientLeft;
                            top += oElement.offsetParent.clientTop;
                        }

                        top += oElement.offsetTop;
                        left += oElement.offsetLeft;

                        oElement = oElement.offsetParent;
                    }
                } else if (oElement.left && oElement.top) {
                    left += oElement.left;
                    top += oElement.top;
                } else {
                    if (oElement.x) {
                        left += oElement.x;
                    }
                    if (oElement.y) {
                        top += oElement.y;
                    }
                }

                //Gets the scrollTop and scrollLeft.
                oElement = id;
                if (typeof id === "string") {
                    oElement = document.getElementById(id);
                }

                if (oElement.parentElement) {
                    while (oElement.parentElement != null && oElement.tagName.toLowerCase() != "html") {
                        scrollTop += oElement.scrollTop;
                        scrollLeft += oElement.scrollLeft;

                        oElement = oElement.parentElement;
                    }
                }

                top -= scrollTop;
                left -= scrollLeft;

                //Add by Ryan Wu at 11:13, Nov 2 2005. For in VS2005, body has also an offset value.
                if (oElement.style.position.toLowerCase() != "relative" && oElement.style.position.toLowerCase() != "absolute" && oElement.tagName.toLowerCase() == "body" && Utility.IsStandCompliantModeOn()) {
                    top += oElement.offsetTop;
                    left += oElement.offsetLeft;
                }

                return { Left: left, Top: top };
            };

            Utility.GetOSDefaultFontFamily = function () {
                switch (input.CoreUtility.GetClientOS().toLowerCase()) {
                    case "winxp":
                        return "MS UI Gothic";
                    case "vista":
                        return "�ᥤ�ꥪ";
                    case "win7":
                        return "�ᥤ�ꥪ";
                    case "win8":
                        return "Meiryo UI";
                    case "win2003":
                        return "MS UI Gothic";
                    case "win2000":
                        return "MS UI Gothic";
                }
                return "MS UI Gothic";
            };

            Utility.IsTouchSupport = function () {
                return window.navigator.userAgent.toLowerCase().indexOf("touch") != -1;
            };

            Utility.DisabledHoldVisual = function (element) {
                if (element !== null && element !== undefined && Utility.IsTouchSupport() && input.CoreUtility.IsIE10OrLater()) {
                    element.addEventListener("MSHoldVisual", function (e) {
                        e.preventDefault();
                    }, false);
                    element.addEventListener("MSGestureHold", function (e) {
                        e.preventDefault();
                    }, false);

                    // Disables visual
                    element.addEventListener("contextmenu", function (e) {
                        e.preventDefault();
                    }, false);
                }
            };

            Utility.IsFocusFromIMControl = function (id, evt) {
                try  {
                    //return event.fromElement.className.IndexOf(Utility.DefaultControlStyle) != -1;
                    var src = evt.fromElement;
                    while (src != null) {
                        // change by Sean Huang at 2008.08.14, for bug 614 and 644 (ttp)-->
                        //if (src.id.Substring(0, id.length) == id)
                        //modified by sj for bug 2149
                        //if (src.id == id ||  src.id == id + this.Hold + "_DropDownObj" || src.id == id + "DropDown_Container" || src.id == id+ "_ContextMenu")
                        if (src.id == id || src.id == id + this.Hold + "_DropDownObj" || src.id == id + "_DropDown_Container" || src.id == id + "_ContextMenu" || src.id == id + "_HistoryList" || src.id == id + "_EditField" || src.id == id + "_BorderContainer" || src.id == id + "_DropDown_EditField") {
                            return true;
                        }

                        //Add comments by Ryan Wu at 11:28 Mar. 15 2007.
                        //For test FireFox.
                        //src = src.parentElement;
                        src = src.parentNode;
                        //end by Ryan Wu.
                    }
                    return false;
                } catch (e) {
                    return false;
                }
            };

            Utility.IsFocusToIMControl = function (id, evt) {
                try  {
                    //	return event.toElement.className.IndexOf(Utility.DefaultControlStyle) != -1;
                    var src = evt.toElement;

                    while (src != null) {
                        //Add comments by Ryan Wu at 17:13 Aug. 22 2007.
                        //For fix the bug8990.
                        //if (src.id && src.id.substring(0, id.length) == id)
                        //add by chris for 12215 (bugzilla) 2010/12/17 16:30
                        //			// change by Sean Huang at 2008.08.14, for bug 614 and 644 (ttp)-->
                        //			//if (src.id && src.id == id)
                        //			//modified by sj for bug 2149
                        //			//if (src.id == id || src.id == id + this.Hold + "_DropDownObj" || src.id == id + "DropDown_Container" || src.id == id+ "_ContextMenu")
                        //			if (src.id == id || src.id == id + this.Hold + "_DropDownObj" || src.id == id + "DropDown_Container" || src.id == id + "_ContextMenu" || src.id == id + "_HistoryList")
                        //			//end by sj
                        //			// end of Sean Huang <--
                        if (src.id == id || src.id == id + this.Hold + "_DropDownObj" || src.id == id + "_DropDown_Container" || src.id == id + "_ContextMenu" || src.id == id + "_HistoryList" || src.id == id + this.Hold + "_DropDownObj_PopupMonth" || src.id == id + "_EditField" || src.id == id + "_BorderContainer" || src.id == id + "_DropDown_EditField") {
                            return true;
                        }

                        //end by Ryan Wu.
                        //Add comments by Ryan Wu at 11:28 Mar. 15 2007.
                        //For test FireFox.
                        //src = src.parentElement;
                        src = src.parentNode;
                        //end by Ryan Wu.
                    }
                    return false;
                } catch (e) {
                    return false;
                }
            };

            Utility.Trim = function (value) {
                if (value == "") {
                    return "";
                }

                var beginIndex = 0;
                var endIndex = 0;
                for (var i = 0; i < value.length; i++) {
                    if (value.CharAt(i) != " " && value.CharAt(i) != "��") {
                        beginIndex = i;
                        break;
                    }
                }

                for (var i = value.length - 1; i >= 0; i--) {
                    if (value.CharAt(i) != " " && value.CharAt(i) != "��") {
                        endIndex = i + 1;
                        break;
                    }
                }

                try  {
                    var s = value.Substring(beginIndex, endIndex);
                    return s;
                } catch (e) {
                    return value;
                }
            };

            Utility.GetTouchPath = function (beginY, endY) {
                if (beginY === -1 || endY === -1) {
                    return "Error";
                }

                if (beginY > endY) {
                    return beginY - endY > 20 ? "ToTop" : "NotMove";
                } else if (beginY < endY) {
                    return endY - beginY > 20 ? "ToBottom" : "NotMove";
                }

                return "NotMove";
            };

            Utility.IsJapan = function () {
                if (navigator.userLanguage) {
                    return navigator.userLanguage.indexOf('ja') != -1;
                } else if (navigator["language"]) {
                    return navigator["language"].indexOf('ja') != -1;
                }

                return false;
            };

            Utility.CreateStyleElement = function (id) {
                var style = document.createElement("style");
                style.id = id;

                //add commnets by Jason.Zhou at 14:23 November 26 2007
                //for style.type="text/css" is used in css file used by linking file type, this sytle is only in dom tree.
                style.type = "text/css";

                //end by Jason.Zhou
                return style;
            };

            Utility.CreateClassStyle = function (className) {
                return Utility.CreateSelectorStyle("." + className);
            };

            Utility.CreateSelectorStyle = function (selectorName) {
                var tableStyle = document.getElementById("tableStyle");
                if (tableStyle == null) {
                    //tableStyle = GrapeCity.IM.Utility.CreateStyleElement("tableStyle");
                    tableStyle = this.CreateStyleElement("tableStyle");
                    document.body.appendChild(tableStyle);
                }

                var sheet = tableStyle.sheet || tableStyle.styleSheet;
                var rules = sheet.cssRules || sheet.rules;
                if (sheet.insertRule) {
                    sheet.insertRule(selectorName + "{ }", rules.length);
                } else {
                    sheet.addRule(selectorName, "{ }", rules.length);
                }

                return rules.item(rules.length - 1);
            };

            Utility.SetSelection = function (element, start, end, multiLine) {
                $(element).wijtextselection(Math.min(start, end), Math.max(start, end));
            };

            Utility.PreventDefault = function (evt) {
                if (evt.preventDefault) {
                    evt.preventDefault();
                } else {
                    evt.returnValue = false;
                }
            };

            Utility.CancelBubble = function (evt) {
                if (evt.cancelBubble !== undefined) {
                    evt.cancelBubble = true;
                } else {
                    evt.stopPropagation();
                }
            };

            Utility.DragDrop = function (obj) {
                try  {
                    obj.dragDrop(true);
                } catch (e) {
                }
            };

            Utility.GetMouseButton = function (evt) {
                var mouseButton = -1 /* Default */;
                var leftKey = input.CoreUtility.IsIE8OrBelow() ? 1 : 0;
                if (evt.button == leftKey) {
                    mouseButton = 0 /* Left */;
                } else if (evt.button == 1) {
                    mouseButton = 1 /* Middle */;
                } else if (evt.button == 2) {
                    mouseButton = 2 /* Right */;
                }
                return mouseButton;
            };

            /**
            * Gets the value after mouse wheel.
            * @param value - the initial value before mousewheel.
            * @returns Returns the value after mouse wheel.
            */
            Utility.GetMouseWheelValue = function (value, evt) {
                //Add comments by Ryan Wu at 9:50 Aug. 13 2007.
                //For Firefox doesn't support the event.wheelDelta to get the mouse wheel value.
                //I don't know why the event.detail is also 3 or -3, so we must divide 3.
                if (input.CoreUtility.IsFireFox4OrLater()) {
                    return -evt.detail / 3;
                }

                //end by Ryan Wu.
                if (evt.wheelDelta >= 120) {
                    value++;
                } else if (evt.wheelDelta <= -120) {
                    value--;
                }

                return value;
            };
            Utility.SetCopy = function (text, useClipboard) {
                // Add comments by Yang
                // For test firefox
                var selText;
                try  {
                    // add by Sean Huang at 2009.04.29, for bug 2209 -->
                    if (text == null || text == "") {
                        if (document.selection) {
                            selText = document.selection.createRange().text;
                        }
                        if (selText == "") {
                            return;
                        }
                    }
                } catch (e) {
                }
                ;

                if (text != null) {
                    selText = text;
                }

                Utility.CopyDataToClipBoard(selText, useClipboard);
            };

            Utility.CopyDataToClipBoard = function (copytext, useClipboard) {
                if (useClipboard == false) {
                    Utility.SavedText = copytext;
                    return;
                }

                if (window.clipboardData) {
                    // change by Sean Huang at 2009.01.13, for bug 1582 -->
                    //window.clipboardData.setData("Text", copytext);
                    // change by Sean Huang at 2009.02.19, for bug 1903 -->
                    //setTimeout('window.clipboardData.setData("Text", "' + copytext + '");', 0);
                    // change by Sean Huang at 2009.05.26, for sometimes throw exception in auto test ==-->
                    //setTimeout(function () {window.clipboardData.setData("Text", copytext);}, 0);
                    setTimeout(function () {
                        try  {
                            window.clipboardData.setData("Text", copytext);
                        } catch (ex) {
                        }
                    }, 0);
                    // end of Sean Huang, for auto test <--==
                    // end of Sean Huang <--
                    // end of Sean Huang <--
                } else if (Utility.CutCopyPasteEventObject !== null) {
                    if (Utility.CutCopyPasteEventObject.clipboardData !== undefined) {
                        Utility.CutCopyPasteEventObject.clipboardData.setData("text", copytext);
                    }
                }
                //else if (window.netscape) {
                //    try {
                //        netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
                //        var clip = Components.classes['@mozilla.org/widget/clipboard;1'].createInstance(Components.interfaces.nsIClipboard);
                //        if (!clip) {
                //            return;
                //        }
                //        var trans = Components.classes['@mozilla.org/widget/transferable;1'].createInstance(Components.interfaces.nsITransferable);
                //        if (!trans) {
                //            return;
                //        }
                //        trans.addDataFlavor('text/unicode');
                //        var str = new Object();
                //        var len = new Object();
                //        var str = Components.classes["@mozilla.org/supports-string;1"].createInstance(Components.interfaces.nsISupportsString);
                //        str.data = copytext;
                //        trans.setTransferData("text/unicode", str, copytext.length * 2);
                //        var clipid = Components.interfaces.nsIClipboard;
                //        if (!clip) {
                //            return false;
                //        }
                //        clip.setData(trans, null, clipid.kGlobalClipboard);
                //    } catch (e) {
                //    }
                //}
            };

            Utility.SetZoomStyle = function (element, value, align) {
                if (element === undefined || element === null) {
                    return;
                }

                var zoomOrigin = "top left";
                if (align === 2 /* Right */) {
                    zoomOrigin = "top right";
                }
                if (input.CoreUtility.firefox) {
                    element.style.MozTransformOrigin = value === "" ? "" : zoomOrigin;
                    element.style.MozTransform = value === "" ? "" : "scale(" + value + ")";
                    element.setAttribute("ZoomValue", value);
                } else {
                    if (input.CoreUtility.chrome || input.CoreUtility.safari) {
                        if (value !== "") {
                            element.style.MozTransform = "scale(" + value + ")";
                            element.style.WebkitTransform = "scale(" + value + ")";
                            element.style.webkitTransformOrigin = zoomOrigin;
                        } else {
                            element.style.MozTransform = "";
                            element.style.WebkitTransform = "";
                            element.style.WebkitTransformOrigin = "";
                        }
                    } else if (input.CoreUtility.IsIE9OrLater()) {
                        if (value !== "") {
                            element.style.msTransform = "scale(" + value + ")";
                            element.style.msTransformOrigin = zoomOrigin;
                        } else {
                            element.style.msTransform = "";
                            element.style.msTransformOrigin = "";
                        }
                    } else {
                        element.style.zoom = value;
                    }
                }
            };

            Utility.FilterText = function (includeText, intext) {
                if (intext.GetLength() == 0)
                    return "";
                var filterText = "";
                var j = 0;
                var i = 0;
                for (j = 0; j < intext.GetLength(); j++) {
                    var valid = false;
                    for (i = 0; i < includeText.GetLength(); i++) {
                        if (intext.Substring(j, j + 1) == includeText.Substring(i, i + 1))
                            valid = true;
                    }
                    if (valid == true)
                        filterText += intext.Substring(j, j + 1);
                }
                return filterText;
            };

            Utility.IndexOfAny = function (str, anyOf, startIndex) {
                if (startIndex >= str.length) {
                    return -1;
                }
                for (var i = startIndex; i < str.length; i++) {
                    for (var j = 0; j < anyOf.length; j++) {
                        if (str.charAt(i) == anyOf[j]) {
                            return i;
                        }
                    }
                }
                return -1;
            };
            Utility.IdCounter = 0;
            Utility.EditFieldSuffix = "_EidtField";

            Utility.MaskValChar = "\ufeff";
            Utility.Hold = "g-C2";
            return Utility;
        })();
        input.Utility = Utility;

        (function (FocusType) {
            FocusType[FocusType["None"] = 0] = "None";
            FocusType[FocusType["Click"] = 1] = "Click";
            FocusType[FocusType["ContextMenu"] = 2] = "ContextMenu";
            FocusType[FocusType["ClientEvent"] = 3] = "ClientEvent";
            FocusType[FocusType["KeyExit"] = 4] = "KeyExit";
            FocusType[FocusType["Default"] = 5] = "Default";
            FocusType[FocusType["SpinButton"] = 6] = "SpinButton";
            FocusType[FocusType["DropDown"] = 7] = "DropDown";
            FocusType[FocusType["ImeInput"] = 8] = "ImeInput";
            FocusType[FocusType["Left"] = 9] = "Left";
            FocusType[FocusType["Right"] = 10] = "Right";
            FocusType[FocusType["DragDrop"] = 11] = "DragDrop";
        })(input.FocusType || (input.FocusType = {}));
        var FocusType = input.FocusType;
        ;

        /** @ignore */
        (function (DateCursorPosition) {
            DateCursorPosition[DateCursorPosition["Default"] = 0] = "Default";
            DateCursorPosition[DateCursorPosition["Era"] = 1] = "Era";
            DateCursorPosition[DateCursorPosition["Year"] = 2] = "Year";
            DateCursorPosition[DateCursorPosition["Month"] = 3] = "Month";
            DateCursorPosition[DateCursorPosition["Day"] = 4] = "Day";
            DateCursorPosition[DateCursorPosition["AMPM"] = 5] = "AMPM";
            DateCursorPosition[DateCursorPosition["Hour"] = 6] = "Hour";
            DateCursorPosition[DateCursorPosition["Minute"] = 7] = "Minute";
            DateCursorPosition[DateCursorPosition["Second"] = 8] = "Second";
        })(input.DateCursorPosition || (input.DateCursorPosition = {}));
        var DateCursorPosition = input.DateCursorPosition;
        ;

        /**
        * Defines the CrLf mode which describes how to process the CrLf char.
        * @type {{NoControl: string, Filter: string, Cut: string}}
        */
        (function (CrLfMode) {
            /**
            * Accepts all CrLf characters in copied, cut, or pasted strings.
            */
            CrLfMode[CrLfMode["NoControl"] = 0] = "NoControl";

            /**
            * Removes all CrLf characters in copied, cut, or pasted strings.
            */
            CrLfMode[CrLfMode["Filter"] = 1] = "Filter";

            /**
            * Cuts the following strings from the first CrLf character in copied, cut, and pasted strings.
            */
            CrLfMode[CrLfMode["Cut"] = 2] = "Cut";
        })(input.CrLfMode || (input.CrLfMode = {}));
        var CrLfMode = input.CrLfMode;
        ;

        /**
        * Specifies how the literal in content is held in the clipboard.
        * @type {{IncludeLiterals: string, ExcludeLiterals: string}}
        */
        (function (ClipContent) {
            /**
            * Literals are included.
            */
            ClipContent[ClipContent["IncludeLiterals"] = 0] = "IncludeLiterals";

            /**
            * Literals are excluded.
            */
            ClipContent[ClipContent["ExcludeLiterals"] = 1] = "ExcludeLiterals";
        })(input.ClipContent || (input.ClipContent = {}));
        var ClipContent = input.ClipContent;
        ;

        (function (EditMode) {
            EditMode[EditMode["Insert"] = 0] = "Insert";
            EditMode[EditMode["Overwrite"] = 1] = "Overwrite";
            EditMode[EditMode["FixedInsert"] = 2] = "FixedInsert";
            EditMode[EditMode["FixedOverwrite"] = 3] = "FixedOverwrite";
        })(input.EditMode || (input.EditMode = {}));
        var EditMode = input.EditMode;
        ;

        (function (ShowLiterals) {
            ShowLiterals[ShowLiterals["Always"] = 1] = "Always";
            ShowLiterals[ShowLiterals["PostDisplay"] = 2] = "PostDisplay";
            ShowLiterals[ShowLiterals["PreDisplay"] = 3] = "PreDisplay";
        })(input.ShowLiterals || (input.ShowLiterals = {}));
        var ShowLiterals = input.ShowLiterals;
        ;

        (function (ExitOnLeftRightKey) {
            ExitOnLeftRightKey[ExitOnLeftRightKey["None"] = 0] = "None";
            ExitOnLeftRightKey[ExitOnLeftRightKey["Left"] = 1] = "Left";
            ExitOnLeftRightKey[ExitOnLeftRightKey["Right"] = 2] = "Right";
            ExitOnLeftRightKey[ExitOnLeftRightKey["Both"] = 3] = "Both";
        })(input.ExitOnLeftRightKey || (input.ExitOnLeftRightKey = {}));
        var ExitOnLeftRightKey = input.ExitOnLeftRightKey;
        ;

        /**
        * Specifies the type of selection text in control.
        * @type {{None: string, Field: string, All: string}}
        */
        (function (HighlightText) {
            /**
            * No selection specified.
            */
            HighlightText[HighlightText["None"] = 0] = "None";

            /**
            * Select the specified field.
            */
            HighlightText[HighlightText["Field"] = 1] = "Field";

            /**
            * Select all the text.
            */
            HighlightText[HighlightText["All"] = 2] = "All";
        })(input.HighlightText || (input.HighlightText = {}));
        var HighlightText = input.HighlightText;
        ;

        (function (DropDownAlign) {
            DropDownAlign[DropDownAlign["Left"] = 1] = "Left";
            DropDownAlign[DropDownAlign["Right"] = 2] = "Right";
        })(input.DropDownAlign || (input.DropDownAlign = {}));
        var DropDownAlign = input.DropDownAlign;

        (function (ScrollBarMode) {
            ScrollBarMode[ScrollBarMode["Automatic"] = 0] = "Automatic";
            ScrollBarMode[ScrollBarMode["Fixed"] = 1] = "Fixed";
        })(input.ScrollBarMode || (input.ScrollBarMode = {}));
        var ScrollBarMode = input.ScrollBarMode;

        (function (ScrollBars) {
            ScrollBars[ScrollBars["None"] = 0] = "None";
            ScrollBars[ScrollBars["Horizontal"] = 1] = "Horizontal";
            ScrollBars[ScrollBars["Vertical"] = 2] = "Vertical";
            ScrollBars[ScrollBars["Both"] = 3] = "Both";
        })(input.ScrollBars || (input.ScrollBars = {}));
        var ScrollBars = input.ScrollBars;

        (function (ControlStatus) {
            ControlStatus[ControlStatus["Normal"] = 0] = "Normal";
            ControlStatus[ControlStatus["Hover"] = 1] = "Hover";
            ControlStatus[ControlStatus["Pressed"] = 2] = "Pressed";
            ControlStatus[ControlStatus["Focused"] = 4] = "Focused";
            ControlStatus[ControlStatus["Disabled"] = 8] = "Disabled";
        })(input.ControlStatus || (input.ControlStatus = {}));
        var ControlStatus = input.ControlStatus;

        (function (ExitKeys) {
            ExitKeys[ExitKeys["Tab"] = 1] = "Tab";
            ExitKeys[ExitKeys["ShiftTab"] = 2] = "ShiftTab";
            ExitKeys[ExitKeys["NextControl"] = 3] = "NextControl";
            ExitKeys[ExitKeys["PreviousControl"] = 4] = "PreviousControl";
            ExitKeys[ExitKeys["Right"] = 5] = "Right";
            ExitKeys[ExitKeys["Left"] = 6] = "Left";
            ExitKeys[ExitKeys["CtrlRight"] = 7] = "CtrlRight";
            ExitKeys[ExitKeys["CtrlLeft"] = 8] = "CtrlLeft";
            ExitKeys[ExitKeys["CharInput"] = 9] = "CharInput";
        })(input.ExitKeys || (input.ExitKeys = {}));
        var ExitKeys = input.ExitKeys;
        ;

        (function (TabAction) {
            TabAction[TabAction["Control"] = 0] = "Control";
            TabAction[TabAction["Field"] = 1] = "Field";
        })(input.TabAction || (input.TabAction = {}));
        var TabAction = input.TabAction;
        ;

        (function (Key) {
            Key[Key["BackSpace"] = 8] = "BackSpace";
            Key[Key["Tab"] = 9] = "Tab";
            Key[Key["Clear"] = 12] = "Clear";
            Key[Key["Enter"] = 13] = "Enter";
            Key[Key["Shift"] = 16] = "Shift";
            Key[Key["Control"] = 17] = "Control";
            Key[Key["Alt"] = 18] = "Alt";
            Key[Key["Pause"] = 19] = "Pause";
            Key[Key["Caps_Lock"] = 20] = "Caps_Lock";
            Key[Key["Escape"] = 27] = "Escape";
            Key[Key["Space"] = 32] = "Space";
            Key[Key["PageUp"] = 33] = "PageUp";
            Key[Key["PageDown"] = 34] = "PageDown";
            Key[Key["End"] = 35] = "End";
            Key[Key["Home"] = 36] = "Home";
            Key[Key["Left"] = 37] = "Left";
            Key[Key["Up"] = 38] = "Up";
            Key[Key["Right"] = 39] = "Right";
            Key[Key["Down"] = 40] = "Down";
            Key[Key["Select"] = 41] = "Select";
            Key[Key["Print"] = 42] = "Print";
            Key[Key["Execute"] = 43] = "Execute";
            Key[Key["Insert"] = 45] = "Insert";
            Key[Key["Delete"] = 46] = "Delete";
            Key[Key["Help"] = 47] = "Help";
            Key[Key["equalbraceright"] = 48] = "equalbraceright";
            Key[Key["exclamonesuperior"] = 49] = "exclamonesuperior";
            Key[Key["quotedbltwosuperior"] = 50] = "quotedbltwosuperior";
            Key[Key["sectionthreesuperior"] = 51] = "sectionthreesuperior";
            Key[Key["dollar"] = 52] = "dollar";
            Key[Key["percent"] = 53] = "percent";
            Key[Key["ampersand"] = 54] = "ampersand";
            Key[Key["slashbraceleft"] = 55] = "slashbraceleft";
            Key[Key["parenleftbracketleft"] = 56] = "parenleftbracketleft";
            Key[Key["parenrightbracketright"] = 57] = "parenrightbracketright";
            Key[Key["A"] = 65] = "A";
            Key[Key["B"] = 66] = "B";
            Key[Key["C"] = 67] = "C";
            Key[Key["D"] = 68] = "D";
            Key[Key["E"] = 69] = "E";
            Key[Key["F"] = 70] = "F";
            Key[Key["G"] = 71] = "G";
            Key[Key["H"] = 72] = "H";
            Key[Key["I"] = 73] = "I";
            Key[Key["J"] = 74] = "J";
            Key[Key["K"] = 75] = "K";
            Key[Key["L"] = 76] = "L";
            Key[Key["M"] = 77] = "M";
            Key[Key["N"] = 78] = "N";
            Key[Key["O"] = 79] = "O";
            Key[Key["P"] = 80] = "P";
            Key[Key["Q"] = 81] = "Q";
            Key[Key["R"] = 82] = "R";
            Key[Key["S"] = 83] = "S";
            Key[Key["T"] = 84] = "T";
            Key[Key["U"] = 85] = "U";
            Key[Key["V"] = 86] = "V";
            Key[Key["W"] = 87] = "W";
            Key[Key["X"] = 88] = "X";
            Key[Key["Y"] = 89] = "Y";
            Key[Key["Z"] = 90] = "Z";
            Key[Key["KP_0"] = 96] = "KP_0";
            Key[Key["KP_1"] = 97] = "KP_1";
            Key[Key["KP_2"] = 98] = "KP_2";
            Key[Key["KP_3"] = 99] = "KP_3";
            Key[Key["KP_4"] = 100] = "KP_4";
            Key[Key["KP_5"] = 101] = "KP_5";
            Key[Key["KP_6"] = 102] = "KP_6";
            Key[Key["KP_7"] = 103] = "KP_7";
            Key[Key["KP_8"] = 104] = "KP_8";
            Key[Key["KP_9"] = 105] = "KP_9";
            Key[Key["KP_Multiply"] = 106] = "KP_Multiply";
            Key[Key["KP_Add"] = 107] = "KP_Add";
            Key[Key["KP_Separator"] = 108] = "KP_Separator";
            Key[Key["KP_Subtract"] = 109] = "KP_Subtract";
            Key[Key["KP_Decimal"] = 110] = "KP_Decimal";
            Key[Key["KP_Divide"] = 111] = "KP_Divide";
            Key[Key["F1"] = 112] = "F1";
            Key[Key["F2"] = 113] = "F2";
            Key[Key["F3"] = 114] = "F3";
            Key[Key["F4"] = 115] = "F4";
            Key[Key["F5"] = 116] = "F5";
            Key[Key["F6"] = 117] = "F6";
            Key[Key["F7"] = 118] = "F7";
            Key[Key["F8"] = 119] = "F8";
            Key[Key["F9"] = 120] = "F9";
            Key[Key["F10"] = 121] = "F10";
            Key[Key["F11"] = 122] = "F11";
            Key[Key["F12"] = 123] = "F12";
            Key[Key["F13"] = 124] = "F13";
            Key[Key["F14"] = 125] = "F14";
            Key[Key["F15"] = 126] = "F15";
            Key[Key["F16"] = 127] = "F16";
            Key[Key["F17"] = 128] = "F17";
            Key[Key["F18"] = 129] = "F18";
            Key[Key["F19"] = 130] = "F19";
            Key[Key["F20"] = 131] = "F20";
            Key[Key["F21"] = 132] = "F21";
            Key[Key["F22"] = 133] = "F22";
            Key[Key["F23"] = 134] = "F23";
            Key[Key["F24"] = 135] = "F24";
            Key[Key["Num_Lock"] = 136] = "Num_Lock";
            Key[Key["Scroll_Lock"] = 137] = "Scroll_Lock";
        })(input.Key || (input.Key = {}));
        var Key = input.Key;
        ;

        

        

        

        /** @ignore */
        var BaseUIProcess = (function () {
            function BaseUIProcess() {
                this.isMulSelected = false;
                this.isDblClick = false;
                this.isTriClick = false;
                this.isOverWrite = false;
                this.moveFocusExitOnLastChar = false;
            }
            BaseUIProcess.prototype.GetInputElement = function () {
                return this.Owner.GetInputElement();
            };

            BaseUIProcess.prototype.GetElementId = function () {
                return this.Owner.GetInputElement().id;
            };

            BaseUIProcess.prototype.GetShowLiterals = function () {
                if (this.Owner.GetShowLiterals !== undefined) {
                    return this.Owner.GetShowLiterals();
                }
                return 1 /* Always */;
            };

            /**
            * Get cursor start and end position according to the specified highlighttext and current text.
            */
            BaseUIProcess.prototype.SetCursorPositionAndSelection = function (highlightText, text, cursorPos, startPos) {
                var retInfo = {};

                if (highlightText == true || highlightText == 2 /* All */) {
                    retInfo.SelectionStart = 0;
                    retInfo.SelectionEnd = text.GetLength();
                }

                return retInfo;
            };

            /**
            * Clear the current value of the control.
            */
            BaseUIProcess.prototype.Clear = function () {
                return null;
            };

            /**
            * Handle the onfocus event.
            */
            BaseUIProcess.prototype.Focus = function (data) {
                var text = data.Text;
                var displayText = data.DisplayText;
                var focusType = data.FocusType;
                var oText = data.Element;
                var highlightText = data.HighlightText;
                var cursorPos = data.CursorPosition;
                var retInfo = {};

                //Add comments by Ryan Wu at 19:22 Dec 7, 2005.
                //Maybe this is a bug? for we press tab key to get focus. If the original state is
                //selection then the current state is also state, thus this.isMulSelected is true.????
                this.isMulSelected = false;

                //the focusType is used to distribute the get focus type by Left key
                // or Right key or something else.
                if (focusType == 1 /* Click */) {
                    retInfo.SelectionStart = Utility.GetCursorPosition(oText);
                    retInfo.SelectionEnd = retInfo.SelectionStart;
                }

                //when get the focus, display the format.
                retInfo.Text = text;

                //Press tab key will set cursor start position to less than zero
                if (retInfo.SelectionStart == -1) {
                    retInfo.SelectionStart = 0;
                    retInfo.SelectionEnd = 0;
                } else if (retInfo.SelectionStart > retInfo.Text.GetLength()) {
                    retInfo.SelectionStart = retInfo.Text.GetLength();
                    retInfo.SelectionEnd = retInfo.Text.GetLength();
                } else if (retInfo.SelectionStart == displayText.GetLength()) {
                    retInfo.SelectionStart = retInfo.Text.GetLength();
                    retInfo.SelectionEnd = retInfo.Text.GetLength();
                }

                //the focusType is FocusType.Left it means that the focus is set by press the left key.
                // change by Sean Huang at 2008.12.05, for bug 992 -->
                //if (focusType == FocusType.Left)
                if (focusType == 9 /* Left */ && cursorPos == 0 /* Default */) {
                    retInfo.SelectionStart = 0;
                    retInfo.SelectionEnd = 0;
                    //update by wuhao 2008-1-8 for fix bug 1362
                    //return retInfo;
                    //end by wuhao 2008-1-8 for fix bug 1362
                } else if (focusType == 10 /* Right */ && cursorPos == 0 /* Default */) {
                    retInfo.SelectionStart = retInfo.Text.GetLength();
                    retInfo.SelectionEnd = retInfo.Text.GetLength();
                    //update by wuhao 2008-1-8 for fix bug 1362
                    //return retInfo;
                    //end by wuhao 2008-1-8 for fix bug 1362
                }

                //The selection is not determined by the HighlightText and CursorPosition property.
                if (highlightText == 0 /* None */ && cursorPos == 0 /* Default */) {
                    return retInfo;
                }

                //Add comments by Ryan Wu at 9:23 Oct. 18 2007.
                //For fix the bug#9065.
                if (focusType == 2 /* ContextMenu */) {
                    return retInfo;
                }

                //end by Ryan Wu.
                //Add comments by Ryan Wu at 14:38 Oct. 11 2007.
                //For fix the bug#8998.
                //    //According to the HighlightText property and CursorPosition property to set the
                //	//selection.
                //	var ret = this.SetCursorPositionAndSelection(highlightText, retInfo.Text, cursorPos, retInfo.SelectionStart);
                var startPos = retInfo.SelectionStart == null ? data.SelectionStart : retInfo.SelectionStart;
                var ret = this.SetCursorPositionAndSelection(highlightText, retInfo.Text, cursorPos, startPos);

                //end by Ryan Wu.
                if (ret != null) {
                    retInfo.SelectionStart = ret.SelectionStart;
                    retInfo.SelectionEnd = ret.SelectionEnd;
                    retInfo.IsSelectionDeterminedByHighlightText = true;
                }

                //Add comments by Ryan Wu at 9:13 Oct. 18 2007.
                //For removing the useless code.
                //	//the focusType is FocusType.ClientEvent it means that the focus is set by ourself.
                //	if (focusType == FocusType.ClientEvent)
                //	{
                //		return retInfo;
                //	}
                //end by Ryan Wu.
                return retInfo;
            };

            /**
            * Handle the onblur event.
            */
            BaseUIProcess.prototype.LoseFocus = function (data) {
            };

            /**
            * Handle the onmousedown event.
            */
            BaseUIProcess.prototype.MouseDown = function (mouseButton) {
                var retInfo = {};

                this.isTriClick = false;

                //for triple click
                if (this.isDblClick && !Utility.GrapeCityTimeout && mouseButton == 0 /* Left */) {
                    this.isTriClick = true;
                    retInfo = this.SelectAll();
                }

                this.isDblClick = false;
                return retInfo;
            };

            /**
            * Handle the onmouseup event.
            */
            // Frank Liu added the parameter "ctrlPressed" at 2013/06/27 for bug 881.
            BaseUIProcess.prototype.MouseUp = function (obj, start, end, mouseButton, ctrlPressed) {
                var retInfo = {};

                if (this.isTriClick) {
                    Utility.SetSelection(obj, start, end);

                    return null;
                }

                //Add comments by Ryan Wu at 10:13 Sep. 13 2007.
                //For fix the bug "17. Ctrl+Click(select all text) will take no effects.".
                // Frank Liu fixed bug 881 at 2013/06/27.
                //if (!Utility.IsIE() && Utility.FuncKeysPressed.Ctrl) {
                if (ctrlPressed) {
                    retInfo = this.SelectAll();
                    Utility.SetSelection(obj, retInfo.SelectionStart, retInfo.SelectionEnd);

                    return retInfo;
                }

                //end by Ryan Wu.
                retInfo.SelectionStart = start;
                retInfo.SelectionEnd = end;

                if (mouseButton == 0 /* Left */) {
                    //bug#5675
                    //retInfo = GrapeCity_InputMan_GetCursorEndPos(obj, start);
                    retInfo.SelectionStart = Utility.GetSelectionStartPosition(obj);
                    retInfo.SelectionEnd = Utility.GetSelectionEndPosition(obj);
                }

                if (retInfo.SelectionStart != retInfo.SelectionEnd) {
                    this.isMulSelected = true;
                } else {
                    this.isMulSelected = false;
                }

                return retInfo;
            };

            /**
            * Handle the shortcut key event.
            */
            BaseUIProcess.prototype.ProcessShortcutKey = function (keyAction, readOnly, end, start) {
                var retInfo = {};

                switch (keyAction) {
                    case "Clear":
                        if (readOnly) {
                            retInfo.System = false;
                            return retInfo;
                        }

                        return this.Clear();
                    case "NextControl":
                        var ret = this.MoveControl(this.GetInputElement(), true, false, "NextControl");

                        if (ret != null) {
                            retInfo.EventInfo = ret.EventInfo;
                            retInfo.FocusType = ret.FocusType;
                            retInfo.FocusExit = true;
                        }

                        retInfo.System = false;
                        return retInfo;
                    case "PreviousControl":
                        var ret = this.MoveControl(this.GetInputElement(), false, false, "PreviousControl");
                        if (ret != null) {
                            retInfo.EventInfo = ret.EventInfo;
                            retInfo.FocusType = ret.FocusType;
                            retInfo.FocusExit = true;
                        }

                        retInfo.System = false;
                        return retInfo;
                    case "NextField":
                        retInfo = this.MoveField(end, true);
                        return retInfo;
                    case "PreviousField":
                        retInfo = this.MoveField(end, false);
                        return retInfo;
                    case "NextField/NextControl":
                        var retInfo = this.MoveFieldAndControl(end, true);
                        return retInfo;
                    case "PreviousField/PreviousControl":
                        var retInfo = this.MoveFieldAndControl(end, false);
                        return retInfo;
                }
            };

            /**
            * Process char key input.
            */
            BaseUIProcess.prototype.ProcessCharKeyInput = function (k, start, end, isExitOnLastChar, text) {
                return null;
            };

            /**
            * Prcess navigator key input.
            */
            BaseUIProcess.prototype.ProcessNavigatorKeyInput = function (k, editMode, clipContent, text, start, end, exitOnLeftRightKey, isExitOnLastChar) {
                var retInfo = {};

                switch (k) {
                    case 45:
                        if (editMode == 2 /* FixedInsert */) {
                            this.isOverWrite = false;
                        } else if (editMode == 3 /* FixedOverwrite */) {
                            this.isOverWrite = true;
                        } else {
                            this.isOverWrite = !this.isOverWrite;
                        }

                        retInfo.Overwrite = this.isOverWrite;
                        retInfo.System = false;

                        if (this.Format.Fields.fieldCount == 0) {
                            retInfo.System = true;
                        }

                        return retInfo;

                    case 8:
                        //Add comments by Ryan Wu at 14:23 Jul. 19 2006.
                        //Add text param only for number to judge whether the current text is zero.
                        //retInfo = this.ProcessBackSpace(start, end);
                        retInfo = this.ProcessBackSpace(start, end, text);

                        //end by Ryan Wu.
                        retInfo.System = false;
                        break;

                    case 46:
                        //Add comments by Ryan Wu at 14:23 Jul. 19 2006.
                        //Add text param only for number to judge whether the current text is zero.
                        //retInfo = this.ProcessDelete(start, end);
                        retInfo = this.ProcessDelete(start, end, text);

                        //end by Ryan Wu.
                        retInfo.System = false;
                        break;

                    case 196643:

                    case 196644:

                    case 196645:

                    case 196647:

                    case 65569:

                    case 196641:

                    case 65570:

                    case 196642:
                        if (k == 65569 || k == 196641) {
                            k = 196644;
                        } else if (k == 65570 || k == 196642) {
                            k = 196643;
                        }

                        //perform the Shift+Ctrl+Left,Shift+Ctrl+Right,Shift+Ctrl+Home,Shift+Ctrl+End action
                        retInfo.SelectionEnd = this.GetCaretPosition(end, k);
                        this.isMulSelected = true;
                        retInfo.System = false;
                        break;

                    case 65582:
                    case 65544:
                        if (this.isMulSelected) {
                            if (this.Owner._isSupportClipBoard()) {
                                retInfo = this.Cut(clipContent, start, end);
                            } else {
                                retInfo.System = true;
                                break;
                            }
                        } else {
                            retInfo = this.ProcessBackSpace(start, end);
                        }
                        retInfo.System = false;
                        break;

                    case 65581:

                    case 131158:
                        if (this.Owner._isSupportClipBoard()) {
                            var pasteData = Utility.GetPasteData(this.Owner ? this.Owner.GetUseClipboard() : true);
                            retInfo = this.Paste(start, end, pasteData, isExitOnLastChar);
                            retInfo.System = false;
                        } else {
                            retInfo.System = true;
                        }
                        break;

                    case 65571:

                    case 65572:

                    case 65573:

                    case 65575:

                    case 65574:

                    case 65576:
                        // end by Jiang Changcheng <--
                        this.isMulSelected = true;

                        //perform the Shift+Left,Shift+Right,Shift+Home,Shift+End action
                        retInfo.SelectionEnd = this.GetCaretPosition(end, k);
                        retInfo.System = false;
                        break;

                    case 131139:

                    case 131117:
                        if (this.Owner._isSupportClipBoard()) {
                            this.Copy(clipContent, start, end);
                            retInfo.System = false;
                        } else {
                            retInfo.System = true;
                        }

                        break;

                    case 131118:
                        if (!this.isMulSelected) {
                            end = this.GetCaretPosition(end, k);
                        }

                        retInfo = this.ProcessDelete(start, end);
                        retInfo.System = false;
                        break;

                    case 131080:
                    case 196616:
                        if (!this.isMulSelected) {
                            end = this.GetCaretPosition(end, k);
                        }

                        retInfo = this.ProcessBackSpace(start, end);
                        retInfo.System = false;
                        break;

                    case 131137:
                        retInfo = this.SelectAll();
                        retInfo.System = false;
                        break;

                    case 131160:
                        if (this.Owner._isSupportClipBoard()) {
                            retInfo = this.Cut(clipContent, start, end);
                            retInfo.System = false;
                        } else {
                            retInfo.System = true;
                        }

                        break;

                    case 131162:
                        //Need add undo methods by Ryan wu.
                        retInfo = this.Undo();
                        retInfo.System = false;
                        break;

                    case 131109:

                    case 37:
                        //Move to previous control
                        if (start == 0 && (exitOnLeftRightKey == 3 /* Both */ || exitOnLeftRightKey == 1 /* Left */)) {
                            var exitType = k == 37 ? "Left" : "CtrlLeft";
                            var ret = this.MoveControl(this.GetInputElement(), false, true, exitType);

                            if (ret != null) {
                                retInfo.EventInfo = ret.EventInfo;
                                retInfo.FocusType = ret.FocusType;
                                retInfo.FocusExit = true;
                            }

                            return retInfo;
                        }

                    case 131108:

                    case 131110:

                    case 36:

                    case 33:

                    case 131105:
                        if (k == 33 || k == 131105) {
                            k = 131108;
                        }

                        retInfo = this.ProcessLeftDirection(start, end, k);
                        retInfo.System = false;
                        break;

                    case 131111:

                    case 39:
                        //Move to next control
                        if (start == text.GetLength() && (exitOnLeftRightKey == 3 /* Both */ || exitOnLeftRightKey == 2 /* Right */)) {
                            var exitType = k == 39 ? "Right" : "CtrlRight";
                            var ret = this.MoveControl(this.GetInputElement(), true, true, exitType);
                            if (ret != null) {
                                retInfo.EventInfo = ret.EventInfo;
                                retInfo.FocusType = ret.FocusType;
                                retInfo.FocusExit = true;
                            }
                            return retInfo;
                        }

                    case 131107:

                    case 131112:

                    case 35:

                    case 34:

                    case 131106:
                        if (k == 34 || k == 131106) {
                            k = 131107;
                        }
                        retInfo = this.ProcessRightDirection(start, end, k);
                        retInfo.System = false;
                        break;
                    default:
                        retInfo = null;
                        break;
                }

                return retInfo;
            };
            BaseUIProcess.prototype.ProcessLeftDirection = function (start, end, k) {
            };
            BaseUIProcess.prototype.ProcessRightDirection = function (start, end, k) {
            };

            /**
            * Handle the onkeydown event.
            */
            BaseUIProcess.prototype.KeyDown = function (data) {
                var k = data.KeyCode;
                var start = data.SelectionStart;
                var end = data.SelectionEnd;
                var text = data.Text;
                var editMode = data.EditMode;
                var keyAction = data.KeyAction;
                var readOnly = data.ReadOnly;
                var clipContent = data.ClipContent;

                //var funcKeysPressed	   = data.FuncKeysPressed;
                var isExitOnLastChar = data.ExitOnLastChar;
                var exitOnLeftRightKey = data.ExitOnLeftRightKey;
                var tabAction = data.TabAction;
                var retInfo = {};

                switch (editMode) {
                    case 0 /* Insert */:
                        this.isOverWrite = false;
                        break;
                    case 1 /* Overwrite */:
                        this.isOverWrite = true;
                        break;
                    case 2 /* FixedInsert */:
                        this.isOverWrite = false;
                        break;
                    case 3 /* FixedOverwrite */:
                        this.isOverWrite = true;
                        break;
                }

                if (start != end) {
                    this.isMulSelected = true;
                } else {
                    this.isMulSelected = false;
                }

                switch (k) {
                    case 9:
                        retInfo = this.ProcessTabKey(end, true, tabAction);
                        return retInfo;
                    case 65545:
                        retInfo = this.ProcessTabKey(end, false, tabAction);
                        return retInfo;
                }

                //ShortCuts
                if (keyAction != null) {
                    return this.ProcessShortcutKey(keyAction, readOnly, end, start);
                }

                //The ReadOnly property is set to true
                if (readOnly) {
                    //When readonly is true, Escape, Alt + Up, Alt + Down, Up, Down can also take effect.
                    //If return null, then in BaseInputControl will handle the Escape, Alt + Up and Alt + Down action.
                    if (k == 27 || k == 262182 || k == 262184 || k == 38 || k == 40) {
                        return null;
                    }

                    //we only let the Ctrl+C and Ctrl+Insert and ShortCut to work when we set
                    //ReadOnly property to true.
                    // change by Sean Huang at 2008.08.13, for bug 28 (ttp)-->
                    //if (k != 131117 && k != 131139)
                    if (k != 131117 && k != 131139 && k != 9 && k != 65545 && k != 131081 && k != 196617 && k != 131137 && k != 37 && k != 39 && k != 38 && k != 40) {
                        return retInfo;
                    }
                }

                //the DateFormat has no Pattern property, we use the system's keydown action
                if (this.Format.Fields.fieldCount == 0) {
                    switch (k) {
                        case 45:
                            if (editMode == 2 /* FixedInsert */) {
                                this.isOverWrite = false;
                            } else if (editMode == 3 /* FixedOverwrite */) {
                                this.isOverWrite = true;
                            } else {
                                this.isOverWrite = !this.isOverWrite;
                            }

                            retInfo.Overwrite = this.isOverWrite;

                            if (this.Format.Fields.fieldCount == 0) {
                                retInfo.System = true;
                            }

                            return retInfo;

                        case 37:

                        case 131109:
                            //Move to previous control
                            if (start == 0 && (exitOnLeftRightKey == 3 /* Both */ || exitOnLeftRightKey == 1 /* Left */)) {
                                var exitType = k == 37 ? "Left" : "CtrlLeft";
                                var ret = this.MoveControl(this.GetInputElement(), false, true, exitType);
                                if (ret != null) {
                                    retInfo.EventInfo = ret.EventInfo;
                                    retInfo.FocusType = ret.FocusType;
                                    retInfo.FocusExit = true;
                                }
                                return retInfo;
                            }
                            break;

                        case 39:

                        case 131111:
                            //Move to next control
                            if (start == text.GetLength() && (exitOnLeftRightKey == 3 /* Both */ || exitOnLeftRightKey == 2 /* Right */)) {
                                var exitType = k == 39 ? "Right" : "CtrlRight";
                                var ret = this.MoveControl(this.GetInputElement(), true, true, exitType);
                                if (ret != null) {
                                    retInfo.EventInfo = ret.EventInfo;
                                    retInfo.FocusType = ret.FocusType;
                                    retInfo.FocusExit = true;
                                }
                                return retInfo;
                            }
                            break;
                    }

                    return null;
                }

                //Process char key input.
                var processInfo = this.ProcessCharKeyInput(k, start, end, isExitOnLastChar, text);

                if (processInfo != null) {
                    return processInfo;
                }

                retInfo = this.ProcessNavigatorKeyInput(k, editMode, clipContent, text, start, end, exitOnLeftRightKey, isExitOnLastChar);

                return retInfo;
            };

            /**
            * Handle the onkeypress event.
            */
            BaseUIProcess.prototype.KeyPress = function (e) {
            };

            /**
            * Handle the onkeyup event.
            */
            BaseUIProcess.prototype.KeyUp = function (e) {
            };

            /**
            * Handle the oncontextmenu event.
            */
            BaseUIProcess.prototype.ShowContextMenu = function (oText, selText) {
                var retInfo = {};

                //If there's no text selected
                if (selText == "") {
                    retInfo.SelectionStart = Utility.GetCursorPosition(oText);
                    retInfo.SelectionEnd = retInfo.SelectionStart;
                }

                return retInfo;
            };

            /**
            * Handle the onselectstart event.
            */
            BaseUIProcess.prototype.SelectStart = function (obj, selText, mouseButton) {
                var retInfo = {};

                if (selText == "" && !this.isTriClick && !this.isDblClick && mouseButton != -1 /* Default */) {
                    retInfo.SelectionStart = Utility.GetCursorPosition(obj);
                    retInfo.SetFalse = true;
                }

                return retInfo;
            };

            /**
            * Handle the ondblclick event.
            */
            BaseUIProcess.prototype.DoubleClick = function (pos) {
                var retInfo = {};

                //Get current field range
                var fieldIndex = this.Format.Fields.GetFieldIndexByPos(pos);
                var fieldPos = this.Format.Fields.GetFieldRange(fieldIndex.index);
                retInfo.SelectionStart = fieldPos.start;
                retInfo.SelectionEnd = fieldPos.length + fieldPos.start;

                //set timer for tripple click
                Utility.GrapeCityTimeout = false;
                this.isDblClick = true;
                this.isMulSelect = true;

                setTimeout(function () {
                    Utility.GrapeCityTimeout = true;
                }, 300);

                return retInfo;
            };

            /**
            * Handle the undo actions.
            */
            BaseUIProcess.prototype.Undo = function () {
            };

            /**
            * Handle the cut actions.
            * @param clipContent - The copy mode.
            * @param start - The start cursor position.
            * @param end   - The end cursor position.
            * @returns Returns the cursor position.
            */
            BaseUIProcess.prototype.Cut = function (clipContent, start, end) {
                var retInfo = {};

                if (start == end) {
                    return retInfo;
                }

                this.FireClientEvent("OnBeforeCut");
                this.Copy(clipContent, start, end);
                retInfo = this.ProcessDelete(start, end);

                this.FireClientEvent("OnCut");
                return retInfo;
            };

            /**
            * Handle the oncopy event.
            * @param clipContent - The copy mode.
            * @param start - The start cursor position.
            * @param end   - The end cursor position.
            */
            BaseUIProcess.prototype.Copy = function (clipContent, start, end) {
                var text = null;
                var useClipboard = true;

                if (clipContent == 1 /* ExcludeLiterals */) {
                    var length = Math.abs(start - end);
                    var start = Math.min(start, end);
                    if (length == 0) {
                        return;
                    }

                    text = this.Format.Fields.GetNonLiteralsText(start, length);
                } else if (!input.CoreUtility.IsIE() || input.CoreUtility.IsIE11OrLater()) {
                    text = Utility.GetSelectionText(this.Owner.GetInputElement());
                } else {
                    text = document.selection.createRange().text;
                }

                // end of Sean Huang <--
                //end by Ryan Wu.
                if (this.Owner) {
                    text = BaseUIProcess.UpdateCrLfString(text, this.Owner.GetAcceptsCrlf());
                    useClipboard = this.Owner.GetUseClipboard();
                }

                // change by Sean Huang at 2009.04.29, for bug 2209 -->
                //Utility.SetCopy(text);
                if (input.CoreUtility.IsIE()) {
                    setTimeout(function () {
                        Utility.SetCopy(text, useClipboard);
                    });
                } else {
                    Utility.SetCopy(text, useClipboard);
                }
                // end of Sean Huang <--
            };

            /**
            * Handle the onpaste event.
            */
            BaseUIProcess.prototype.Paste = function (start, end, text, exitonlastChar) {
            };

            /**
            * Select all the content.
            * @returns Returns the cursor position.
            */
            BaseUIProcess.prototype.SelectAll = function () {
                var retInfo = { SelectionStart: 0, SelectionEnd: 0 };
                retInfo.SelectionStart = 0;

                //modified by sj 2008.8.13 for bug 243
                var ShowLiterals;

                if (this.ID) {
                    ShowLiterals = this.GetShowLiterals();
                }

                if (ShowLiterals == 'PostDisplay' || ShowLiterals == 'PreDisplay') {
                    retInfo.SelectionEnd = Utility.FindIMControl(this.ID).GetText().GetLength();
                } else {
                    retInfo.SelectionEnd = this.Format.Fields.GetLength();
                }

                //retInfo.SelectionEnd   = this.Format.Fields.GetLength();
                //end by sj
                this.isMulSelected = true;

                return retInfo;
            };

            //Add comments by Ryan Wu at 9:31 Apr. 5 2007.
            //For support Aspnet Ajax 1.0.
            ///*
            //* This Function should be called when an event needs to be fired.
            //* @param oControl - the javascript object representation of our control.
            //* @param eName    - the name of the function that should handle this event.
            //* @param eArgs    - the argument of the function that should handle this event.
            //*/
            //FireEvent (oControl, eName, eArgs)
            //{
            //	//Because when we fire client event we may be invoke the lose focus event,
            //	//so we must return the current focus type of getting focus.
            //	//No event will be fired
            //	if (eName == null || eName == "")
            //	{
            //		return null;
            //	}
            //
            //	if (Utility.FireEvent(oControl, eName, eArgs))
            //	{
            //		return FocusType.ClientEvent;
            //	}
            //};
            /*
            * This Function should be called when an event needs to be fired.
            * @param oControl - the javascript object representation of our control.
            * @param eName    - the name of the function that should handle this event.
            * @param eArgs    - the argument of the function that should handle this event.
            */
            BaseUIProcess.prototype.FireEvent = function (oControl, eName, eArgs, eType) {
                //Because when we fire client event we may be invoke the lose focus event,
                //so we must return the current focus type of getting focus.
                //No event will be fired
                //if (eName == null || eName == "") {
                //    return null;
                //}
                if (Utility.FireEvent(oControl, eName, eArgs, eType)) {
                    return 3 /* ClientEvent */;
                }
            };

            //end by Ryan Wu.
            /**
            * Process the input char key action.
            * @param start - The specified start cursor position.
            * @param end - The specified end cursor position.
            * @param charInput - The specified char will be input.
            * @returns Returns action result includes cursor position and if succeed after the process and whether we fire a client event.
            */
            BaseUIProcess.prototype.ProcessCharKey = function (start, end, charInput, isExitOnLastChar) {
                var processInfo = {};

                //get the selection information.
                var selectionStart = Math.min(start, end);
                var selectionLength = Math.abs(end - start);
                var retInfo = {};

                processInfo.start = selectionStart;
                processInfo.success = false;

                //none action.
                if (this.Format.Fields.GetFieldIndex(selectionStart).index == -1) {
                    //we input an invalid char, so invoke the InvalidInput Event
                    var eventInfo = {};
                    eventInfo.Name = this.Owner.InvalidInputEvent;
                    eventInfo.Args = null;

                    //Add comments by Ryan Wu at 10:27 Apr. 5 2007.
                    //For support Aspnet Ajax 1.0.
                    eventInfo.Type = "invalidInput";

                    //end by Ryan Wu.
                    processInfo.EventInfo = eventInfo;

                    return processInfo;
                }

                var text = charInput.toString();

                if (selectionLength == 0 && !this.isOverWrite) {
                    retInfo = this.Format.Fields.Insert(selectionStart, text, false);
                } else if (selectionLength == 0) {
                    if (selectionStart == this.Format.Fields.GetLength()) {
                        retInfo = this.Format.Fields.Insert(selectionStart, text, false);
                    } else {
                        var isReplace = false;
                        var posInfo = this.Format.Fields.GetFieldIndexByPos(selectionStart);
                        var fieldIndex = posInfo.index;
                        var fieldOffset = posInfo.offset;

                        //var fieldsLength = selectionStart - fieldOffset;
                        var fieldRange = this.Format.Fields.GetFieldRange(fieldIndex);

                        if (this.Format.Fields.GetFieldByIndex(fieldIndex).fieldLabel == "PromptField") {
                            if (selectionStart - fieldOffset + fieldRange.length == this.Format.Fields.GetLength()) {
                                isReplace = false;
                            } else {
                                isReplace = true;
                                selectionLength = fieldRange.length - fieldOffset + 1;
                            }
                        } else {
                            isReplace = true;

                            // DaryLuo 2013/07/15 fix bug 1014 in IM HTML 5.
                            selectionLength = charInput.GetLength();
                        }

                        //none action.
                        if (this.Format.Fields.GetFieldIndexByPos(selectionStart + selectionLength).index == -1) {
                            //we input an invalid char, so invoke the InvalidInput Event
                            var eventInfo = {};
                            eventInfo.Name = this.Owner.InvalidInputEvent;
                            eventInfo.Args = null;

                            //Add comments by Ryan Wu at 10:27 Apr. 5 2007.
                            //For support Aspnet Ajax 1.0.
                            eventInfo.Type = "invalidInput";

                            //end by Ryan Wu.
                            processInfo.EventInfo = eventInfo;

                            return processInfo;
                        }

                        if (isReplace) {
                            retInfo = this.Format.Fields.Replace(selectionStart, selectionLength, text, false);
                        } else {
                            retInfo = this.Format.Fields.Insert(selectionStart, text, false);
                        }
                    }
                } else {
                    retInfo = this.Format.Fields.Replace(selectionStart, selectionLength, text, false);
                }

                selectionStart = retInfo.cursorPos;

                //we input an invalid char, so invoke the InvalidInput Event
                if (retInfo.text != "") {
                    var eventInfo = {};
                    eventInfo.Name = this.Owner.InvalidInputEvent;
                    eventInfo.Args = null;

                    //Add comments by Ryan Wu at 10:27 Apr. 5 2007.
                    //For support Aspnet Ajax 1.0.
                    eventInfo.Type = "invalidInput";

                    //end by Ryan Wu.
                    processInfo.EventInfo = eventInfo;

                    processInfo.start = selectionStart;
                    processInfo.success = false;

                    return processInfo;
                }

                //judge if the focus should exit on last char.
                if (isExitOnLastChar == true) {
                    if (selectionStart == this.Format.Fields.GetLength()) {
                        this.moveFocusExitOnLastChar = true;
                    } else {
                        var posInfo = this.Format.Fields.GetFieldIndexByPos(selectionStart);
                        var fieldIndex = posInfo.index;
                        var fieldOffset = posInfo.offset;

                        if (fieldIndex == this.Format.Fields.fieldCount - 1 && fieldOffset == 0 && this.Format.Fields.GetFieldByIndex(fieldIndex).fieldLabel == "PromptField") {
                            this.moveFocusExitOnLastChar = true;
                        }
                    }
                }

                processInfo.start = selectionStart;
                processInfo.success = true;

                return processInfo;
            };

            /**
            * Process the Delete key down action.
            * @param start - The specified start cursor position.
            * @param end - The specified end cursor position.
            * @returns Returns the cursor position after the process.
            */
            BaseUIProcess.prototype.ProcessDeleteKey = function (start, end) {
                //get the selection information.
                var selectionStart = Math.min(start, end);
                var selectionLength = Math.abs(start - end);
                var retInfo = {};

                if (selectionStart == this.Format.Fields.GetLength() && selectionLength == 0) {
                    return retInfo;
                }

                //var startFieldOffset;
                var startFieldIndex;
                var fieldPosInfo = this.Format.Fields.GetFieldIndexByPos(selectionStart);
                startFieldIndex = fieldPosInfo.index;

                //startFieldOffset = fieldPosInfo.offset;
                //none action.
                if (startFieldIndex == -1) {
                    return retInfo;
                }

                //if the selectionlength = 0, do the delete action for one post char.
                if (selectionLength == 0) {
                    //none action.
                    if (this.Format.Fields.GetFieldByIndex(startFieldIndex).fieldLabel == "PromptField") {
                        return retInfo;
                    }

                    selectionStart = this.Format.Fields.Delete(selectionStart, 1).cursorPos;

                    retInfo.SelectionStart = selectionStart;
                    retInfo.SelectionEnd = retInfo.SelectionStart;
                } else {
                    var endFieldOffset;
                    var endFieldIndex;
                    fieldPosInfo = this.Format.Fields.GetFieldIndexByPos(selectionStart + selectionLength);
                    endFieldOffset = fieldPosInfo.offset;
                    endFieldIndex = fieldPosInfo.index;

                    //none action.
                    if (endFieldIndex == -1) {
                        return retInfo;
                    }

                    if (endFieldOffset == 0) {
                        endFieldIndex--;
                    }

                    //none action
                    if (startFieldIndex == endFieldIndex && this.Format.Fields.GetFieldByIndex(startFieldIndex).fieldLabel == "PromptField") {
                        return retInfo;
                    }

                    var info = this.Format.Fields.Delete(selectionStart, selectionLength);

                    //The same as BackSpace. ("20005[/)02/24" press delete)
                    if (!info.isSucceed) {
                        return retInfo;
                    }

                    retInfo.SelectionStart = info.cursorPos;

                    if (retInfo.SelectionStart == 0 && this.Format.Fields.GetFieldByIndex(0).fieldLabel == "PromptField") {
                        retInfo.SelectionStart = this.Format.Fields.GetFieldByIndex(0).GetLength();
                    }

                    retInfo.SelectionEnd = retInfo.SelectionStart;

                    //Accordingto the changed information, generate BehaviorInfo and invoke UpdateBehavior to finsihed the correlative action.
                    var currentFieldOffset;
                    var currentFieldIndex;
                    var currentFieldInfo = this.Format.Fields.GetFieldIndexByPos(retInfo.SelectionStart);
                    currentFieldIndex = currentFieldInfo.index;
                    currentFieldOffset = currentFieldInfo.offset;

                    if (currentFieldOffset != 0 && this.Format.Fields.GetFieldByIndex(currentFieldIndex).fieldLabel == "PromptField") {
                        retInfo.SelectionStart = retInfo.SelectionStart - currentFieldOffset + this.Format.Fields.GetFieldByIndex(currentFieldIndex).GetLength();
                        retInfo.SelectionEnd = retInfo.SelectionStart;
                    }
                }

                return retInfo;
            };

            /**
            * Perform the delete keydown event.
            * @param start - The start cursor position.
            * @param end   - The start end position.
            */
            BaseUIProcess.prototype.ProcessBackSpace = function (start, end, text) {
            };

            /**
            * Perform the delete keydown event.
            * @param start - The start cursor position.
            * @param end   - The start end position.
            */
            BaseUIProcess.prototype.ProcessDelete = function (start, end, text) {
            };

            /**
            * Get the next caret position according to the special cursor position and keycode(processType).
            * @param cursorPos - The current cursor position.
            * @param keyCode   - The keyCode indicate the key action.
            * @returns Return the cursor position after the key action.
            */
            BaseUIProcess.prototype.GetCaretPosition = function (cursorPos, keyCode, startPos, endPos, literalFieldLabel) {
                var fields = this.Format.Fields;
                var fieldPosInfo = fields.GetFieldIndexByPos(cursorPos);
                var fieldIndex = fieldPosInfo.index;
                var fieldOffset = fieldPosInfo.offset;
                var fieldRange;

                //var startPos;
                //var endPos;
                var i = 0;

                switch (keyCode) {
                    case 36:

                    case 65572:

                    case 65574:
                        // end by Jiang Changcheng <--
                        if (cursorPos <= startPos) {
                            return 0;
                        } else {
                            return startPos;
                        }

                    case 35:

                    case 65571:

                    case 65576:
                        // end by Jiang Changcheng <--
                        if (cursorPos >= endPos) {
                            return fields.GetLength();
                        } else {
                            return endPos;
                        }

                    case 37:
                        if (cursorPos == 0) {
                            return 0;
                        }

                        if (fields.GetFieldByIndex(fieldIndex).fieldLabel == literalFieldLabel) {
                            if (fieldOffset > 0) {
                                cursorPos -= fieldOffset;
                            } else {
                                cursorPos--;
                            }
                        } else {
                            //aaaggg|eebbbMMccddee
                            if (fieldOffset == 0 && fields.GetFieldByIndex(fieldIndex - 1).fieldLabel == literalFieldLabel) {
                                cursorPos -= fields.GetFieldRange(fieldIndex - 1).length;
                            } else {
                                cursorPos--;
                            }
                        }
                        break;

                    case 39:
                        if (cursorPos == fields.GetLength()) {
                            return cursorPos;
                        }

                        if (fields.GetFieldByIndex(fieldIndex).fieldLabel == literalFieldLabel) {
                            fieldRange = fields.GetFieldRange(fieldIndex);
                            startPos = fieldRange.start;
                            endPos = startPos + fieldRange.length;

                            if (cursorPos < endPos) {
                                return endPos;
                            }
                        } else {
                            cursorPos++;
                        }
                        break;

                    case 131109:
                        if (cursorPos == 0 || fieldIndex == 0) {
                            return 0;
                        }

                        if (fields.GetFieldByIndex(fieldIndex).fieldLabel == literalFieldLabel) {
                            fieldRange = fields.GetFieldRange(fieldIndex - 1);
                            cursorPos = fieldRange.start;
                        } else {
                            if (fieldOffset == 0) {
                                for (i = fieldIndex - 1; i >= 0; i--) {
                                    //find the edit field before the current field
                                    if (fields.GetFieldByIndex(i).fieldLabel != literalFieldLabel) {
                                        fieldRange = fields.GetFieldRange(i);

                                        return fieldRange.start;
                                    }
                                }

                                //if the former field is PromptField, then return 0
                                return 0;
                            } else {
                                cursorPos -= fieldOffset;
                            }
                        }
                        break;

                    case 196645:
                        if (cursorPos == 0 || fieldIndex == 0) {
                            return 0;
                        }

                        if (fieldOffset == 0) {
                            fieldRange = fields.GetFieldRange(fieldIndex - 1);
                            cursorPos = fieldRange.start;
                        } else {
                            cursorPos -= fieldOffset;
                        }
                        break;

                    case 131111:
                        if (cursorPos == fields.GetLength() || fieldIndex == fields.fieldCount - 1) {
                            return fields.GetLength();
                        }

                        if (fields.GetFieldByIndex(fieldIndex).fieldLabel == literalFieldLabel) {
                            fieldRange = fields.GetFieldRange(fieldIndex + 1);
                            cursorPos = fieldRange.start;
                        } else {
                            for (i = fieldIndex + 1; i < fields.fieldCount; i++) {
                                //find the edit field after the current field
                                if (fields.GetFieldByIndex(i).fieldLabel != literalFieldLabel) {
                                    fieldRange = fields.GetFieldRange(i);

                                    return fieldRange.start;
                                }
                            }

                            //if the latter field is PromptField, then return fieldcollection length
                            return fields.GetLength();
                        }
                        break;

                    case 196647:
                        if (cursorPos == fields.GetLength() || fieldIndex == fields.fieldCount - 1) {
                            return fields.GetLength();
                        }

                        //if the current caret is in the last field then return the fields' length
                        fieldRange = fields.GetFieldRange(fieldIndex + 1);
                        cursorPos = fieldRange.start;
                        break;

                    case 131118:
                        if (cursorPos == fields.GetLength() || fields.GetFieldByIndex(fieldIndex).fieldLabel == literalFieldLabel) {
                            return cursorPos;
                        } else {
                            fieldRange = fields.GetFieldRange(fieldIndex);

                            return fieldRange.start + fieldRange.length;
                        }

                    case 131080:
                    case 196616:
                        if (cursorPos == 0 || (fields.GetFieldByIndex(fieldIndex).fieldLabel == literalFieldLabel && fieldIndex == 0)) {
                            return cursorPos;
                        } else if (fields.GetFieldByIndex(fieldIndex).fieldLabel == literalFieldLabel) {
                            return fields.GetFieldRange(fieldIndex - 1).start;
                        } else {
                            if (fieldOffset == 0) {
                                for (i = fieldIndex - 1; i >= 0; i--) {
                                    //find the edit field before the current field
                                    if (fields.GetFieldByIndex(i).fieldLabel != literalFieldLabel) {
                                        fieldRange = fields.GetFieldRange(i);

                                        return fieldRange.start;
                                    }
                                }

                                //if there is no edit field before the current field
                                return cursorPos;
                            } else {
                                cursorPos -= fieldOffset;
                            }
                        }
                        break;

                    case 196643:

                    case 131107:

                    case 131112:
                        // end of Sean Huang <--
                        return fields.GetLength();

                    case 196644:

                    case 131108:

                    case 131110:
                        // end of Sean Huang <--
                        return 0;

                    case 65573:
                        if (cursorPos == 0) {
                            return 0;
                        } else {
                            return --cursorPos;
                        }

                    case 65575:
                        if (cursorPos == fields.GetLength()) {
                            return cursorPos;
                        } else {
                            return ++cursorPos;
                        }
                }

                return cursorPos;
            };

            /**
            * Compare the specified keycode with the shortcut array passed from server side.
            * @param keyCode - The keyCode indicate the key action.
            * @param shortcut - The shortcut text passed from server side.
            * @returns Return true if keycode in the shortcuts array otherwise return false.
            */
            BaseUIProcess.prototype.CompareShortcut = function (keyCode, shortcut) {
                if (shortcut.toString().IndexOf("|") == -1) {
                    if (shortcut == keyCode) {
                        return true;
                    } else {
                        return false;
                    }
                } else {
                    var index = null;
                    while (index != -1) {
                        index = shortcut.toString().IndexOf("|");
                        var length = shortcut.toString().GetLength();
                        if (shortcut.Substring(0, index == -1 ? length : index) == keyCode) {
                            return true;
                        } else {
                            shortcut = shortcut.Substring(index + 1, length);
                        }
                    }
                    return false;
                }
            };

            /**
            * Move the focus from one control to another.
            * @param elementID - The current element id.
            * @param isForward - The boolean value indicate if we move focus to the next control according to the tabindex value.
            * @param isUseLeftRightKey - The boolean value indicate if we move focus to the next control by left or right key.
            * @param exitType - The exit type.
            */
            BaseUIProcess.prototype.MoveControl = function (currentElement, isForward, isUseLeftRightKey, exitType) {
                var elements = input.CoreUtility.GetElements();
                var ret = null;
                var retInfo = {};

                //Add by Ryan Wu at 10:24 Jan. 20 2006.
                //For fix bug#4965.
                if (elements.length < 2) {
                    return null;
                }

                //Add comments by Ryan Wu at 14:08 Aug. 28 2007.
                //For the sequence of the onfocus, onblur, onkeydown event in firefox is not same as IE
                //when we use the focus method in keydown.
                //in IE: onkeydown --> onblur --> onfocus.
                //in Firefox: onblur --> onfocus --> onkeydown.
                //So we must split the MoveFocus into two methods. Firstly, We must get the next control's id.
                //Then if we use the ExitOnLeftRightKey to move focus, we should set the next control's FocusType to FocusType.Left/FocusType.Right.
                //Lastly we can invoke the obj.focus method to set focus to the next control.
                //	var nextID = Utility.MoveFocus(elementID, elements, isForward);
                //
                //	if (isUseLeftRightKey == true)
                //	{
                //		try
                //		{
                //		    var index = nextID.LastIndexOf("_EditField");
                //
                //		    if (index != -1)
                //		    {
                //		        var conID = nextID.Substring(0, index);
                //		        var nextObj = FindIMControl(conID);
                //		        nextObj.FocusType = isForward ? FocusType.Left : FocusType.Right;
                //		    }
                //		}
                //		catch(e)
                //		{}
                //    }
                var nextElement = input.CoreUtility.GetNextFocusableControl(currentElement, elements, isForward);

                // TODO:
                //if (isUseLeftRightKey == true) {
                //    try {
                //        var index = nextID.LastIndexOf("_EditField");
                //        if (index != -1) {
                //            var conID = nextID.Substring(0, index);
                //            var nextObj = FindIMControl(conID);
                //            nextObj.FocusType = isForward ? FocusType.Left : FocusType.Right;
                //        }
                //        else {
                //            var nextObj = FindIMControl(nextID);
                //            if (nextObj) {
                //                if (nextObj.IsjQueryControl == true) {
                //                    nextObj.FocusType = isForward ? FocusType.Left : FocusType.Right;
                //                }
                //            }
                //        }
                //    }
                //    catch (e)
                //    { }
                //}
                // change by Sean Huang at 2008.12.16, for bug 1054 -->
                //Utility.SetElementFocus(nextID);
                // change by Sean Huang at 2009.01.04, for bug 1402 -->
                //if (exitType == "CharInput")
                // change by Sean Huang at 2009.02.16, for bug 1863, 1865 -->
                //if (exitType == "CharInput" || (!isIE && isUseLeftRightKey))
                if (exitType == "CharInput" || (!input.CoreUtility.IsIE())) {
                    Utility.NextID = nextElement;
                    setTimeout(function () {
                        input.CoreUtility.SetElementFocus(nextElement);
                    }, 0);
                } else {
                    input.CoreUtility.SetElementFocus(nextElement);
                }

                // end of Sean Huang <--
                // add by Sean Huang at 2008.12.09, for bug 1057, 1058 -->
                // set the cursor position of the standard text box while it is get focus
                // by using the left right key.
                if (isUseLeftRightKey) {
                    var obj = document.getElementById(nextElement);
                    if (obj != null && (obj.tagName.toLowerCase() == "textarea" || obj.type == "text")) {
                        if (input.CoreUtility.IsIE()) {
                            var range = obj.createTextRange();
                            if (exitType == "Left" || exitType == "CtrlLeft") {
                                // move the cursor position to the end
                                range.moveStart('character', obj.value.length);
                                range.select();
                            }
                            //else if (exitType == "Right" || exitType == "CtrlRight")
                            //{
                            //    // ie will move the cusor position to the begin by default
                            //}
                        }
                        // HelenLiu 2013/06/24 fix bug 743 in IM HTML5.
                        //else {
                        //    if (exitType == "Left" || exitType == "CtrlLeft") {
                        //        // move the cursor to the end
                        //        var len = obj.value.length;
                        //        obj.setSelectionRange(len, len);
                        //    }
                        //else if (exitType == "Right" || exitType == "CtrlRight") {
                        //     //move the cursor to the begin
                        //    obj.setSelectionRange(0, 0);
                        //}
                        //}
                    }
                }

                // end of Sean Huang, for bug 1057, 1058<--
                //end by Ryan Wu.
                //invoke the KeyExit Event if it exit
                var eArgs = { Key: 9 /* CharInput */ };

                switch (exitType) {
                    case "NextControl":
                        eArgs.Key = 3 /* NextControl */;
                        break;
                    case "PreviousControl":
                        eArgs.Key = 4 /* PreviousControl */;
                        break;
                    case "Right":
                        eArgs.Key = 5 /* Right */;
                        break;
                    case "Left":
                        eArgs.Key = 6 /* Left */;
                        break;
                    case "CtrlRight":
                        eArgs.Key = 7 /* CtrlRight */;
                        break;
                    case "CtrlLeft":
                        eArgs.Key = 8 /* CtrlLeft */;
                        break;
                    case "CharInput":
                        eArgs.Key = 9 /* CharInput */;
                        break;
                }

                ret = {};
                ret.Name = this.Owner.KeyExitEvent;
                ret.Args = eArgs;

                //Add comments by Ryan Wu at 10:27 Apr. 5 2007.
                //For support Aspnet Ajax 1.0.
                ret.Type = "KeyExit";

                //end by Ryan Wu.
                if (ret != null) {
                    retInfo.EventInfo = ret;
                }

                return retInfo;
            };

            /**
            * Move the caret from one field to another in the control.
            * @param pos - The current caret position.
            * @param isForward - The boolean value indicate if we move caret to the next field or previous field.
            */
            BaseUIProcess.prototype.MoveField = function (pos, isForward) {
                var nextPos = this.Format.Fields.MoveField(pos, isForward);
                var retInfo = {};

                if (nextPos == -1) {
                    retInfo.NextPos = nextPos;
                    return retInfo;
                }

                retInfo.SelectionStart = nextPos;
                retInfo.SelectionEnd = nextPos;
                return retInfo;
            };

            /**
            * Process Tab key press event.
            * @param isForward - The boolean value indicate if we move caret to the forward or backward.
            */
            BaseUIProcess.prototype.ProcessTabKey = function (pos, isForward, tabAction) {
                //invoke the KeyExit Event if it exit
                var eArgs = { Key: 1 /* Tab */ };
                var retInfo = {};
                if (isForward) {
                    eArgs.Key = 1 /* Tab */;
                } else {
                    eArgs.Key = 2 /* ShiftTab */;
                }

                var eventInfo = {};
                eventInfo.Name = this.Owner.KeyExitEvent;
                eventInfo.Args = eArgs;

                //Add comments by Ryan Wu at 10:27 Apr. 5 2007.
                //For support Aspnet Ajax 1.0.
                eventInfo.Type = "KeyExit";

                //end by Ryan Wu.
                retInfo.EventInfo = eventInfo;

                retInfo.FocusType = 4 /* KeyExit */;
                retInfo.System = true;

                return retInfo;
            };

            /**
            * Move caret between fields then move focus to the next control if caret is in the edge
            * of the control.
            * @param isForward - The boolean value indicate if we move caret to the forward or backward.
            */
            BaseUIProcess.prototype.MoveFieldAndControl = function (pos, isForward) {
                var retInfo = this.MoveField(pos, isForward);

                //retInfo.NextPos == -1 indicate that we have move the caret to the edge of the control.
                if (retInfo.NextPos != -1) {
                    return retInfo;
                }

                var exitType = isForward ? "NextControl" : "PreviousControl";
                var ret = this.MoveControl(this.GetInputElement(), isForward, false, exitType);

                if (ret != null) {
                    retInfo.EventInfo = ret.EventInfo;
                    retInfo.FocusType = ret.FocusType;
                    retInfo.FocusExit = true;
                }

                return retInfo;
            };

            /**
            * Handle the ondragstart event.
            */
            BaseUIProcess.prototype.DragStart = function () {
            };

            /**
            * Handle the ondragend event.
            */
            BaseUIProcess.prototype.DragEnd = function () {
            };

            /**
            * Handle the ondrop event.
            */
            BaseUIProcess.prototype.Drop = function () {
            };

            /**
            * Handle the ondragover event.
            */
            BaseUIProcess.prototype.DragOver = function () {
            };

            /**
            * Parse the shortcutsString and judge whether the key user pressed
            * is a shortcutkey defined by deveploper.
            * not replace indexOf, substring method, because autotest is slow
            * @param keyCode - The specified keyCode will be checked.
            * @param strShortcut - The shortcuts string passed from the server side.
            * @returns Returns the shortcut's keyAction Name if contains the specified
            *          keyCode action; else return null.
            */
            BaseUIProcess.prototype.GetKeyActionName = function (keyCode, strShortcut) {
                if (strShortcut == null) {
                    return null;
                }

                var s = strShortcut;
                var shortcuts = new Array();
                var index = s.IndexOf(",");
                var i = 0;

                if (strShortcut != "") {
                    while (index != -1) {
                        shortcuts[i++] = s.Substring(0, index);
                        s = s.Substring(index + 1, s.GetLength());
                        index = s.IndexOf(",");
                    }
                    shortcuts[i++] = s;

                    for (var j = 0; j < i; j = j + 2) {
                        if (this.IsKeyCodeContained(keyCode, shortcuts[j + 1])) {
                            return shortcuts[j];
                        }
                    }
                }
                return null;
            };

            /**
            * Judge whether the keyCode is contained in the shortcuts's item.
            * @param keyCode - The specified keyCode will be checked.
            * @param shortcut - The shortcuts's item.
            * @returns Returns true if contains the specified keyCode action; else return false.
            */
            BaseUIProcess.prototype.IsKeyCodeContained = function (keyCode, shortcut) {
                var s = shortcut;
                var index = s.IndexOf("|");

                while (index != -1) {
                    if (s.Substring(0, index) == keyCode) {
                        return true;
                    }
                    s = s.Substring(index + 1, s.GetLength());
                    index = s.IndexOf("|");
                }

                if (s == keyCode) {
                    return true;
                }

                return false;
            };

            /**
            *fire event
            */
            BaseUIProcess.prototype.FireClientEvent = function (evenType) {
                // TODO:
            };

            BaseUIProcess.prototype.PerformSpin = function (curpos, increment, wrap) {
            };

            /**
            * update crlf string for AcceptsCrLf property
            */
            BaseUIProcess.UpdateCrLfString = function (text, crlfMode) {
                var ret = text;

                if (text) {
                    if (crlfMode == 1 /* Filter */) {
                        ret = text.replace(new RegExp("[\r\n]", "g"), "");
                    } else if (crlfMode == 2 /* Cut */) {
                        var splits = text.split(new RegExp("[\r\n]", "g"));
                        if (splits.length > 0) {
                            ret = splits[0];
                        } else {
                            ret = "";
                        }
                    }
                }

                return ret;
            };

            BaseUIProcess.FilterReturnChar = function (text) {
                if (text != null) {
                    text = text.replace(new RegExp("[\r]", "g"), "");
                }
                return text;
            };
            return BaseUIProcess;
        })();
        input.BaseUIProcess = BaseUIProcess;

        

        /** @ignore */
        var InputUIUpdate = (function () {
            function InputUIUpdate(owner) {
                this.Owner = owner;
            }
            InputUIUpdate.prototype.SetLastClientValues = function (text) {
                //var obj = document.getElementById(this.ID + Utility.LastClientValuesID);
                //if (obj != null) {
                //    obj.value = text;
                //}
                //this.lastclientvalues = text;
            };

            InputUIUpdate.prototype.GetText = function () {
                if (this.Owner.GetInputElement() != null) {
                    return this.Owner.GetInputElement().value;
                }
            };

            InputUIUpdate.prototype.SetText = function (text) {
                if (this.GetText() == null) {
                    return;
                }

                if (this.GetText().replace(/\r\n/g, "\n") == text.replace(/\r\n/g, "\n")) {
                    return;
                }

                if (this.Owner.GetInputElement() != null) {
                    this.Owner.GetInputElement().value = text;
                }
            };

            InputUIUpdate.prototype.SetFocus = function () {
                try  {
                    if (this.Owner.GetInputElement() != null) {
                        this.Owner.GetInputElement().focus();
                    }
                } catch (e) {
                }
            };

            InputUIUpdate.prototype.GetTextHAlign = function () {
                if (this.Owner.GetInputElement() !== null) {
                    return this.Owner.GetInputElement().style.textAlign;
                }
                return "";
            };

            InputUIUpdate.prototype.SetTextHAlign = function (value) {
                if (this.Owner.GetInputElement() !== null) {
                    this.Owner.GetInputElement().style.textAlign = value;

                    if (input.CoreUtility.IsIE()) {
                        // Change the width to trigger the layout, to make this property take affect immediately.
                        var old = this.Owner.GetInputElement().style.width;
                        var length = parseInt(old);
                        if (isNaN(length)) {
                            length = 120;
                        }
                        this.Owner.GetInputElement().style.width = length + 1 + "px";
                        var self = this;
                        setTimeout(function () {
                            self.InputElement.style.width = old;
                        }, 0);
                    }
                }
            };

            InputUIUpdate.prototype.SetForeColor = function (foreColor) {
                if (this.Owner.GetInputElement() != null) {
                    this.Owner.GetInputElement().style.color = foreColor;
                }
            };

            InputUIUpdate.prototype.WriteCssStyle = function (style) {
                try  {
                    var styleContainer = document.getElementById('gcsh_InputManWeb_Style_Container');

                    if (input.CoreUtility.IsIE()) {
                        styleContainer.styleSheet.cssText = style;
                    } else {
                        var sheet = styleContainer.sheet;

                        for (var i = sheet.cssRules.length - 1; i >= 0; i--) {
                            sheet.deleteRule(i);
                        }

                        var ruleLines = style.split('}');

                        for (var j = 0; j < ruleLines.length; j++) {
                            var rule = ruleLines[j];
                            var index = rule.indexOf('{');

                            if (index == -1) {
                                continue;
                            }

                            var style = rule.substring(index + 1);

                            if (style.length != 0) {
                                var selector = rule.substring(0, index);
                                sheet.insertRule(selector + '{' + style + '}', sheet.cssRules.length);
                            }
                        }
                    }
                } catch (e) {
                }
            };

            InputUIUpdate.prototype.ClearCssStyle = function () {
            };
            return InputUIUpdate;
        })();
        input.InputUIUpdate = InputUIUpdate;

        /** @ignore */
        var GlobalEventHandler = (function () {
            function GlobalEventHandler() {
            }
            GlobalEventHandler.OnKeyDown = function (control, evt, forShortcutExtender) {
                if (control.ImeMode === true && !input.CoreUtility.IsIE8OrBelow()) {
                    return;
                }

                // debugger;
                var k = evt.keyCode;

                //Add comments by Jiang Changcheng at Sep. 9 2008
                //Add the fake key for Shortcut Extender
                if (forShortcutExtender) {
                    k |= 524288;
                }

                //End by Jiang Changcheng
                var funcKeysPressed = {};
                funcKeysPressed.Shift = false;
                funcKeysPressed.Ctrl = false;
                funcKeysPressed.Alt = false;
                if (evt.shiftKey) {
                    funcKeysPressed.Shift = true;
                }

                if (evt.ctrlKey) {
                    funcKeysPressed.Ctrl = true;
                }

                if (evt.altKey) {
                    funcKeysPressed.Alt = true;
                }
                var useSystem = null;

                //Add comments by Ryan Wu at 16:55 Sep. 11 2007.
                //For fix the bug "17. Ctrl+Click(select all text) will take no effects(firefox).".
                Utility.FuncKeysPressed = funcKeysPressed;

                try  {
                    useSystem = control.KeyDown(evt);
                } catch (e) {
                }

                //Added by Jeff for Edit
                if (useSystem != null && useSystem.KeyCode != null) {
                    // Add comments by Yang at 11:44 Sep. 5th 2007
                    // For event.keyCode is readonly in firefox.
                    // Firefox doesn't support some shortcuts.
                    //event.keyCode = useSystem.KeyCode;
                    if (input.CoreUtility.IsIE()) {
                        evt.keyCode = useSystem.KeyCode;
                    }

                    // End by Yang
                    //Add comments by Ryan Wu at 15:35 Aug. 13 2007.
                    //For in firefox, even if we set the event.returnValue = false in keydown event,
                    //the keypress event will also be invoked while in IE will not.
                    if (!input.CoreUtility.IsIE()) {
                        Utility.ShouldInvokeKeyPress = false;
                    }

                    //end by Ryan Wu.
                    return;
                }

                //Add comments by Ryan Wu at 15:35 Aug. 13 2007.
                //For in firefox, even if we set the event.returnValue = false in keydown event,
                //the keypress event will also be invoked while in IE will not.
                //	if (!useSystem)
                //	{
                //		event.returnValue = false;
                //	    //event.cancelBubble = true;
                //	}
                if (!useSystem) {
                    Utility.PreventDefault(evt);

                    //event.cancelBubble = true;
                    if (!input.CoreUtility.IsIE()) {
                        Utility.ShouldInvokeKeyPress = false;
                    }
                } else {
                    if (!input.CoreUtility.IsIE()) {
                        Utility.ShouldInvokeKeyPress = true;
                    } else if (evt != null) {
                        evt.returnValue = true;
                    }
                }
            };

            GlobalEventHandler.OnKeyPress = function (control, evt) {
                // Ctrl + X, Ctrl + V, Ctrl + C.
                if ((evt.charCode === 118 || evt.charCode === 120 || evt.charCode === 99) && evt.ctrlKey) {
                    // Fire fox 's paste behavior will run at here.
                    return;
                }

                if (input.CoreUtility.IPadAndIPhone && evt.charCode > 256) {
                    // DaryLuo 2013/05/22 fix bug 414, on the ipad, when the charCode is greater than 256, the compoistion event will fired, so here we don't process.
                    return;
                }

                if (evt.keyCode == 46 && evt.shiftKey) {
                    // FireFox Shift + Delete will run at here.  Cut operation.
                    return;
                }

                if (control.ImeMode === true) {
                    return;
                }
                var obj = control;

                if (!input.CoreUtility.IsIE() && (evt.charCode == 0 || !Utility.ShouldInvokeKeyPress)) {
                    if (!Utility.ShouldInvokeKeyPress || ((evt.keyCode == 38 || evt.keyCode == 40) && obj.Type != "Edit")) {
                        Utility.ShouldInvokeKeyPress = true;
                        Utility.PreventDefault(evt);

                        // Add comments by Yang at 20:15 October 15th 2007
                        // For fix the bug 9047
                        if (obj != null && obj.Type == "Edit" && obj.DropDownObj != null && obj.DropDownObj.IsKeyFromDropDown) {
                            obj.DropDownObj.IsKeyFromDropDown = false;
                        }

                        // End by Yang
                        return;
                    } else if (!(evt.keyCode == 13 && obj.Type == "Edit")) {
                        return;
                    }
                }

                var keyCode = evt.keyCode || evt.charCode;

                if (keyCode != 13 || obj.Type == "Edit") {
                    var str = String.fromCharCode(keyCode);

                    try  {
                        if (input.CharProcess.CharEx.IsSurrogate(str.charAt(0))) {
                            // DaryLuo 2012/09/17 fix bug 630 in IM Web 7.0, do it in keyup.
                            obj.IsSurrogateKeyPressing = true;
                            return;
                        }
                    } catch (e) {
                    }
                    if (str != null) {
                        var useSystem = null;

                        try  {
                            useSystem = GlobalEventHandler.CallKeyPress(control, str, evt);
                        } catch (e) {
                        }
                    }
                    if (!useSystem) {
                        Utility.PreventDefault(evt);

                        //event.cancelBubble = true;
                        return;
                    }
                }
            };

            GlobalEventHandler.CallKeyPress = function (control, str, evt) {
                if (input.CoreUtility.IsPad()) {
                    control.HasInput = true;
                    return true;
                } else {
                    var useSystem = control.KeyPress(str, evt);
                    return useSystem;
                }
            };

            GlobalEventHandler.OnKeyUp = function (control, evt) {
                if (control.ImeMode === true && !input.CoreUtility.IsIE8OrBelow()) {
                    return;
                }
                try  {
                    var imControl = control;
                    if (imControl.IsSurrogateKeyPressing) {
                        try  {
                            if (imControl.InputElement != null) {
                                var value = imControl.InputElement.value;
                                var selectionStart = imControl.InputElement.selectionStart;
                                var str = value.substr(selectionStart - 2, selectionStart);
                                imControl.KeyPress(str, evt);
                            }
                        } finally {
                            imControl.IsSurrogateKeyPressing = false;
                        }
                    }

                    //Add comments by Ryan Wu at 16:55 Sep. 11 2007.
                    //For fix the bug "17. Ctrl+Click(select all text) will take no effects(firefox).".
                    Utility.FuncKeysPressed = { Shift: evt.shiftKey, Ctrl: evt.ctrlKey, Alt: evt.altKey };

                    //end by Ryan Wu.
                    imControl.KeyUp(evt);
                    //event.cancelBubble = true;
                } catch (e) {
                }
            };

            GlobalEventHandler.OnCompositionStart = function (control, evt) {
                try  {
                    if (input.CoreUtility.IsPad()) {
                        control.ImeMode = true;
                        if (input.CoreUtility.IsAndroid()) {
                            // initialize _compositionEndFired
                            control._compositionEndFired = false;
                        }

                        return;
                    }
                    control.CompositionStart(evt);
                } catch (e) {
                }
            };

            GlobalEventHandler.OnCompositionUpdate = function (control, evt) {
                try  {
                    if (input.CoreUtility.IsPad()) {
                        return;
                    }
                    control.CompositionUpdate(evt);
                } catch (e) {
                }
            };

            GlobalEventHandler.OnCompositionEnd = function (control, evt) {
                try  {
                    if (input.CoreUtility.IsPad()) {
                        control.HasInput = true;
                        control.ImeMode = false;
                        if (input.CoreUtility.IsAndroid()) {
                            // In chrome 61(android), when we input the direct text, the keycode is always 229,
                            // 1. if the text correction is open in ime:
                            //		keydown, compostionStart, compostionUpdate, input, keyup,...,compositionEnd, keydown, textinput, input, keyup
                            //	In this case, we need process the input text in the input event after textinput, because we can get the correct text in this event.
                            // 2. if the text correction is not open:
                            //		keydown, textinput, keyup
                            //	In this case, we need process the input text in the textinput event.
                            // 3. no matter whether text correction is open, the delete, backspace key should be processed in keyup event. It cannot be processed in
                            // the textinput event and the input event as the focus process is complex and we use the same behavior in the non-mobile browser.
                            control._compositionEndFired = true; // if compositionEnd is fired, it is the case 1.
                        }
                        return;
                    }
                    control.CompositionEnd(evt);
                } catch (e) {
                }
            };

            GlobalEventHandler.OnTextInput = function (control, evt) {
                if (control.ImeMode && control._compositionEndFired !== true) {
                    control.HasTextInput = false;
                    control.TextInput(evt);
                    Utility.PreventDefault(evt); // forbid firing the input event.
                } else {
                    // if it is the case 1,
                    control.HasTextInput = true;
                }

                if (control._compositionEndFired === true) {
                    control._compositionEndFired = false;
                }
            };

            GlobalEventHandler.OnInput = function (control, evt) {
                try  {
                    if (input.CoreUtility.IsAndroid() && control.ImeMode && !control.HasTextInput) {
                        control.UIProcess.keyupResponse = true;
                        control.UIProcess.systemEdit = true;
                        control.ImeMode = false;
                        return;
                    }

                    if (control.HasTextInput !== true && (control.ImeMode === true || control.HasInput !== true)) {
                        return;
                    }

                    control.ImeMode = true;
                    control.HasInput = false;
                    control.HasTextInput = false;
                    control.Input(evt);
                } catch (e) {
                }
            };

            GlobalEventHandler.OnMouseOver = function (control, evt) {
                try  {
                    if (control.MouseOver) {
                        control.MouseOver();
                    }
                } catch (e) {
                }
            };

            GlobalEventHandler.OnMouseOut = function (control, evt) {
                try  {
                    control.MouseOut();
                } catch (e) {
                }
            };

            GlobalEventHandler.OnMouseMove = function (control, evt) {
                try  {
                    if (control.MouseMove) {
                        control.MouseMove(evt);
                    }
                } catch (e) {
                }
            };

            GlobalEventHandler.OnMouseDown = function (control, evt) {
                if (control.ImeMode && control.ImeMode === true && !input.CoreUtility.IsIE8OrBelow()) {
                    return;
                }
                try  {
                    control.MouseDown(evt);

                    if (!input.CoreUtility.IsIE()) {
                        Utility.DragStartElementID = control;
                    }
                } catch (e) {
                }
            };

            GlobalEventHandler.OnMouseUp = function (imControl, evt) {
                if (imControl.ImeMode && imControl.ImeMode === true && !input.CoreUtility.IsIE8OrBelow()) {
                    return;
                }
                try  {
                    // DaryLuo 2013/07/12 fix bug 933, 934 in IM HTML 5.
                    if (imControl.MouseUpPointerType != null && imControl.MouseUpPointerType !== 4 && imControl.MouseUpPointerType !== "mouse") {
                        var evtClone = {};
                        for (var item in evt) {
                            evtClone[item] = evt[item];
                        }
                        setTimeout(function (parameters) {
                            imControl.MouseUp(evtClone);
                        }, 300);
                    } else {
                        imControl.MouseUp(evt);
                    }

                    if (!input.CoreUtility.IsIE()) {
                        Utility.DragStartElementID = "";
                    }
                } catch (e) {
                }
            };

            GlobalEventHandler.OnSelectStart = function (control, evt) {
                if (Utility.InnerSelect === true && Utility.ShouldFireOnSelectStart == false) {
                    Utility.CancelBubble(evt);
                }

                var selText = Utility.GetSelectionText(control.GetInputElement());

                if (typeof (selText) == "undefined" || selText == null) {
                    selText = "";
                }
                var useSystem = null;

                try  {
                    useSystem = control.SelectStart(selText);
                } catch (e) {
                }

                if (useSystem == false) {
                    Utility.PreventDefault(evt);
                }
            };

            GlobalEventHandler.OnDblClick = function (control, evt) {
                var useSystem = null;
                try  {
                    useSystem = control.DoubleClick();
                } catch (e) {
                }

                if (!useSystem) {
                    Utility.PreventDefault(evt);
                }
            };

            GlobalEventHandler.OnHTML5BeforeCopy = function (control, evt) {
                try  {
                    Utility.CutCopyPasteEventObject = evt ? evt.originalEvent : evt;
                    control.Copy(evt);
                } catch (e) {
                } finally {
                    Utility.CutCopyPasteEventObject = null;
                }
            };

            GlobalEventHandler.OnHTML5Cut = function (control, evt) {
                try  {
                    var inputElement = control.GetInputElement();
                    var text = inputElement.value;
                    var selStart = inputElement.selectionStart;
                    var selEnd = inputElement.selectionEnd;
                    setTimeout(function () {
                        inputElement.value = text;
                        inputElement.selectionStart = selStart;
                        inputElement.selectionEnd = selEnd;
                        control.Cut(evt);
                    }, 0);
                    // Let browser do it.
                } catch (e) {
                }
            };

            GlobalEventHandler.OnHTML5Paste = function (control, evt) {
                try  {
                    // DaryLuo 2013/05/21, the paste operation doesn't take effect on the android chrome.
                    if (input.CoreUtility.chrome && !input.CoreUtility.IsAndroid()) {
                        Utility.CutCopyPasteEventObject = evt ? evt.originalEvent : evt;

                        control.Paste(Utility.GetDataFromClipboard(true));
                        Utility.PreventDefault(evt);
                    } else {
                        var selStart = control.SelectionStart;
                        var selEnd = control.SelectionEnd;
                        setTimeout(function () {
                            if (input.CoreUtility.IsAndroid()) {
                                // DaryLuo 2013/05/27 fix bug 371 in IM HTML5.0.
                                control.SelectionStart = selStart;
                                control.SelectionEnd = selEnd;
                            }

                            control.isPasting = true;

                            // Firefox & android chrome will run at here.
                            control.ImeInput("DirectInput");
                        }, 0);
                    }
                } catch (e) {
                } finally {
                    Utility.CutCopyPasteEventObject = null;
                }
            };

            GlobalEventHandler.OnMouseWheel = function (control, evt) {
                try  {
                    control.MouseWheel(evt);
                    if (control.ShouldCancelMouseWheelDefaultBehavior()) {
                        Utility.PreventDefault(evt);
                    }
                } catch (e) {
                }
            };

            GlobalEventHandler.OnDragStart = function (control, evt) {
                try  {
                    control.DragStart();
                } catch (e) {
                }
            };

            GlobalEventHandler.OnDragEnd = function (control, evt) {
                try  {
                    control.DragEnd(evt);
                } catch (e) {
                }
            };

            GlobalEventHandler.OnDrop = function (control, evt) {
                try  {
                    var text = evt.originalEvent.dataTransfer.getData("Text");
                    control.DragDrop(text, evt);
                } catch (e) {
                }
            };

            GlobalEventHandler.OnTouchStart = function (control, evt) {
                Utility.TouchStartTime = new Date();
                Utility.TouchStartEvt = evt;
            };

            GlobalEventHandler.OnTouchEnd = function (control, evt) {
                if (Utility.TouchStartTime !== undefined) {
                    Utility.TouchEndTime = new Date();
                    var offset = Utility.TouchEndTime.valueOf() - Utility.TouchStartTime.valueOf();
                    if (offset > 1000) {
                        var text = "";
                        try  {
                            text = Utility.GetSelectionText(control.GetInputElement());
                        } catch (e) {
                        }
                        control.ShowContextMenu(text, Utility.TouchStartEvt);
                        if (control.GetEnabled()) {
                            Utility.PreventDefault(evt);
                        }
                    }
                    Utility.TouchStartTime = undefined;
                    Utility.TouchEndTime = undefined;
                }
            };

            GlobalEventHandler.OnDragEnter = function (control, evt) {
                try  {
                    control.DragEnter();
                } catch (e) {
                }
            };

            GlobalEventHandler.OnDragLeave = function (control, evt) {
                try  {
                    control.DragLeave();
                } catch (e) {
                }
            };

            GlobalEventHandler.OnSelect = function (control, evt) {
                try  {
                    if (input.CoreUtility.IsPad() && control.ImeMode) {
                        return;
                    }
                    if (control && control.Focused) {
                        control.Select();
                    }
                } catch (e) {
                }
            };

            GlobalEventHandler.OnPropertyChanged = function (control, evt) {
                try  {
                    control.PropertyChange(evt);
                } catch (e) {
                }
            };

            GlobalEventHandler.OnMSPointerUp = function (control, evt) {
                control.MSPointerUp(evt);
            };

            GlobalEventHandler.OnMSPointerDown = function (control, evt) {
                try  {
                    control.MSPointerDown(evt);
                } catch (e) {
                }
            };

            GlobalEventHandler.OnMSGestureTap = function (control, evt) {
                try  {
                    control.MSGestureTap(evt);
                } catch (e) {
                }
            };

            GlobalEventHandler.OnEditFieldFocus = function (control, evt) {
                if (Utility.IsFocusFromIMControl(control._id, evt)) {
                    if (input.CoreUtility.IsIE() || Utility.HasGetFocus) {
                        return;
                    }
                }

                //if (!Utility.firefox) {
                //    if (Utility.IsOnFocus) {
                //        if (GrapeCity.IM.Utility.IsIE() && Utility.IsOnActivate || Utility.HasGetFocus) {
                //            return;
                //        }
                //    }
                //}
                Utility.IsOnFocus = true;
                if (!input.CoreUtility.IsIE()) {
                    Utility.HasGetFocus = true;
                }
                this.OnFocus(control, evt);
                //onFocus(id);
                //Utility.FireEvent(document.getElementById(id), eventName, null);
                // end of Sean Huang <--
            };

            GlobalEventHandler.OnEditFieldLoseFocus = function (control, evt) {
                try  {
                    //function gcsh_InputManWeb_onLoseFocus(eventName, id) {
                    var obj = control;

                    if (obj != null && obj.Type == "Edit" && obj.IsFocusToDropDownEdit) {
                        obj.IsFocusToDropDownEdit = false;
                        return;
                    }

                    // Temporarily comment at 2013/08/13.
                    //if (!Utility.IsIE() && obj != null && obj.IMControlType == "Date" && obj.DropDownObj != null) {
                    //    if (Utility.IsFireFox4OrLater()) {
                    //        if (obj.DropDownObj.IsNavigateMouseDown) {
                    //            obj.DropDownObj.IsNavigateMouseDown = null;
                    //            return;
                    //        }
                    //        if (obj.DropDownObj.IsZoomButtonMouseDown) {
                    //            obj.DropDownObj.IsZoomButtonMouseDown = null;
                    //            return;
                    //        }
                    //    }
                    //    if (obj.DropDownObj.IsHeaderMouseDown) {
                    //        obj.DropDownObj.IsHeaderMouseDown = null;
                    //        return;
                    //    }
                    //}
                    if (Utility.IsFocusToIMControl(control._id, evt)) {
                        return;
                    }

                    if (input.CoreUtility.firefox) {
                        if (Utility.IsOnFocus && input.CoreUtility.IsIE() && Utility.IsOnActivate && Utility.IsOnActivateControlID == control._id) {
                            if (Utility.FocusToBorder != null && Utility.FocusToBorder == true) {
                                Utility.FocusToBorder = false;
                                obj.SetInnerFocus();
                            }

                            return;
                        }

                        Utility.FocusToBorder = false;

                        if (!input.CoreUtility.IsIE()) {
                            Utility.HasGetFocus = false;
                        } else {
                            Utility.IsOnFocus = false;
                        }
                    }

                    GlobalEventHandler.OnLostFocus(control, evt);

                    Utility.FuncKeysPressed = { Shift: false, Ctrl: false, Alt: false };
                    //Utility.FireEvent(control, "LoseFocus", null);
                } catch (e) {
                }
            };

            GlobalEventHandler.OnFocusOut = function (control, evt) {
                Utility.FocusToBorder = false;

                if (input.CoreUtility.IsIE()) {
                    if (evt.toElement) {
                        var toID = evt.toElement.id;
                        if (toID == control._id + "_Inside_Div_Container") {
                            Utility.FocusToBorder = true;
                        }
                    }
                }

                if (Utility.IsFocusToIMControl(control._id, evt)) {
                    if (input.CoreUtility.IsIE9OrLater()) {
                        Utility.IsOnActivate = true;
                        Utility.IsOnActivateControlID = control._id;
                        Utility.IsOnFocus = true;
                    }
                    return;
                }
                if (input.CoreUtility.IsIE() && Utility.IsOnActivate) {
                    Utility.IsOnActivate = false;
                    Utility.IsOnActivateControlID = "";
                }
                if (Utility.IsOnFocus) {
                    Utility.IsOnFocus = false;
                }
            };

            GlobalEventHandler.OnActivate = function (control, evt) {
                Utility.IsOnActivate = true;
                Utility.IsOnActivateControlID = control._id;

                if (Utility.IsFocusFromIMControl(control._id, evt)) {
                    return;
                }

                Utility.IsOnActivate = true;
                Utility.IsOnActivateControlID = control._id;
            };

            GlobalEventHandler.OnDeActivate = function (control, evt) {
                if (Utility.IsFocusToIMControl(control._id, evt)) {
                    return;
                }

                Utility.IsOnActivate = false;
                Utility.IsOnActivateControlID = "";

                Utility.IsOnFocus = false;
            };

            GlobalEventHandler.OnFocus = function (control, evt) {
                try  {
                    var handler = function () {
                        control.Focus();
                        control.Focused = true;

                        if (input.CoreUtility.IsPad()) {
                            // DaryLuo 2013/05/27 fix bug 412 in IM HTML 5.0.
                            control.IPadSelectionRefreshTimer = setInterval(function (evt) {
                                GlobalEventHandler.OnSelect(control, evt);
                            }, 400);
                        }
                    };
                    if (input.CoreUtility.IsIE()) {
                        handler.call(this);
                    } else {
                        setTimeout(handler, 0);
                    }
                } catch (e) {
                }
            };

            GlobalEventHandler.OnLostFocus = function (control, evt) {
                try  {
                    control.LoseFocus(evt);
                    control.Focused = false;

                    if (input.CoreUtility.IsPad()) {
                        clearInterval(control.IPadSelectionRefreshTimer);
                    }
                } catch (e) {
                }
            };
            return GlobalEventHandler;
        })();
        input.GlobalEventHandler = GlobalEventHandler;
    })(wijmo.input || (wijmo.input = {}));
    var input = wijmo.input;
})(wijmo || (wijmo = {}));

;
/// <reference path="../External/declarations/jquery.d.ts"/>
/// <reference path="../External/declarations/globalize.d.ts"/>
/// <reference path="../wijutil/jquery.wijmo.wijutil.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*
    * Depends:
    *	jquery-1.11.1.js
    *	globalize.js
    *  jquery.wijmo.wijutil.js
    *
    */
    (function (input) {
        /** @ignore */
        function paddingZero(val, aCount) {
            if (typeof aCount === "undefined") { aCount = 2; }
            var text = '' + val + '';
            if (text.length > aCount) {
                text = text.substr(text.length - aCount);
            } else
                while (text.length < aCount) {
                    text = '0' + text;
                }
            return text;
        }
        input.paddingZero = paddingZero;

        (function (DescriptorType) {
            DescriptorType[DescriptorType["liternal"] = -1] = "liternal";

            DescriptorType[DescriptorType["OneDigitYear"] = 1] = "OneDigitYear";
            DescriptorType[DescriptorType["TwoDigitYear"] = 2] = "TwoDigitYear";
            DescriptorType[DescriptorType["FourDigitYear"] = 10] = "FourDigitYear";

            DescriptorType[DescriptorType["TwoDigitMonth"] = 20] = "TwoDigitMonth";
            DescriptorType[DescriptorType["Month"] = 25] = "Month";
            DescriptorType[DescriptorType["AbbreviatedMonthNames"] = 26] = "AbbreviatedMonthNames";
            DescriptorType[DescriptorType["MonthNames"] = 27] = "MonthNames";

            DescriptorType[DescriptorType["EraYear"] = 70] = "EraYear";
            DescriptorType[DescriptorType["TwoEraYear"] = 71] = "TwoEraYear";
            DescriptorType[DescriptorType["EraName"] = 72] = "EraName";
            DescriptorType[DescriptorType["TwoEraName"] = 73] = "TwoEraName";
            DescriptorType[DescriptorType["ThreeEraName"] = 74] = "ThreeEraName";
            DescriptorType[DescriptorType["EraYearBig"] = 75] = "EraYearBig";

            DescriptorType[DescriptorType["AD"] = 80] = "AD";

            DescriptorType[DescriptorType["TwoDigityDayOfMonth"] = 30] = "TwoDigityDayOfMonth";
            DescriptorType[DescriptorType["DayOfMonth"] = 31] = "DayOfMonth";
            DescriptorType[DescriptorType["AbbreviatedDayNames"] = 100] = "AbbreviatedDayNames";
            DescriptorType[DescriptorType["DayNames"] = 101] = "DayNames";

            DescriptorType[DescriptorType["h"] = 45] = "h";
            DescriptorType[DescriptorType["hh"] = 46] = "hh";
            DescriptorType[DescriptorType["H"] = 47] = "H";
            DescriptorType[DescriptorType["HH"] = 48] = "HH";

            DescriptorType[DescriptorType["ShortAmPm"] = 250] = "ShortAmPm";
            DescriptorType[DescriptorType["AmPm"] = 251] = "AmPm";

            DescriptorType[DescriptorType["mm"] = 50] = "mm";
            DescriptorType[DescriptorType["m"] = 51] = "m";

            DescriptorType[DescriptorType["ss"] = 60] = "ss";
            DescriptorType[DescriptorType["s"] = 61] = "s";
        })(input.DescriptorType || (input.DescriptorType = {}));
        var DescriptorType = input.DescriptorType;

        ////////////////////////////////////////////////////////////////////////////////
        // _iDateDescriptor
        /** @ignore */
        var _iDateDescriptor = (function () {
            function _iDateDescriptor(textProvider, id) {
                this.id = id;
                this.startIndex = 0;
                this.name = null;
                this.type = -1 /* liternal */;
                this.maxLen = 2;
                this.formatString = "";
                this._txtProvider = textProvider;
                this.startIndex = 0;
            }
            _iDateDescriptor.prototype.getText = function () {
                return null;
            };

            _iDateDescriptor.prototype.getRealText = function (text) {
                var opt = this._txtProvider.inputWidget.options;
                if (opt.date == null) {
                    if (opt.promptChar !== '') {
                        var tmp = '';
                        for (var i = 0; i < this.formatString.length; i++) {
                            tmp += opt.promptChar;
                        }
                        return tmp;
                    }
                    return this.formatString;
                }
                return text;
            };

            _iDateDescriptor.prototype.setText = function (value, allowchangeotherpart, result, isSmartInputMode) {
                return false;
            };

            _iDateDescriptor.prototype.inc = function () {
            };
            _iDateDescriptor.prototype.dec = function () {
            };
            _iDateDescriptor.prototype.needAdjustInsertPos = function () {
                return true;
            };
            _iDateDescriptor.prototype.reachMaxLen = function () {
                var t = this.getText();
                do {
                    if (t.charAt(0) === '0') {
                        t = t.slice(1);
                    } else {
                        break;
                    }
                } while(t.length > 0);
                return t.length >= this.maxLen;
            };
            return _iDateDescriptor;
        })();
        input._iDateDescriptor = _iDateDescriptor;

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor
        var _dateDescriptor = (function (_super) {
            __extends(_dateDescriptor, _super);
            function _dateDescriptor(owner, id) {
                _super.call(this, owner, id);
                this.liternal = '';
                this.maxLen = 100;
            }
            _dateDescriptor.prototype.getText = function () {
                return this.liternal;
            };
            return _dateDescriptor;
        })(_iDateDescriptor);

        var EraYearDescriptor = (function (_super) {
            __extends(EraYearDescriptor, _super);
            function EraYearDescriptor(owner, id) {
                _super.call(this, owner, id);
            }
            EraYearDescriptor.prototype.inc = function () {
                var date = this._txtProvider.getDate();
                var minDate = this._txtProvider.inputWidget._getRealEraMinDate();
                var maxDate = this._txtProvider.inputWidget._getRealEraMaxDate();

                if (DateTimeInfo.Equal(date, maxDate)) {
                    if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                        this._txtProvider.setDate(new Date(minDate.valueOf()));
                    }
                } else {
                    var increment = this._txtProvider.inputWidget._getInnerIncrement();
                    this._txtProvider.setYear(this._txtProvider.getYear() + increment, null, true);
                    if (this._txtProvider.getDate() > maxDate) {
                        this._txtProvider.setDate(new Date(maxDate.valueOf()));
                    }
                }
            };

            EraYearDescriptor.prototype.dec = function () {
                var date = this._txtProvider.getDate();
                var minDate = this._txtProvider.inputWidget._getRealEraMinDate();
                var maxDate = this._txtProvider.inputWidget._getRealEraMaxDate();

                if (DateTimeInfo.Equal(date, minDate)) {
                    if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                        this._txtProvider.setDate(new Date(maxDate.valueOf()));
                    }
                } else {
                    var increment = this._txtProvider.inputWidget._getInnerIncrement();
                    this._txtProvider.setYear(this._txtProvider.getYear() - increment, null, true);
                    if (this._txtProvider.getDate() < minDate) {
                        this._txtProvider.setDate(new Date(minDate.valueOf()));
                    }
                }
            };
            return EraYearDescriptor;
        })(_iDateDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor70
        var _dateDescriptor70 = (function (_super) {
            __extends(_dateDescriptor70, _super);
            function _dateDescriptor70(owner, id) {
                _super.call(this, owner, id);
                this.name = 'Era Year';
                this.formatString = "e";
                this.type = 70 /* EraYear */;
            }
            _dateDescriptor70.prototype.getText = function () {
                var eraDate = DateTimeInfo.GetEraDate(this._txtProvider.getDate());
                if (eraDate.eraYear === -1) {
                    return "";
                }
                eraDate.eraYear = eraDate.eraYear > 99 ? 99 : eraDate.eraYear;
                return this.getRealText(String(eraDate.eraYear));
            };

            _dateDescriptor70.prototype.setText = function (value, allowchangeotherpart, result) {
                if (isNaN(parseInt(value))) {
                    return false;
                }

                var date = this._txtProvider.getDate();
                var eraDate = DateTimeInfo.GetEraDate(date);
                if (eraDate.eraYear !== -1) {
                    var eraYear = parseInt(value);
                    if (eraYear >= DateTimeInfo.GetEraYears()[eraDate.era]) {
                        eraYear = DateTimeInfo.GetEraYears()[eraDate.era];
                    }

                    var nullFlag = this._txtProvider.inputWidget.options.date == null;
                    if (nullFlag) {
                        eraYear = parseInt(value);
                    }

                    var newDate = DateTimeInfo.ConvertToGregorianDate(eraDate.era, eraYear, date.getMonth() + 1, date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), false);

                    if (eraDate.era < DateTimeInfo.GetEraCount() - 1) {
                        var maxEraDate = DateTimeInfo.GetEraDates()[eraDate.era + 1];
                        if (newDate > maxEraDate) {
                            eraYear = DateTimeInfo.GetEraYears()[eraDate.era] - 1;
                            newDate = DateTimeInfo.ConvertToGregorianDate(eraDate.era, eraYear, date.getMonth() + 1, date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), false);
                        }
                    }

                    this._txtProvider.setDate(newDate);
                    return true;
                }

                return false;
            };
            return _dateDescriptor70;
        })(EraYearDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor71
        var _dateDescriptor71 = (function (_super) {
            __extends(_dateDescriptor71, _super);
            function _dateDescriptor71(owner, id) {
                _super.call(this, owner, id);
                this.name = 'Two Era Year';
                this.formatString = "ee";
                this.type = 71 /* TwoEraYear */;
            }
            _dateDescriptor71.prototype.getText = function () {
                var eraDate = DateTimeInfo.GetEraDate(this._txtProvider.getDate());
                if (eraDate.eraYear === -1) {
                    return "";
                }

                eraDate.eraYear = eraDate.eraYear > 99 ? 99 : eraDate.eraYear;
                return this.getRealText(paddingZero(eraDate.eraYear, 2));
            };

            _dateDescriptor71.prototype.setText = function (value, allowchangeotherpart, result) {
                if (isNaN(parseInt(value))) {
                    return false;
                }

                var date = this._txtProvider.getDate();
                var eraDate = DateTimeInfo.GetEraDate(date);
                if (eraDate.eraYear !== -1) {
                    var newValue = String(eraDate.eraYear) + value;
                    var eraYear = parseInt(newValue.substring(newValue.length - 2, newValue.length));
                    if (eraYear > DateTimeInfo.GetEraYears()[eraDate.era]) {
                        eraYear = DateTimeInfo.GetEraYears()[eraDate.era];
                    }

                    var nullFlag = this._txtProvider.inputWidget.options.date == null;
                    if (nullFlag) {
                        eraYear = parseInt(value);
                    }

                    var newDate = DateTimeInfo.ConvertToGregorianDate(eraDate.era, eraYear, date.getMonth() + 1, date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), false);
                    if (eraDate.era < DateTimeInfo.GetEraCount() - 1) {
                        var maxEraDate = DateTimeInfo.GetEraDates()[eraDate.era + 1];
                        if (newDate > maxEraDate) {
                            eraYear = DateTimeInfo.GetEraYears()[eraDate.era] - 1;
                            newDate = DateTimeInfo.ConvertToGregorianDate(eraDate.era, eraYear, date.getMonth() + 1, date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), false);
                        }
                    }

                    this._txtProvider.setDate(newDate);
                    return true;
                }

                return false;
            };
            return _dateDescriptor71;
        })(EraYearDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor75
        var _dateDescriptor75 = (function (_super) {
            __extends(_dateDescriptor75, _super);
            function _dateDescriptor75(owner, id) {
                _super.call(this, owner, id);
                this.name = 'Era Year Big';
                this.formatString = "E";
                this.type = 75 /* EraYearBig */;
            }
            _dateDescriptor75.prototype.getText = function () {
                var result = _super.prototype.getText.call(this);
                return result == 1 ? "\u5143" : result;
            };
            return _dateDescriptor75;
        })(_dateDescriptor70);

        var EraNameDescriptor = (function (_super) {
            __extends(EraNameDescriptor, _super);
            function EraNameDescriptor(owner, id) {
                _super.call(this, owner, id);
            }
            EraNameDescriptor.prototype.inc = function () {
                var date = this._txtProvider.getDate();
                var eraDate = DateTimeInfo.GetEraDate(date);
                if (eraDate.era === -1) {
                    return;
                }

                var minDate = this._txtProvider.inputWidget._getRealEraMinDate();
                var maxDate = this._txtProvider.inputWidget._getRealEraMaxDate();

                if (DateTimeInfo.Equal(date, maxDate)) {
                    if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                        this._txtProvider.setDate(new Date(minDate.valueOf()));
                    }
                } else {
                    if (eraDate.era >= DateTimeInfo.GetEraCount() - 1) {
                        this._txtProvider.setDate(new Date(maxDate.valueOf()));
                    } else {
                        var era = eraDate.era + this._txtProvider.inputWidget._getInnerIncrement();
                        era = era > DateTimeInfo.GetEraCount() - 1 ? DateTimeInfo.GetEraCount() - 1 : era;

                        var eraYear = eraDate.eraYear > DateTimeInfo.GetEraYears()[era] ? DateTimeInfo.GetEraYears()[era] : eraDate.eraYear;
                        var newDate = DateTimeInfo.ConvertToGregorianDate(era, eraYear, date.getMonth() + 1, date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), true);
                        newDate = newDate == null ? DateTimeInfo.GetEraDates()[era] : newDate;

                        if (newDate > maxDate) {
                            this._txtProvider.setDate(new Date(maxDate.valueOf()));
                        } else {
                            this._txtProvider.setDate(newDate);
                        }
                    }
                }
            };

            EraNameDescriptor.prototype.dec = function () {
                var date = this._txtProvider.getDate();
                var eraDate = DateTimeInfo.GetEraDate(date);
                if (eraDate.era === -1) {
                    return;
                }

                var minDate = this._txtProvider.inputWidget._getRealEraMinDate();
                var maxDate = this._txtProvider.inputWidget._getRealEraMaxDate();

                if (DateTimeInfo.Equal(date, minDate)) {
                    if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                        this._txtProvider.setDate(new Date(maxDate.valueOf()));
                    }
                } else {
                    if (eraDate.era == 0) {
                        this._txtProvider.setDate(new Date(minDate.valueOf()));
                    } else {
                        var era = eraDate.era - this._txtProvider.inputWidget._getInnerIncrement();
                        era = era < 0 ? 0 : era;

                        var eraYear = eraDate.eraYear > DateTimeInfo.GetEraYears()[era] ? DateTimeInfo.GetEraYears()[era] : eraDate.eraYear;
                        var newDate = DateTimeInfo.ConvertToGregorianDate(era, eraYear, date.getMonth() + 1, date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), true);

                        if (newDate == null) {
                            newDate = new Date(DateTimeInfo.GetEraDates()[era + 1]);
                            ;
                            newDate.setDate(newDate.getDate() - 1);
                        }

                        if (newDate > maxDate) {
                            this._txtProvider.setDate(new Date(minDate.valueOf()));
                        } else {
                            this._txtProvider.setDate(newDate);
                        }
                    }
                }
            };
            return EraNameDescriptor;
        })(_iDateDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor72
        var _dateDescriptor72 = (function (_super) {
            __extends(_dateDescriptor72, _super);
            function _dateDescriptor72(owner, id) {
                _super.call(this, owner, id);
                this.name = 'Era Name';
                this.formatString = "g";
                this.type = 72 /* EraName */;
            }
            _dateDescriptor72.prototype.getText = function () {
                if (DateTimeInfo.GetEraCount() === 1) {
                    return DateTimeInfo.GetEraSymbols()[0];
                }

                var eraDate = DateTimeInfo.GetEraDate(this._txtProvider.getDate());
                if (eraDate.era === -1) {
                    return "";
                }

                return this.getRealText(DateTimeInfo.GetEraSymbols()[eraDate.era]);
            };

            _dateDescriptor72.prototype.setText = function (value, allowchangeotherpart, result) {
                var singleValue = value.substr(value.length - 1, 1);
                var era = 0;
                for (era = 0; era < DateTimeInfo.GetEraCount(); era++) {
                    if ((singleValue.toLowerCase() === DateTimeInfo.GetEraShortcuts()[era].toLowerCase()) || (value.toLowerCase() === DateTimeInfo.GetEraShortNames()[era].toLowerCase())) {
                        break;
                    }
                }

                if (era == DateTimeInfo.GetEraCount()) {
                    return true;
                }

                var date = this._txtProvider.getDate();
                var eraDate = DateTimeInfo.GetEraDate(date);
                if (eraDate.era === -1) {
                    return true;
                }

                var eraYear = eraDate.eraYear > DateTimeInfo.GetEraYears()[era] ? DateTimeInfo.GetEraYears()[era] : eraDate.eraYear;
                var newDate = DateTimeInfo.ConvertToGregorianDate(era, eraYear, date.getMonth() + 1, date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), true);
                newDate = newDate == null ? DateTimeInfo.GetEraDates()[era] : newDate;

                if (era < DateTimeInfo.GetEraCount() - 1) {
                    var maxEraDate = DateTimeInfo.GetEraDates()[era + 1];
                    newDate = newDate > maxEraDate ? maxEraDate : newDate;
                }

                this._txtProvider.setDate(newDate);
                return true;
            };
            return _dateDescriptor72;
        })(EraNameDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor73
        var _dateDescriptor73 = (function (_super) {
            __extends(_dateDescriptor73, _super);
            function _dateDescriptor73(owner, id) {
                _super.call(this, owner, id);
                this.name = 'Two Era Name';
                this.formatString = "gg";
                this.type = 73 /* TwoEraName */;
            }
            _dateDescriptor73.prototype.getText = function () {
                if (DateTimeInfo.GetEraCount() === 1) {
                    return DateTimeInfo.GetEraAbbreviations()[0];
                }

                var eraDate = DateTimeInfo.GetEraDate(this._txtProvider.getDate());
                if (eraDate.era === -1) {
                    return "";
                }
                return this.getRealText(DateTimeInfo.GetEraAbbreviations()[eraDate.era]);
            };

            _dateDescriptor73.prototype.setText = function (value, allowchangeotherpart, result) {
                var singleValue = value.substr(value.length - 1, 1);
                var era = 0;
                for (era = 0; era < DateTimeInfo.GetEraCount(); era++) {
                    if ((singleValue.toLowerCase() === DateTimeInfo.GetEraShortcuts()[era].toLowerCase()) || (value.toLowerCase() === DateTimeInfo.GetEraShortNames()[era].toLowerCase()) || (value.toLowerCase() === DateTimeInfo.GetEraAbbreviations()[era].toLowerCase())) {
                        break;
                    }
                }

                if (era == DateTimeInfo.GetEraCount()) {
                    return true;
                }

                var date = this._txtProvider.getDate();
                var eraDate = DateTimeInfo.GetEraDate(date);
                if (eraDate.era === -1) {
                    return true;
                }

                var eraYear = eraDate.eraYear > DateTimeInfo.GetEraYears()[era] ? DateTimeInfo.GetEraYears()[era] : eraDate.eraYear;
                var newDate = DateTimeInfo.ConvertToGregorianDate(era, eraYear, date.getMonth() + 1, date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), true);
                newDate = newDate == null ? DateTimeInfo.GetEraDates()[era] : newDate;

                if (era < DateTimeInfo.GetEraCount() - 1) {
                    var maxEraDate = DateTimeInfo.GetEraDates()[era + 1];
                    newDate = newDate > maxEraDate ? maxEraDate : newDate;
                }

                this._txtProvider.setDate(newDate);
                return true;
            };
            return _dateDescriptor73;
        })(EraNameDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor74
        var _dateDescriptor74 = (function (_super) {
            __extends(_dateDescriptor74, _super);
            function _dateDescriptor74(owner, id) {
                _super.call(this, owner, id);
                this.name = 'Three Era Name';
                this.formatString = "ggg";
                this.type = 74 /* ThreeEraName */;
            }
            _dateDescriptor74.prototype.getText = function () {
                if (DateTimeInfo.GetEraCount() === 1) {
                    return DateTimeInfo.GetEraNames()[0];
                }

                var eraDate = DateTimeInfo.GetEraDate(this._txtProvider.getDate());
                if (eraDate.era === -1) {
                    return "";
                }
                return this.getRealText(DateTimeInfo.GetEraNames()[eraDate.era]);
            };

            _dateDescriptor74.prototype.setText = function (value, allowchangeotherpart, result) {
                var singleValue = value.substr(value.length - 1, 1);
                var era = 0;
                for (era = 0; era < DateTimeInfo.GetEraCount(); era++) {
                    if ((singleValue.toLowerCase() === DateTimeInfo.GetEraShortcuts()[era].toLowerCase()) || (value.toLowerCase() === DateTimeInfo.GetEraShortNames()[era].toLowerCase()) || (value.toLowerCase() === DateTimeInfo.GetEraAbbreviations()[era].toLowerCase()) || (value.toLowerCase() === DateTimeInfo.GetEraNames()[era].toLowerCase())) {
                        break;
                    }
                }

                if (era == DateTimeInfo.GetEraCount()) {
                    return false;
                }

                var date = this._txtProvider.getDate();
                var eraDate = DateTimeInfo.GetEraDate(date);
                if (eraDate.era === -1) {
                    return true;
                }

                var eraYear = eraDate.eraYear > DateTimeInfo.GetEraYears()[era] ? DateTimeInfo.GetEraYears()[era] : eraDate.eraYear;
                var newDate = DateTimeInfo.ConvertToGregorianDate(era, eraYear, date.getMonth() + 1, date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), true);
                newDate = newDate == null ? DateTimeInfo.GetEraDates()[era] : newDate;

                if (era < DateTimeInfo.GetEraCount() - 1) {
                    var maxEraDate = DateTimeInfo.GetEraDates()[era + 1];
                    newDate = newDate > maxEraDate ? maxEraDate : newDate;
                }

                this._txtProvider.setDate(newDate);
                return true;
            };
            return _dateDescriptor74;
        })(EraNameDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor80
        var _dateDescriptor80 = (function (_super) {
            __extends(_dateDescriptor80, _super);
            function _dateDescriptor80(owner, id) {
                _super.call(this, owner, id);
                this.name = 'AD';
                this.formatString = "A";
                this.type = 80 /* AD */;
            }
            _dateDescriptor80.prototype.getText = function () {
                return "A.D.";
            };
            return _dateDescriptor80;
        })(_iDateDescriptor);

        var MonthDateDescriptor = (function (_super) {
            __extends(MonthDateDescriptor, _super);
            function MonthDateDescriptor(owner, id) {
                _super.call(this, owner, id);
            }
            MonthDateDescriptor.prototype.inc = function () {
                _super.prototype.inc.call(this);

                var date = this._txtProvider.getDate();
                var year = date.getFullYear();
                var month = date.getMonth();
                var day = date.getDate();
                var hour = date.getHours();
                var minute = date.getMinutes();
                var second = date.getSeconds();

                var newMonth = month + this._txtProvider.inputWidget._getInnerIncrement();
                var dayCount = DateTimeInfo.DaysInMonth(year, newMonth + 1);
                if (day > dayCount) {
                    day = dayCount;
                }

                var newDate = new Date(year, newMonth, day, hour, minute, second);

                if (this._txtProvider._isEraFormatExist()) {
                    var minDate = this._txtProvider.inputWidget._getRealEraMinDate();
                    var maxDate = this._txtProvider.inputWidget._getRealEraMaxDate();

                    if (newDate >= maxDate) {
                        if (!DateTimeInfo.Equal(this._txtProvider.getDate(), maxDate)) {
                            this._txtProvider.setDate(maxDate);
                        } else if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                            this._txtProvider.setDate(minDate);
                        }
                    } else {
                        this._txtProvider.setDate(newDate);
                    }
                } else {
                    var minDate = this._txtProvider.inputWidget._getRealMinDate();
                    var maxDate = this._txtProvider.inputWidget._getRealMaxDate();

                    if (!this._txtProvider.inputWidget._isValidDate(newDate, true)) {
                        if (!DateTimeInfo.Equal(this._txtProvider.getDate(), maxDate)) {
                            this._txtProvider.setDate(maxDate);
                        } else if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                            this._txtProvider.setDate(minDate);
                        }
                    } else {
                        this._txtProvider.setDate(newDate);
                    }
                }
            };

            MonthDateDescriptor.prototype.dec = function () {
                _super.prototype.inc.call(this);
                var date = this._txtProvider.getDate();
                var year = date.getFullYear();
                var month = date.getMonth();
                var day = date.getDate();
                var hour = date.getHours();
                var minute = date.getMinutes();
                var second = date.getSeconds();

                var newMonth = month - this._txtProvider.inputWidget._getInnerIncrement();
                var dayCount = DateTimeInfo.DaysInMonth(year, newMonth + 1);
                if (day > dayCount) {
                    day = dayCount;
                }

                var newDate = new Date(year, newMonth, day, hour, minute, second);
                if (year == 1) {
                    newDate.setFullYear(1);
                    if (newMonth < 0) {
                        newDate.setMonth(newMonth);
                    }
                }

                if (this._txtProvider._isEraFormatExist()) {
                    var minDate = this._txtProvider.inputWidget._getRealEraMinDate();
                    var maxDate = this._txtProvider.inputWidget._getRealEraMaxDate();

                    if (newDate < minDate) {
                        if (!DateTimeInfo.Equal(this._txtProvider.getDate(), minDate)) {
                            this._txtProvider.setDate(minDate);
                        } else if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                            this._txtProvider.setDate(maxDate);
                        }
                    } else {
                        this._txtProvider.setDate(newDate);
                    }
                } else {
                    var minDate = this._txtProvider.inputWidget._getRealMinDate();
                    var maxDate = this._txtProvider.inputWidget._getRealMaxDate();
                    if (!this._txtProvider.inputWidget._isValidDate(newDate, true)) {
                        if (!DateTimeInfo.Equal(this._txtProvider.getDate(), minDate)) {
                            this._txtProvider.setDate(minDate);
                        } else if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                            this._txtProvider.setDate(maxDate);
                        }
                    } else {
                        this._txtProvider.setDate(newDate);
                    }
                }
            };

            MonthDateDescriptor.prototype.setText = function (value, allowchangeotherpart, result) {
                if (parseInt(value) > 12) {
                    value = value.substr(value.length - 1, 1);
                }
                var returnResult = this._txtProvider.setMonth(value, allowchangeotherpart, result);
                if (returnResult) {
                    if (this._txtProvider._isEraFormatExist()) {
                        var minDate = this._txtProvider.inputWidget._getRealEraMinDate();
                        var maxDate = this._txtProvider.inputWidget._getRealEraMaxDate();
                        var date = this._txtProvider.getDate();

                        if (date > maxDate) {
                            this._txtProvider.setDate(maxDate);
                        } else if (date < minDate) {
                            this._txtProvider.setDate(minDate);
                        }
                    }
                }

                return returnResult;
            };
            return MonthDateDescriptor;
        })(_iDateDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor20
        var _dateDescriptor20 = (function (_super) {
            __extends(_dateDescriptor20, _super);
            function _dateDescriptor20(owner, id) {
                _super.call(this, owner, id);
                this.name = 'Two-digit month';
                this.formatString = "MM";
                this.type = 20 /* TwoDigitMonth */;
            }
            _dateDescriptor20.prototype.getText = function () {
                var m = '' + this._txtProvider.getMonth() + '';
                return this.getRealText(m.length === 1 ? ('0' + m) : m);
            };

            _dateDescriptor20.prototype.setText = function (value, allowchangeotherpart, result) {
                if (value === "0") {
                    return true;
                }

                return _super.prototype.setText.call(this, value, allowchangeotherpart, result);
            };
            return _dateDescriptor20;
        })(MonthDateDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor25
        var _dateDescriptor25 = (function (_super) {
            __extends(_dateDescriptor25, _super);
            function _dateDescriptor25(owner, id) {
                _super.call(this, owner, id);
                this.name = 'month';
                this.formatString = "M";
                this.type = 25 /* Month */;
            }
            _dateDescriptor25.prototype.getText = function () {
                var m = '' + this._txtProvider.getMonth() + '';
                return this.getRealText(m);
            };
            return _dateDescriptor25;
        })(MonthDateDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor26
        var _dateDescriptor26 = (function (_super) {
            __extends(_dateDescriptor26, _super);
            function _dateDescriptor26(owner, id) {
                _super.call(this, owner, id);
                this.name = 'AbbreviatedMonthNames';
                this.formatString = "MMM";
                this.type = 26 /* AbbreviatedMonthNames */;
                this.maxLen = 26 /* AbbreviatedMonthNames */;
            }
            _dateDescriptor26.prototype.getText = function () {
                var m = this._txtProvider.getMonth(), culture = this._txtProvider._getCulture();
                return this.getRealText(culture.calendars.standard.months.namesAbbr[m - 1]);
            };

            _dateDescriptor26.prototype.setText = function (value, allowchangeotherpart, result) {
                var m = -1, cf = this._txtProvider.inputWidget._getCulture().calendars.standard;
                m = this._txtProvider.findAlikeArrayItemIndex(cf.months.namesAbbr, value);
                if (m === -1) {
                    return false;
                }
                return this._txtProvider.setMonth(m + 1, allowchangeotherpart, result);
            };
            return _dateDescriptor26;
        })(MonthDateDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor27
        var _dateDescriptor27 = (function (_super) {
            __extends(_dateDescriptor27, _super);
            function _dateDescriptor27(owner, id) {
                _super.call(this, owner, id);
                this.name = 'MonthNames';
                this.formatString = "MMMM";
                this.type = 27 /* MonthNames */;
                this.maxLen = 100;
            }
            _dateDescriptor27.prototype.getText = function () {
                var m = this._txtProvider.getMonth(), culture = this._txtProvider._getCulture();
                return this.getRealText(culture.calendars.standard.months.names[m - 1]);
            };

            _dateDescriptor27.prototype.setText = function (value, allowchangeotherpart, result) {
                var m = -1, culture;
                if (result && result.isfullreset) {
                    m = 1;
                } else {
                    culture = this._txtProvider._getCulture();
                    m = this._txtProvider.findAlikeArrayItemIndex(culture.calendars.standard.months.names, value);
                    if (m === -1) {
                        return false;
                    }
                }
                return this._txtProvider.setMonth(m + 1, allowchangeotherpart, result);
            };
            return _dateDescriptor27;
        })(MonthDateDescriptor);

        var DayOfMonthDescriptor = (function (_super) {
            __extends(DayOfMonthDescriptor, _super);
            function DayOfMonthDescriptor(owner, id) {
                _super.call(this, owner, id);
            }
            DayOfMonthDescriptor.prototype.inc = function () {
                var newDay = this._txtProvider.getDayOfMonth() + this._txtProvider.inputWidget._getInnerIncrement();
                var newDate = new Date(this._txtProvider.getDate().valueOf());
                newDate.setDate(newDay);
                if (this._txtProvider._isEraFormatExist()) {
                    var minDate = this._txtProvider.inputWidget._getRealEraMinDate();
                    var maxDate = this._txtProvider.inputWidget._getRealEraMaxDate();

                    if (newDate > maxDate) {
                        if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                            this._txtProvider.setDate(minDate);
                        }
                    } else {
                        this._txtProvider.setDate(newDate);
                    }
                } else {
                    var minDate = this._txtProvider.inputWidget._getRealMinDate();
                    var maxDate = this._txtProvider.inputWidget._getRealMaxDate();

                    if (!this._txtProvider.inputWidget._isValidDate(newDate, true)) {
                        if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                            this._txtProvider.setDate(minDate);
                        }
                    } else {
                        this._txtProvider.setDate(newDate);
                    }
                }
            };

            DayOfMonthDescriptor.prototype.dec = function () {
                var newDay = this._txtProvider.getDayOfMonth() - this._txtProvider.inputWidget._getInnerIncrement();
                var newDate = new Date(this._txtProvider.getDate().valueOf());
                newDate.setDate(newDay);
                if (this._txtProvider._isEraFormatExist()) {
                    var minDate = this._txtProvider.inputWidget._getRealEraMinDate();
                    var maxDate = this._txtProvider.inputWidget._getRealEraMaxDate();

                    if (newDate < minDate) {
                        if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                            this._txtProvider.setDate(maxDate);
                        }
                    } else {
                        this._txtProvider.setDate(newDate);
                    }
                } else {
                    var minDate = this._txtProvider.inputWidget._getRealMinDate();
                    var maxDate = this._txtProvider.inputWidget._getRealMaxDate();

                    if (!this._txtProvider.inputWidget._isValidDate(newDate, true)) {
                        if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                            this._txtProvider.setDate(maxDate);
                        }
                    } else {
                        this._txtProvider.setDate(newDate);
                    }
                }
            };

            DayOfMonthDescriptor.prototype.setText = function (value, allowchangeotherpart, result) {
                var date = this._txtProvider.getDate();
                var dayCount = DateTimeInfo.DaysInMonth(date.getFullYear(), date.getMonth() + 1);
                if (parseInt(value) > dayCount) {
                    value = dayCount + "";
                }
                var returnResult = this._txtProvider.setDayOfMonth(value, allowchangeotherpart, result);
                if (returnResult) {
                    if (this._txtProvider._isEraFormatExist()) {
                        var minDate = this._txtProvider.inputWidget._getRealEraMinDate();
                        var maxDate = this._txtProvider.inputWidget._getRealEraMaxDate();
                        var date = this._txtProvider.getDate();

                        if (date > maxDate) {
                            this._txtProvider.setDate(maxDate);
                        } else if (date < minDate) {
                            this._txtProvider.setDate(minDate);
                        }
                    }
                }

                return returnResult;
            };
            return DayOfMonthDescriptor;
        })(_iDateDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor30
        var _dateDescriptor30 = (function (_super) {
            __extends(_dateDescriptor30, _super);
            function _dateDescriptor30(owner, id) {
                _super.call(this, owner, id);
                this.name = 'Two-digit day of month';
                this.formatString = "dd";
                this.type = 30 /* TwoDigityDayOfMonth */;
            }
            _dateDescriptor30.prototype.getText = function () {
                return this.getRealText(paddingZero(this._txtProvider.getDayOfMonth()));
            };

            _dateDescriptor30.prototype.setText = function (value, allowchangeotherpart, result) {
                if (value === "0") {
                    return true;
                }

                return _super.prototype.setText.call(this, value, allowchangeotherpart, result);
            };
            return _dateDescriptor30;
        })(DayOfMonthDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor31
        var _dateDescriptor31 = (function (_super) {
            __extends(_dateDescriptor31, _super);
            function _dateDescriptor31(owner, id) {
                _super.call(this, owner, id);
                this.name = 'Day of month';
                this.formatString = "d";
                this.type = 31 /* DayOfMonth */;
            }
            _dateDescriptor31.prototype.getText = function () {
                var dom = this._txtProvider.getDayOfMonth();
                return this.getRealText('' + dom + '');
            };
            return _dateDescriptor31;
        })(DayOfMonthDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor100
        var _dateDescriptor100 = (function (_super) {
            __extends(_dateDescriptor100, _super);
            function _dateDescriptor100(owner, id) {
                _super.call(this, owner, id);
                this.name = 'AbbreviatedDayNames';
                this.formatString = "ddd";
                this.type = 100 /* AbbreviatedDayNames */;
                this.maxLen = 100;
            }
            _dateDescriptor100.prototype.getText = function () {
                var dw = this._txtProvider.getDayOfWeek(), culture = this._txtProvider._getCulture();
                return this.getRealText(culture.calendars.standard.days.namesAbbr[dw - 1]);
            };

            _dateDescriptor100.prototype.setText = function (value, allowchangeotherpart, result) {
                var dw = -1, culture = this._txtProvider._getCulture();
                dw = this._txtProvider.findAlikeArrayItemIndex(culture.calendars.standard.days.namesShort, value);
                if (dw === -1) {
                    return false;
                }
                return this._txtProvider.setDayOfWeek(dw + 1);
            };

            _dateDescriptor100.prototype.needAdjustInsertPos = function () {
                return false;
            };
            return _dateDescriptor100;
        })(DayOfMonthDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor101
        var _dateDescriptor101 = (function (_super) {
            __extends(_dateDescriptor101, _super);
            function _dateDescriptor101(owner, id) {
                _super.call(this, owner, id);
                this.name = 'DayNames';
                this.formatString = "dddd";
                this.type = 101 /* DayNames */;
                this.maxLen = 100;
            }
            _dateDescriptor101.prototype.getText = function () {
                var dw = this._txtProvider.getDayOfWeek(), culture = this._txtProvider._getCulture();
                return this.getRealText(culture.calendars.standard.days.names[dw - 1]);
            };

            _dateDescriptor101.prototype.setText = function (value, allowchangeotherpart, result) {
                var dw = -1, culture = this._txtProvider._getCulture();
                dw = this._txtProvider.findAlikeArrayItemIndex(culture.calendars.standard.days.names, value);
                if (dw === -1) {
                    return false;
                }
                return this._txtProvider.setDayOfWeek(dw + 1);
            };

            _dateDescriptor101.prototype.needAdjustInsertPos = function () {
                return false;
            };
            return _dateDescriptor101;
        })(DayOfMonthDescriptor);

        var YearDateDescriptor = (function (_super) {
            __extends(YearDateDescriptor, _super);
            function YearDateDescriptor(owner, id) {
                _super.call(this, owner, id);
            }
            YearDateDescriptor.prototype.inc = function () {
                var newYear = this._txtProvider.getYear() + this._txtProvider.inputWidget._getInnerIncrement();
                var newDate = new Date(this._txtProvider.getDate().valueOf());
                newDate.setFullYear(newYear);

                if (this._txtProvider._isEraFormatExist()) {
                    var minDate = this._txtProvider.inputWidget._getRealEraMinDate();
                    var maxDate = this._txtProvider.inputWidget._getRealEraMaxDate();

                    if (newDate > maxDate) {
                        if (!DateTimeInfo.Equal(this._txtProvider.getDate(), maxDate)) {
                            this._txtProvider.setDate(maxDate);
                        } else if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                            this._txtProvider.setDate(minDate);
                        }
                    } else {
                        this._txtProvider.setDate(newDate);
                    }
                } else {
                    var minDate = this._txtProvider.inputWidget._getRealMinDate();
                    var maxDate = this._txtProvider.inputWidget._getRealMaxDate();

                    if (!this._txtProvider.inputWidget._isValidDate(newDate, true)) {
                        if (!DateTimeInfo.Equal(this._txtProvider.getDate(), maxDate)) {
                            this._txtProvider.setDate(maxDate);
                        } else if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                            this._txtProvider.setDate(minDate);
                        }
                    } else {
                        this._txtProvider.setDate(newDate);
                    }
                }
            };

            YearDateDescriptor.prototype.dec = function () {
                var newYear = this._txtProvider.getYear() - +this._txtProvider.inputWidget._getInnerIncrement();
                var newDate = new Date(this._txtProvider.getDate().valueOf());
                newDate.setFullYear(newYear);

                if (this._txtProvider._isEraFormatExist()) {
                    var minDate = this._txtProvider.inputWidget._getRealEraMinDate();
                    var maxDate = this._txtProvider.inputWidget._getRealEraMaxDate();

                    if (newDate < minDate) {
                        if (!DateTimeInfo.Equal(this._txtProvider.getDate(), minDate)) {
                            this._txtProvider.setDate(minDate);
                        } else if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                            this._txtProvider.setDate(maxDate);
                        }
                    } else {
                        this._txtProvider.setDate(newDate);
                    }
                } else {
                    var minDate = this._txtProvider.inputWidget._getRealMinDate();
                    var maxDate = this._txtProvider.inputWidget._getRealMaxDate();

                    if (!this._txtProvider.inputWidget._isValidDate(newDate, true)) {
                        if (!DateTimeInfo.Equal(this._txtProvider.getDate(), minDate)) {
                            this._txtProvider.setDate(minDate);
                        } else if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                            this._txtProvider.setDate(maxDate);
                        }
                    } else {
                        this._txtProvider.setDate(newDate);
                    }
                }
            };
            return YearDateDescriptor;
        })(_iDateDescriptor);

        var TwoDigitYearDescriptor = (function (_super) {
            __extends(TwoDigitYearDescriptor, _super);
            function TwoDigitYearDescriptor(owner, id) {
                _super.call(this, owner, id);
            }
            TwoDigitYearDescriptor.prototype.setText = function (value, allowchangeotherpart, result) {
                value = paddingZero(value);
                var y = paddingZero(this._txtProvider.getYear(), 4), m, dom, h, min, s;
                if (value === '00') {
                    m = this._txtProvider.getMonth();
                    dom = this._txtProvider.getDayOfMonth();
                    h = this._txtProvider.getHours();
                    min = this._txtProvider.getMinutes();
                    s = this._txtProvider.getSeconds();
                    if (m === 1 && dom === 1 && !h && !min && !s) {
                        y = '0001';
                        value = '01';
                    }
                }
                if (y.length >= 2) {
                    y = y.substr(0, 2) + value.substr(0, 2);
                }

                return this._txtProvider.setYear(parseInt(y), result, false);
            };
            return TwoDigitYearDescriptor;
        })(YearDateDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor10
        var _dateDescriptor10 = (function (_super) {
            __extends(_dateDescriptor10, _super);
            function _dateDescriptor10(owner, id) {
                _super.call(this, owner, id);
                this.name = 'Four-digit year';
                this.formatString = "yyyy";
                this.type = 10 /* FourDigitYear */;
                this.maxLen = 4;
            }
            _dateDescriptor10.prototype.getText = function () {
                return this.getRealText(paddingZero(this._txtProvider.getYear(), 4));
            };

            _dateDescriptor10.prototype.setText = function (value, allowchangeotherpart, result, isSmartInputMode) {
                if (isSmartInputMode && result) {
                    value = value * 1;
                    value = value % 100;

                    var startYear = 1900 + 100;
                    if (this._txtProvider.inputWidget.options.startYear) {
                        startYear = this._txtProvider.inputWidget.options.startYear;
                    }

                    var lastYear = startYear % 100;
                    var firstYear = startYear - lastYear;

                    if (value >= lastYear) {
                        value = firstYear + value;
                    } else {
                        value = firstYear + value + 100;
                    }
                    //    startYearStr: string,
                    //    endYear, curDate, thisYear, inputNum, century, addYear, s;
                    //endYear = startYear + 100 - 1;
                    //startYearStr = this._txtProvider.paddingZero(startYear, 4);
                    //endYear = this._txtProvider.paddingZero(endYear, 4);
                    //if (result.pos === 0 || result.pos === 1) {
                    //    curDate = new Date();
                    //    thisYear = this._txtProvider
                    //        .paddingZero(this._txtProvider.getYear(), 4);
                    //    if (thisYear.charAt(0) === '0' &&
                    //        thisYear.charAt(1) === '0' && result.pos <= 1) {
                    //        inputNum = result.val;
                    //        century = '00';
                    //        if (inputNum >= 5) {
                    //            century = startYearStr.slice(0, 2);
                    //        }
                    //        else {
                    //            century = endYear.slice(0, 2);
                    //        }
                    //        addYear = result.val + thisYear.slice(3, 4);
                    //        s = century + addYear;
                    //        result.offset = 2 - result.pos;
                    //        this._txtProvider.setYear(s, result);
                    //        return true;
                    //    }
                    //}
                }

                return this._txtProvider.setYear(value, result, false);
            };
            return _dateDescriptor10;
        })(YearDateDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor1
        var _dateDescriptor1 = (function (_super) {
            __extends(_dateDescriptor1, _super);
            function _dateDescriptor1(owner, id) {
                _super.call(this, owner, id);
                this.name = 'One-digit year';
                this.formatString = "y";
                this.type = 1 /* OneDigitYear */;
            }
            _dateDescriptor1.prototype.getText = function () {
                var y = paddingZero(this._txtProvider.getYear());
                if (y[0] === '0') {
                    y = y[1];
                }
                return this.getRealText(y);
            };
            return _dateDescriptor1;
        })(TwoDigitYearDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor2
        var _dateDescriptor2 = (function (_super) {
            __extends(_dateDescriptor2, _super);
            function _dateDescriptor2(owner, id) {
                _super.call(this, owner, id);
                this.name = 'Two-digit year';
                this.formatString = "yy";
                this.type = 2 /* TwoDigitYear */;
            }
            _dateDescriptor2.prototype.getText = function () {
                if (this._txtProvider.inputWidget.isFocused() && this._txtProvider.inputWidget.options.date == null) {
                    return "yy";
                }
                return this.getRealText(paddingZero(this._txtProvider.getYear(), 2));
            };
            return _dateDescriptor2;
        })(TwoDigitYearDescriptor);

        var HourDescriptor = (function (_super) {
            __extends(HourDescriptor, _super);
            function HourDescriptor(owner, id) {
                _super.call(this, owner, id);
            }
            HourDescriptor.prototype.inc = function () {
                var newHour = this._txtProvider.getHours() + this._txtProvider.inputWidget._getInnerIncrement();
                var newDate = new Date(this._txtProvider.getDate().valueOf());
                newDate.setHours(newHour);

                if (this._txtProvider._isEraFormatExist()) {
                    var minDate = this._txtProvider.inputWidget._getRealEraMinDate();
                    var maxDate = this._txtProvider.inputWidget._getRealEraMaxDate();

                    if (newDate > maxDate) {
                        if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                            this._txtProvider.setDate(minDate);
                        }
                    } else {
                        this._txtProvider.setDate(newDate);
                    }
                } else {
                    var minDate = this._txtProvider.inputWidget._getRealMinDate();
                    var maxDate = this._txtProvider.inputWidget._getRealMaxDate();

                    if (!this._txtProvider.inputWidget._isValidDate(newDate, true)) {
                        if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                            this._txtProvider.setDate(minDate);
                        }
                    } else {
                        this._txtProvider.setDate(newDate);
                    }
                }
            };

            HourDescriptor.prototype.dec = function () {
                var newHour = this._txtProvider.getHours() - this._txtProvider.inputWidget._getInnerIncrement();
                var newDate = new Date(this._txtProvider.getDate().valueOf());
                newDate.setHours(newHour);
                if (this._txtProvider._isEraFormatExist()) {
                    var minDate = this._txtProvider.inputWidget._getRealEraMinDate();
                    var maxDate = this._txtProvider.inputWidget._getRealEraMaxDate();

                    if (newDate < minDate) {
                        if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                            this._txtProvider.setDate(maxDate);
                        }
                    } else {
                        this._txtProvider.setDate(newDate);
                    }
                } else {
                    var minDate = this._txtProvider.inputWidget._getRealMinDate();
                    var maxDate = this._txtProvider.inputWidget._getRealMaxDate();

                    if (!this._txtProvider.inputWidget._isValidDate(newDate, true)) {
                        if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                            this._txtProvider.setDate(maxDate);
                        }
                    } else {
                        this._txtProvider.setDate(newDate);
                    }
                }
            };
            return HourDescriptor;
        })(_iDateDescriptor);

        var TwelveHourDescriptor = (function (_super) {
            __extends(TwelveHourDescriptor, _super);
            function TwelveHourDescriptor(owner, id) {
                _super.call(this, owner, id);
            }
            TwelveHourDescriptor.prototype.setText = function (value, allowchangeotherpart, result) {
                var h = this._txtProvider.getHours();
                if (h >= 12 && value < 12) {
                    value = ((value * 1) + 12);
                } else if (h < 12 && value == 12) {
                    value = 0;
                }
                return this._txtProvider.setHours(value, allowchangeotherpart);
            };
            return TwelveHourDescriptor;
        })(HourDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor45
        var _dateDescriptor45 = (function (_super) {
            __extends(_dateDescriptor45, _super);
            function _dateDescriptor45(owner, id) {
                _super.call(this, owner, id);
                this.name = 'h';
                this.formatString = "h";
                this.type = 45 /* h */;
            }
            _dateDescriptor45.prototype.getText = function () {
                if (this._txtProvider.inputWidget.isFocused() && this._txtProvider.inputWidget.options.date == null) {
                    return "h";
                }

                var h = this._txtProvider.getHours();
                if (h > 12) {
                    h = h - 12;
                } else if (h === 0) {
                    h = 12;
                }

                if (h == 12 && this._txtProvider.inputWidget.options.hour12As0) {
                    h = 0;
                }

                return this.getRealText('' + h + '');
            };
            return _dateDescriptor45;
        })(TwelveHourDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor46
        var _dateDescriptor46 = (function (_super) {
            __extends(_dateDescriptor46, _super);
            function _dateDescriptor46(owner, id) {
                _super.call(this, owner, id);
                this.name = 'hh';
                this.formatString = "hh";
                this.type = 46 /* hh */;
            }
            _dateDescriptor46.prototype.getText = function () {
                var h = this._txtProvider.getHours();
                if (h > 12) {
                    h -= 12;
                } else if (h === 0) {
                    h = 12;
                }

                if (h == 12 && this._txtProvider.inputWidget.options.hour12As0) {
                    h = 0;
                }

                return this.getRealText(paddingZero(h, 2));
            };
            return _dateDescriptor46;
        })(TwelveHourDescriptor);

        var TwentyFourHourDescriptor = (function (_super) {
            __extends(TwentyFourHourDescriptor, _super);
            function TwentyFourHourDescriptor(owner, id) {
                _super.call(this, owner, id);
            }
            TwentyFourHourDescriptor.prototype.setText = function (value, allowchangeotherpart, result) {
                return this._txtProvider.setHours(value, allowchangeotherpart);
            };
            return TwentyFourHourDescriptor;
        })(HourDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor47
        var _dateDescriptor47 = (function (_super) {
            __extends(_dateDescriptor47, _super);
            function _dateDescriptor47(owner, id) {
                _super.call(this, owner, id);
                this.name = 'H';
                this.formatString = "H";
                this.type = 47 /* H */;
            }
            _dateDescriptor47.prototype.getText = function () {
                var h = this._txtProvider.getHours();

                if (h == 0 && !this._txtProvider.inputWidget.options.midnightAs0) {
                    h = 24;
                }

                return this.getRealText('' + h + '');
            };
            return _dateDescriptor47;
        })(TwentyFourHourDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor48
        var _dateDescriptor48 = (function (_super) {
            __extends(_dateDescriptor48, _super);
            function _dateDescriptor48(owner, id) {
                _super.call(this, owner, id);
                this.name = 'HH';
                this.formatString = "HH";
                this.type = 48 /* HH */;
            }
            _dateDescriptor48.prototype.getText = function () {
                var h = this._txtProvider.getHours();
                if (h == 0 && !this._txtProvider.inputWidget.options.midnightAs0) {
                    h = 24;
                }
                return this.getRealText(paddingZero(h, 2));
            };
            return _dateDescriptor48;
        })(TwentyFourHourDescriptor);

        var AmPmDescriptor = (function (_super) {
            __extends(AmPmDescriptor, _super);
            function AmPmDescriptor(owner, id) {
                _super.call(this, owner, id);
            }
            AmPmDescriptor.prototype.inc = function () {
                var h = (this._txtProvider.getHours() + 12) % 24;
                this._txtProvider.setHours(h, true);
            };

            AmPmDescriptor.prototype.dec = function () {
                var h = (this._txtProvider.getHours() + 12) % 24;
                this._txtProvider.setHours(h, true);
            };

            AmPmDescriptor.prototype.setText = function (value, allowchangeotherpart, result) {
                var h;
                if (value.toLowerCase().indexOf('a') >= 0) {
                    h = this._txtProvider.getHours() % 12;
                    this._txtProvider.setHours(h, true);
                } else if (value.toLowerCase().indexOf('p') >= 0) {
                    h = this._txtProvider.getHours() % 12 + 12;
                    this._txtProvider.setHours(h, true);
                }

                return true;
            };
            return AmPmDescriptor;
        })(_iDateDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor250
        var _dateDescriptor250 = (function (_super) {
            __extends(_dateDescriptor250, _super);
            function _dateDescriptor250(owner, id) {
                _super.call(this, owner, id);
                this.name = 't';
                this.formatString = "t";
                this.type = 250 /* ShortAmPm */;
            }
            _dateDescriptor250.prototype.getText = function () {
                var hours = this._txtProvider.getHours();
                var culture = this._txtProvider._getCulture();
                var am = this._txtProvider.inputWidget._getInnerAmDesignator();
                var pm = this._txtProvider.inputWidget._getInnerPmDesignator();
                var designator = hours < 12 ? am : pm;
                return this.getRealText(designator.charAt(0) || " ");
            };
            return _dateDescriptor250;
        })(AmPmDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor251
        var _dateDescriptor251 = (function (_super) {
            __extends(_dateDescriptor251, _super);
            function _dateDescriptor251(owner, id) {
                _super.call(this, owner, id);
                this.name = 'tt';
                this.formatString = "tt";
                this.type = 251 /* AmPm */;
            }
            _dateDescriptor251.prototype.getText = function () {
                var hours = this._txtProvider.getHours();
                var culture = this._txtProvider._getCulture();
                var am = this._txtProvider.inputWidget._getInnerAmDesignator();
                var pm = this._txtProvider.inputWidget._getInnerPmDesignator();
                var designator = hours < 12 ? am : pm;

                if (designator.length <= 0) {
                    designator = ' ';
                }
                return this.getRealText(designator);
            };
            return _dateDescriptor251;
        })(AmPmDescriptor);

        var MinuteDescriptor = (function (_super) {
            __extends(MinuteDescriptor, _super);
            function MinuteDescriptor(owner, id) {
                _super.call(this, owner, id);
            }
            MinuteDescriptor.prototype.inc = function () {
                var newMinute = this._txtProvider.getMinutes() + this._txtProvider.inputWidget._getInnerIncrement();
                var newDate = new Date(this._txtProvider.getDate().valueOf());
                newDate.setMinutes(newMinute);
                if (this._txtProvider._isEraFormatExist()) {
                    var minDate = this._txtProvider.inputWidget._getRealEraMinDate();
                    var maxDate = this._txtProvider.inputWidget._getRealEraMaxDate();

                    if (newDate > maxDate) {
                        if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                            this._txtProvider.setDate(minDate);
                        }
                    } else {
                        this._txtProvider.setDate(newDate);
                    }
                } else {
                    var minDate = this._txtProvider.inputWidget._getRealMinDate();
                    var maxDate = this._txtProvider.inputWidget._getRealMaxDate();

                    if (!this._txtProvider.inputWidget._isValidDate(newDate, true)) {
                        if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                            this._txtProvider.setDate(minDate);
                        }
                    } else {
                        this._txtProvider.setDate(newDate);
                    }
                }
            };

            MinuteDescriptor.prototype.dec = function () {
                var newMinite = this._txtProvider.getMinutes() - this._txtProvider.inputWidget._getInnerIncrement();
                var newDate = new Date(this._txtProvider.getDate().valueOf());
                newDate.setMinutes(newMinite);

                if (this._txtProvider._isEraFormatExist()) {
                    var minDate = this._txtProvider.inputWidget._getRealEraMinDate();
                    var maxDate = this._txtProvider.inputWidget._getRealEraMaxDate();

                    if (newDate < minDate) {
                        if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                            this._txtProvider.setDate(maxDate);
                        }
                    } else {
                        this._txtProvider.setDate(newDate);
                    }
                } else {
                    var minDate = this._txtProvider.inputWidget._getRealMinDate();
                    var maxDate = this._txtProvider.inputWidget._getRealMaxDate();

                    if (!this._txtProvider.inputWidget._isValidDate(newDate, true)) {
                        if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                            this._txtProvider.setDate(maxDate);
                        }
                    } else {
                        this._txtProvider.setDate(newDate);
                    }
                }
            };

            MinuteDescriptor.prototype.setText = function (value, allowchangeotherpart, result) {
                if (result && result.isfullreset) {
                    value = '0';
                }

                return this._txtProvider.setMinutes(value, allowchangeotherpart);
            };
            return MinuteDescriptor;
        })(_iDateDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor50
        var _dateDescriptor50 = (function (_super) {
            __extends(_dateDescriptor50, _super);
            function _dateDescriptor50(owner, id) {
                _super.call(this, owner, id);
                this.name = 'mm';
                this.formatString = "mm";
                this.type = 50 /* mm */;
            }
            _dateDescriptor50.prototype.getText = function () {
                return this.getRealText(paddingZero(this._txtProvider.getMinutes()));
            };
            return _dateDescriptor50;
        })(MinuteDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor51
        var _dateDescriptor51 = (function (_super) {
            __extends(_dateDescriptor51, _super);
            function _dateDescriptor51(owner, id) {
                _super.call(this, owner, id);
                this.name = 'm';
                this.formatString = "m";
                this.type = 51 /* m */;
                this.delta = 12;
            }
            _dateDescriptor51.prototype.getText = function () {
                return this.getRealText(this._txtProvider.getMinutes().toString());
            };
            return _dateDescriptor51;
        })(MinuteDescriptor);

        var SecondDescriptor = (function (_super) {
            __extends(SecondDescriptor, _super);
            function SecondDescriptor(owner, id) {
                _super.call(this, owner, id);
            }
            SecondDescriptor.prototype.inc = function () {
                var newSecond = this._txtProvider.getSeconds() + this._txtProvider.inputWidget._getInnerIncrement();
                var newDate = new Date(this._txtProvider.getDate().valueOf());
                newDate.setSeconds(newSecond);

                if (this._txtProvider._isEraFormatExist()) {
                    var minDate = this._txtProvider.inputWidget._getRealEraMinDate();
                    var maxDate = this._txtProvider.inputWidget._getRealEraMaxDate();

                    if (newDate > maxDate) {
                        if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                            this._txtProvider.setDate(minDate);
                        }
                    } else {
                        this._txtProvider.setDate(newDate);
                    }
                } else {
                    var minDate = this._txtProvider.inputWidget._getRealMinDate();
                    var maxDate = this._txtProvider.inputWidget._getRealMaxDate();

                    if (!this._txtProvider.inputWidget._isValidDate(newDate, true)) {
                        if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                            this._txtProvider.setDate(minDate);
                        }
                    } else {
                        this._txtProvider.setDate(newDate);
                    }
                }
            };

            SecondDescriptor.prototype.dec = function () {
                var newSecond = this._txtProvider.getSeconds() - this._txtProvider.inputWidget._getInnerIncrement();
                var newDate = new Date(this._txtProvider.getDate().valueOf());
                newDate.setSeconds(newSecond);

                if (this._txtProvider._isEraFormatExist()) {
                    var minDate = this._txtProvider.inputWidget._getRealEraMinDate();
                    var maxDate = this._txtProvider.inputWidget._getRealEraMaxDate();

                    if (newDate < minDate) {
                        if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                            this._txtProvider.setDate(maxDate);
                        }
                    } else {
                        this._txtProvider.setDate(newDate);
                    }
                } else {
                    var minDate = this._txtProvider.inputWidget._getRealMinDate();
                    var maxDate = this._txtProvider.inputWidget._getRealMaxDate();

                    if (!this._txtProvider.inputWidget._isValidDate(newDate, true)) {
                        if (this._txtProvider.inputWidget._getAllowSpinLoop()) {
                            this._txtProvider.setDate(maxDate);
                        }
                    } else {
                        this._txtProvider.setDate(newDate);
                    }
                }
            };

            SecondDescriptor.prototype.setText = function (value, allowchangeotherpart, result) {
                if (result && result.isfullreset) {
                    value = '0';
                }
                return this._txtProvider.setSeconds(value, allowchangeotherpart);
            };
            return SecondDescriptor;
        })(_iDateDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor60
        var _dateDescriptor60 = (function (_super) {
            __extends(_dateDescriptor60, _super);
            function _dateDescriptor60(owner, id) {
                _super.call(this, owner, id);
                this.name = 'ss';
                this.formatString = "ss";
                this.type = 60 /* ss */;
            }
            _dateDescriptor60.prototype.getText = function () {
                return this.getRealText(paddingZero(this._txtProvider.getSeconds()));
            };
            return _dateDescriptor60;
        })(SecondDescriptor);

        ////////////////////////////////////////////////////////////////////////////////
        // _dateDescriptor61
        var _dateDescriptor61 = (function (_super) {
            __extends(_dateDescriptor61, _super);
            function _dateDescriptor61(owner, id) {
                _super.call(this, owner, id);
                this.name = 's';
                this.formatString = "s";
                this.type = 61 /* s */;
            }
            _dateDescriptor61.prototype.getText = function () {
                return this.getRealText(this._txtProvider.getSeconds().toString());
            };
            return _dateDescriptor61;
        })(SecondDescriptor);

        

        /** @ignore */
        var DateTimeInfo = (function () {
            function DateTimeInfo() {
            }
            DateTimeInfo.IsValidEraDate = function (date) {
                if (date < this.GetEraMin() || date > this.GetEraMax()) {
                    return false;
                }
                return true;
            };
            DateTimeInfo.ConvertToGregorianYear = function (era, eraYear, strict) {
                if (era < 0 || era >= this.GetEraCount() || eraYear < 1 || strict && eraYear > this.GetEraYears()[era]) {
                    return -1;
                }
                return this.GetEraDates()[era].getFullYear() + eraYear - 1;
            };
            DateTimeInfo.GetEraDates = function () {
                if (window.eras != undefined) {
                    var eraDates = new Array();
                    for (var i = 0; i < window.eras.length; i++) {
                        var date = new Date(window.eras[i].startDate.replace(/-/g, "/"));
                        eraDates[i] = date;
                    }
                    return eraDates;
                }
                return this.EraDates;
            };
            DateTimeInfo.GetEraNames = function () {
                var eraNames = new Array();
                if (window.eras != undefined) {
                    for (var i = 0; i < window.eras.length; i++) {
                        eraNames[i] = window.eras[i].name;
                    }
                    return eraNames;
                }

                for (var i = 0; i < this.EraCount; i++) {
                    eraNames[i] = this.EraNames[i + 2 * this.EraCount];
                }
                return eraNames;
            };

            DateTimeInfo.GetEraSymbols = function () {
                var eraSymbol = new Array();
                if (window.eras != undefined) {
                    for (var i = 0; i < window.eras.length; i++) {
                        eraSymbol[i] = window.eras[i].symbol;
                    }
                    return eraSymbol;
                }

                for (var i = 0; i < this.EraCount; i++) {
                    eraSymbol[i] = this.EraNames[i];
                    ;
                }
                return eraSymbol;
            };

            DateTimeInfo.GetEraAbbreviations = function () {
                var eraAbbreviation = new Array();
                if (window.eras != undefined) {
                    for (var i = 0; i < window.eras.length; i++) {
                        eraAbbreviation[i] = window.eras[i].abbreviation;
                    }
                    return eraAbbreviation;
                }

                for (var i = 0; i < this.EraCount; i++) {
                    eraAbbreviation[i] = this.EraNames[i + this.EraCount];
                }
                return eraAbbreviation;
            };

            DateTimeInfo.GetEraShortNames = function () {
                var eraShortName = new Array();
                if (window.eras != undefined) {
                    for (var i = 0; i < window.eras.length; i++) {
                        eraShortName[i] = window.eras[i].shortcuts.split(',')[1];
                    }
                    return eraShortName;
                }

                for (var i = 0; i < this.EraCount; i++) {
                    eraShortName[i] = this.EraNames[i];
                }
                return eraShortName;
            };

            DateTimeInfo.GetEraShortcuts = function () {
                var eraShortcuts = new Array();
                if (window.eras != undefined) {
                    for (var i = 0; i < window.eras.length; i++) {
                        eraShortcuts[i] = window.eras[i].shortcuts.split(',')[0];
                    }
                    return eraShortcuts;
                }

                for (var i = 0; i < this.EraCount; i++) {
                    eraShortcuts[i] = this.EraKeys[i];
                }
                return eraShortcuts;
            };

            DateTimeInfo.GetEraMax = function () {
                if (window.eras != undefined) {
                    if (window.eras.length > 0) {
                        var date = new Date(window.eras[window.eras.length - 1].startDate.replace(/-/g, "/"));
                        date.setFullYear(date.getFullYear() + 99);
                        return date;
                    }
                }
                return this.EraMax;
            };

            DateTimeInfo.GetEraMin = function () {
                if (window.eras != undefined) {
                    if (window.eras.length > 0) {
                        var date = new Date(window.eras[0].startDate.replace(/-/g, "/"));
                        return date;
                    }
                }
                return this.EraMin;
            };

            DateTimeInfo.GetEraCount = function () {
                if (window.eras != undefined) {
                    return window.eras.length;
                }
                return this.EraCount;
            };

            DateTimeInfo.GetEraYears = function () {
                if (window.eras != undefined) {
                    var eraYears = new Array();
                    for (var i = 1; i < window.eras.length; i++) {
                        var date1 = new Date(window.eras[i - 1].startDate.replace(/-/g, "/"));
                        var date2 = new Date(window.eras[i].startDate.replace(/-/g, "/"));
                        eraYears[i - 1] = date2.getFullYear() - date1.getFullYear() + 1;
                    }
                    eraYears[i - 1] = 99;
                    return eraYears;
                }
                return this.EraYears;
            };

            DateTimeInfo.ConvertToGregorianDate = function (era, eraYear, month, day, hour, minute, second, strict) {
                var year = this.ConvertToGregorianYear(era, eraYear, strict);

                if (year < 1 || year > 9999) {
                    return null;
                }

                if (month < 1 || month > 12) {
                    return null;
                }

                var maxdays = this.DaysInMonth(year, month);

                if (day < 1 || day > maxdays) {
                    return null;
                }
                if (hour < 0 || hour > 23) {
                    return null;
                }
                if (minute < 0 || minute > 59) {
                    return null;
                }
                if (second < 0 || second > 59) {
                    return null;
                }
                var dateTime = new Date(year, month - 1, day, hour, minute, second);

                if (strict) {
                    var startDate = this.GetEraDates()[era];
                    var endDate = era + 1 != this.GetEraCount() ? this.AddMilliseconds(this.GetEraDates()[era + 1], -1) : this.GetEraMax();

                    if (dateTime < startDate || dateTime > endDate) {
                        return null;
                    }
                }

                return dateTime;
            };

            DateTimeInfo.String2Date = function (value) {
                if (value == null || value.Length == 0) {
                    return null;
                }

                var date = new Date(Date.parse(value));
                return date;
            };

            DateTimeInfo.ToString = function (value, length, ch, position) {
                var val = value + "";

                //It is same as String.PadLeft(int, char) in C#.
                if (ch != null) {
                    while (val.length < length) {
                        if (position) {
                            val = val + ch;
                        } else {
                            val = ch + val;
                        }
                    }

                    return val;
                }

                while (val.length < length) {
                    val += value + "";
                }

                return val;
            };

            DateTimeInfo.Date2String = function (date, isJapan, IsjqDate, IsjqTime) {
                var strDate = "";

                try  {
                    if (isJapan == true) {
                        if (IsjqDate == true) {
                            strDate = date.getFullYear() + "/" + (date.getMonth() + 1) + "/" + date.getDate();
                        } else if (IsjqTime == true) {
                            strDate = date.getHours() + ":" + DateTimeInfo.ToString(date.getMinutes(), 2, "0") + ":" + DateTimeInfo.ToString(date.getSeconds(), 2, "0");
                        } else {
                            strDate = date.getFullYear() + "/" + (date.getMonth() + 1) + "/" + date.getDate() + " " + date.getHours() + ":" + DateTimeInfo.ToString(date.getMinutes(), 2, "0") + ":" + DateTimeInfo.ToString(date.getSeconds(), 2, "0");
                        }
                    } else {
                        if (IsjqDate == true) {
                            strDate = (date.getMonth() + 1) + "/" + date.getDate() + "/" + date.getFullYear();
                        } else if (IsjqTime == true) {
                            strDate = date.getHours() + ":" + DateTimeInfo.ToString(date.getMinutes(), 2, "0") + ":" + DateTimeInfo.ToString(date.getSeconds(), 2, "0");
                        } else {
                            strDate = (date.getMonth() + 1) + "/" + date.getDate() + "/" + date.getFullYear() + " " + date.getHours() + ":" + DateTimeInfo.ToString(date.getMinutes(), 2, "0") + ":" + DateTimeInfo.ToString(date.getSeconds(), 2, "0");
                        }
                    }
                } catch (ex) {
                    strDate = "";
                }

                return strDate;
            };

            DateTimeInfo.Date2Long = function (date) {
                try  {
                    return (date.getFullYear() * 100 + date.getMonth() + 1) * 100 + date.getDate();
                } catch (ex) {
                    return 0;
                }
            };

            DateTimeInfo.Date2Number = function (date) {
                if (date == null) {
                    return 0;
                }

                return ((((date.getFullYear() * 100 + date.getMonth() + 1) * 100 + date.getDate()) * 100 + date.getHours()) * 100 + date.getMinutes()) * 100 + date.getSeconds();
            };

            DateTimeInfo.Long2Date = function (value) {
                return new Date(Math.floor(value / 10000), Math.floor((value % 10000) / 100) - 1, value % 100);
            };

            DateTimeInfo.GetEraDate = function (date) {
                var eraDate = new Object();
                eraDate.era = -1;
                eraDate.eraYear = -1;

                if (!this.IsValidEraDate(date)) {
                    return eraDate;
                }

                for (var i = 0; i < this.GetEraCount(); i++) {
                    var nextDate = i + 1 != this.GetEraCount() ? this.GetEraDates()[i + 1] : this.AddMilliseconds(this.GetEraMax(), 1);

                    if (date < nextDate) {
                        eraDate.era = i;
                        eraDate.eraYear = date.getFullYear() - this.GetEraDates()[i].getFullYear() + 1;

                        break;
                    }
                }

                return eraDate;
            };

            DateTimeInfo.MakeDate = function (era, erayear, month, day) {
                var date = new Date();

                date = this.ConvertToGregorianDate(era, erayear, month, day, 0, 0, 0, true);

                if (date == null) {
                    return -1;
                }

                return date;
            };

            DateTimeInfo.GetValidMonthRange = function (era, eraYear) {
                var monthRange = {};
                monthRange.min = 1;
                monthRange.max = 12;

                if (era == -1 || eraYear == -1) {
                    return monthRange;
                }

                if (eraYear == 1) {
                    monthRange.min = this.GetEraDates()[era].getMonth() + 1;
                } else if (eraYear == this.EraYears[era] && era < this.EraCount - 1) {
                    monthRange.max = this.AddMilliseconds(this.GetEraDates()[era + 1], -1).getMonth() + 1;
                }

                return monthRange;
            };

            DateTimeInfo.GetValidDayRange = function (era, eraYear, month) {
                var dayRange = new Object();
                dayRange.min = 1;
                dayRange.max = this.DaysInMonth(this.ConvertToGregorianYear(era, eraYear, true), month);
                var eraMin = this.GetEraDates()[era];
                var eraMax = era < this.GetEraCount() - 1 ? this.AddMilliseconds(this.GetEraDates()[era + 1], -1) : this.GetEraMax();

                if (era == -1 || eraYear == -1) {
                    return dayRange;
                }

                if (eraYear == 1 && month == eraMin.getMonth() + 1) {
                    dayRange.min = eraMin.getDate();
                } else if (eraYear == this.EraYears[era] && month == eraMax.getMonth() + 1) {
                    dayRange.max = eraMax.getDate();
                }

                return dayRange;
            };

            DateTimeInfo.IsLeapYear = function (year) {
                if ((year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0))) {
                    return true;
                } else {
                    return false;
                }
            };

            DateTimeInfo.DayOfYear = function (year, month, day) {
                var sum = 0;
                for (var i = 1; i < month; i++) {
                    sum = sum + this.DaysInMonth(year, i);
                }

                sum = sum + day;
                return sum;
            };

            DateTimeInfo.DaysInMonth = function (year, month) {
                if (month > 12) {
                    year += Math.floor(month / 12);
                    month = month % 12;
                } else if (month < 0) {
                    var zMonth = month * (-1);
                    year -= Math.ceil(zMonth / 12);
                    month = 12 - zMonth % 12;
                }
                switch (month) {
                    case 2:
                        if (this.IsLeapYear(year)) {
                            return 29;
                        } else {
                            return 28;
                        }
                        break;
                    case 4:
                    case 6:
                    case 9:
                    case 11:
                        return 30;
                        break;
                    default:
                        return 31;
                        break;
                }
            };

            DateTimeInfo.Equal = function (date1, date2, strict) {
                if (date1 == null && date2 == null) {
                    return true;
                } else if (date1 == null) {
                    return false;
                } else if (date2 == null) {
                    return false;
                }

                try  {
                    if (!strict) {
                        if (date1.getFullYear() == date2.getFullYear() && date1.getMonth() == date2.getMonth() && date1.getDate() == date2.getDate()) {
                            return true;
                        } else {
                            return false;
                        }
                    }

                    if (date1.getFullYear() == date2.getFullYear() && date1.getMonth() == date2.getMonth() && date1.getDate() == date2.getDate() && date1.getHours() == date2.getHours() && date1.getMinutes() == date2.getMinutes() && date1.getSeconds() == date2.getSeconds()) {
                        return true;
                    } else {
                        return false;
                    }
                } catch (e) {
                    return false;
                }
            };

            DateTimeInfo.YearMonthEqual = function (date1, date2) {
                if (date1 == null && date2 == null) {
                    return true;
                } else if (date1 == null) {
                    return false;
                } else if (date2 == null) {
                    return false;
                }

                try  {
                    if (date1.getFullYear() == date2.getFullYear() && date1.getMonth() == date2.getMonth()) {
                        return true;
                    } else {
                        return false;
                    }
                } catch (e) {
                    return false;
                }
            };

            DateTimeInfo.SetDate = function (year, month, day) {
                var newDate = new Date();
                var maxMonth = 9999 * 12 + 12;

                if (year * 12 + month > maxMonth) {
                    newDate = new Date(9999, 11, 31);
                } else if (year * 12 + month < 100) {
                    newDate = new Date(100, 0, 1);
                } else {
                    var days = this.DaysInMonth(year, month);
                    if (day > days) {
                        day = days;
                    }
                    newDate = new Date(year, month - 1, day);
                }

                return newDate;
            };

            DateTimeInfo.SetFullDate = function (year, month, day) {
                var newDate = new Date();
                newDate.setDate(1);
                var maxMonth = 9999 * 12 + 12;

                var days = this.DaysInMonth(year, month);

                if ((month > 0) && (month < 12) && (day > days)) {
                    day = days;
                }

                newDate.setFullYear(year);
                newDate.setMonth(month - 1);
                newDate.setDate(day);
                return newDate;
            };

            DateTimeInfo.SetFullDateByDate = function (date) {
                var newDate = new Date();
                newDate.setDate(1);
                newDate.setFullYear(date.getFullYear());
                newDate.setMonth(date.getMonth());
                newDate.setDate(date.getDate());
                newDate.setHours(0, 0, 0, 0);
                return newDate;
            };

            DateTimeInfo.LYearDays = function (y) {
                var i, sum = 348;
                for (i = 0x8000; i > 0x8; i >>= 1)
                    sum += (this.LunarInfo[y - 1960] & i) ? 1 : 0;
                return (sum + this.leapDays(y));
            };

            DateTimeInfo.leapDays = function (y) {
                if (this.LeapMonth(y))
                    return ((this.LunarInfo[y - 1960] & 0x10000) ? 30 : 29);
                else
                    return (0);
            };

            DateTimeInfo.LeapDays = function (y) {
                if (this.LeapMonth(y))
                    return ((this.LunarInfo[y - 1960] & 0x10000) ? 30 : 29);
                else
                    return (0);
            };

            DateTimeInfo.LeapMonth = function (y) {
                return (this.LunarInfo[y - 1960] & 0xf);
            };

            DateTimeInfo.MonthDays = function (y, m) {
                return ((this.LunarInfo[y - 1960] & (0x10000 >> m)) ? 30 : 29);
            };

            DateTimeInfo.GetRokuyou = function (date) {
                if ((date - this.RokuyouMin) < 0 || (date - this.RokuyouMax) > 0) {
                    return;
                }
                var i, leap = 0, temp = 0;
                var baseDate = new Date(1960, 0, 28);
                var offset = Math.round((date - baseDate) / 86400000);

                for (i = 1960; i < 2050 && offset > 0; i++) {
                    temp = this.LYearDays(i);
                    offset -= temp;
                }
                if (offset < 0) {
                    offset += temp;
                    i--;
                }

                this.year = i;

                leap = this.LeapMonth(i);
                this.isLeap = false;

                for (i = 1; i < 13 && offset > 0; i++) {
                    if (leap > 0 && i == (leap + 1) && this.isLeap == false) {
                        --i;
                        this.isLeap = true;
                        temp = this.LeapDays(this.year);
                    } else {
                        temp = this.MonthDays(this.year, i);
                    }

                    if (this.isLeap == true && i == (leap + 1))
                        this.isLeap = false;

                    offset -= temp;
                }

                if (offset == 0 && leap > 0 && i == leap + 1)
                    if (this.isLeap) {
                        this.isLeap = false;
                    } else {
                        this.isLeap = true;
                        --i;
                    }

                if (offset < 0) {
                    offset += temp;
                    --i;
                }

                this.month = i;
                this.day = offset + 1;

                var index = (this.month + this.day - 2) % 6;

                var errorRange1Min = new Date(1996, 6, 15);
                var errorRange1Max = new Date(1996, 7, 13);
                if (this.IsDateInRange(date, errorRange1Min, errorRange1Max)) {
                    index = (6 + index - 1) % 6;
                }

                var errorRange2Min = new Date(1996, 8, 12);
                var errorRange2Max = new Date(1996, 9, 11);
                if (this.IsDateInRange(date, errorRange2Min, errorRange2Max)) {
                    index = (6 + index - 1) % 6;
                }

                var errorRange3Min = new Date(2033, 7, 25);
                var errorRange3Max = new Date(2033, 11, 21);
                if (this.IsDateInRange(date, errorRange3Min, errorRange3Max)) {
                    index = (index + 1) % 6;
                }

                if (this.Equal(date, errorRange1Min)) {
                    index = (6 + index - 1) % 6;
                }
                if (this.Equal(date, errorRange2Min)) {
                    index = (6 + index - 1) % 6;
                }

                var rokuyou;

                //switch (index) {
                //    case 0:
                //        rokuyou = GrapeCity.IM.Rokuyou.Senshou;
                //        break;
                //    case 1:
                //        rokuyou = GrapeCity.IM.Rokuyou.Tomobiki;
                //        break;
                //    case 2:
                //        rokuyou = GrapeCity.IM.Rokuyou.Senbu;
                //        break;
                //    case 3:
                //        rokuyou = GrapeCity.IM.Rokuyou.Butsumetsu;
                //        break;
                //    case 4:
                //        rokuyou = GrapeCity.IM.Rokuyou.Taian;
                //        break;
                //    case 5:
                //        rokuyou = GrapeCity.IM.Rokuyou.Shakkou;
                //        break;
                //    default:
                //        break;
                //}
                return rokuyou;
            };

            DateTimeInfo.IsDateInRange = function (dt, min, max) {
                var dtYear = dt.getYear();
                var minYear = min.getYear();
                var maxYear = max.getYear();
                var dtMonth = dt.getMonth();
                var minMonth = min.getMonth();
                var maxMonth = max.getMonth();
                var dtDay = dt.getDate();
                var minDay = min.getDate();
                var maxDay = max.getDate();
                var dtValue = dtYear * 10000 + dtMonth * 100 + dtDay;
                var minValue = minYear * 10000 + minMonth * 100 + minDay;
                var maxValue = maxYear * 10000 + maxMonth * 100 + maxDay;

                return dtValue >= minValue && dtValue <= maxValue;
            };

            DateTimeInfo.GetRokuyouText = function (rokuyou) {
                var rokuyouArray = new Array();

                //if (GrapeCity.IM.Localization.Region == "ja") {
                rokuyouArray = this.RokuyouTextArray.slice(0);

                switch (rokuyou) {
                    default:
                        return "";
                        break;
                }
            };

            DateTimeInfo.DaysInSpecialWeek = function (year, month, weekFlay) {
                var selections = new Array();
                var days = this.DaysInMonth(year, month + 1);
                var date = new Date(year, month, 1);
                var firstDateOfWeekTitle;

                for (var i = 1; i <= days; i++) {
                    date.setDate(i);
                    if (date.getDay() == weekFlay) {
                        var selectedDate = new Date(year, month, i);
                        selections.push(selectedDate);
                        firstDateOfWeekTitle = i;
                        break;
                    }
                }

                firstDateOfWeekTitle += 7;
                while (firstDateOfWeekTitle <= days) {
                    date.setDate(firstDateOfWeekTitle);
                    var followSelectedDate = new Date(year, month, firstDateOfWeekTitle);
                    selections.push(followSelectedDate);
                    firstDateOfWeekTitle += 7;
                }
                return selections;
            };

            DateTimeInfo.GetDaysByFirstWeekday = function (firstWeekday) {
                var days = new Array();
                days.push(firstWeekday);
                var date = new Date(firstWeekday);
                while (date.getDate() + 7 <= this.DaysInMonth(firstWeekday.getFullYear(), firstWeekday.getMonth() + 1)) {
                    date = new Date(date.getFullYear(), date.getMonth(), date.getDate() + 7);
                    days.push(date);
                }
                return days;
            };

            DateTimeInfo.AddMilliseconds = function (date, msec) {
                var newDate = new Date(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds());
                newDate.setMilliseconds(newDate.getMilliseconds() + msec);
                return new Date(newDate.valueOf());
            };

            DateTimeInfo.GetWeekIndexByDate = function (date) {
                return Math.floor(date.getDate() / 7);
            };
            DateTimeInfo.EraDates = new Array(new Date(1868, 9 - 1, 8), new Date(1912, 7 - 1, 30), new Date(1926, 12 - 1, 25), new Date(1989, 1 - 1, 8));
            DateTimeInfo.EraCount = 4;
            DateTimeInfo.EraYears = new Array(45, 15, 64, 99);
            DateTimeInfo.EraMax = new Date(2087, 12 - 1, 31, 23, 59, 59);
            DateTimeInfo.EraMin = new Date(1868, 9 - 1, 8);
            DateTimeInfo.EraKeys = new Array("1", "2", "3", "4", "m", "t", "s", "h");
            DateTimeInfo.EraIndices = new Array(0, 1, 2, 3, 0, 1, 2, 3);
            DateTimeInfo.DateLongFormat = "yyyyMMddHHmmss";
            DateTimeInfo.EraNames = new Array("M", "T", "S", "H", "\u660E", "\u5927", "\u662D", "\u5E73", "\u660E\u6CBB", "\u5927\u6B63", "\u662D\u548C", "\u5E73\u6210");
            DateTimeInfo.WeekDays = new Array("\u65e5\u66dc\u65e5", "\u6708\u66dc\u65e5", "\u706b\u66dc\u65e5", "\u6c34\u66dc\u65e5", "\u6728\u66dc\u65e5", "\u91d1\u66dc\u65e5", "\u571f\u66dc\u65e5");
            DateTimeInfo.MonthNames = new Array("\u0031\u6708", "\u0032\u6708", "\u0033\u6708", "\u0034\u6708", "\u0035\u6708", "\u0036\u6708", "\u0037\u6708", "\u0038\u6708", "\u0039\u6708", "\u0031\u0030\u6708", "\u0031\u0031\u6708", "\u0031\u0032\u6708");
            DateTimeInfo.ShortWeekDays = new Array("\u65e5", "\u6708", "\u706b", "\u6c34", "\u6728", "\u91d1", "\u571f");
            DateTimeInfo.ShortMonthNames = new Array("\u0031", "\u0032", "\u0033", "\u0034", "\u0035", "\u0036", "\u0037", "\u0038", "\u0039", "\u0031\u0030", "\u0031\u0031", "\u0031\u0032");
            DateTimeInfo.RokuyouTextArray = new Array("\u5148\u52dd", "\u53cb\u5f15", "\u5148\u8ca0", "\u4ecf\u6ec5", "\u5927\u5b89", "\u8d64\u53e3");
            DateTimeInfo.RokuyouTextArrayEn = new Array("Senshou", "Tomobiki", "Senbu", "Butsumetsu", "Taian", "Shakkou");
            DateTimeInfo.DefaultTwoDigitYear = 2029;
            DateTimeInfo.Digits = 2;
            DateTimeInfo.EraYearMax = 99;
            DateTimeInfo.RokuyouMin = new Date(1960, 0, 28);
            DateTimeInfo.RokuyouMax = new Date(2050, 0, 22);
            DateTimeInfo.LunarInfo = new Array(0x0aea6, 0x0ab50, 0x04d60, 0x0aae4, 0x0a570, 0x05270, 0x07263, 0x0d950, 0x06b57, 0x056a0, 0x09ad0, 0x04dd5, 0x04ae0, 0x0a4e0, 0x0d4d4, 0x0d250, 0x0d598, 0x0b540, 0x0d6a0, 0x0195a6, 0x095b0, 0x049b0, 0x0a9b4, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0b756, 0x02b60, 0x095b0, 0x04b75, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06d98, 0x055d0, 0x02b60, 0x096e5, 0x092e0, 0x0c960, 0x0e954, 0x0d4a0, 0x0da50, 0x07552, 0x056c0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x1b4a3, 0x0b550, 0x055d9, 0x04ba0, 0x0a5b0, 0x05575, 0x052b0, 0x0a950, 0x0b954, 0x06aa0, 0x0ad50, 0x06b52, 0x04b60, 0x0a6e6, 0x0a570, 0x05270, 0x06a65, 0x0d930, 0x05aa0, 0x0b6a3, 0x096d0, 0x04bd7, 0x04ae0, 0x0a4d0, 0x01d0d6, 0x0d250, 0x0d520, 0x0dd45, 0x0b6a0, 0x096d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0b250, 0x01b255, 0x06d40, 0x0ada0);
            return DateTimeInfo;
        })();
        input.DateTimeInfo = DateTimeInfo;

        

        /** @ignore */
        var wijDateTextFormatter = (function () {
            function wijDateTextFormatter(inputWidget, format, isDisplayFormat) {
                this.inputWidget = inputWidget;
                this.maskPartsCount = 0;
                this.isDisplayFormat = true;
                this.pattern = 'M/d/yyyy';
                this.descriptors = new Array(0);
                this.desPostions = new Array(0);
                this.fields = new Array(0);
                this.isDisplayFormat = isDisplayFormat;
                this._setFormat(format);
            }
            wijDateTextFormatter.prototype._parseFormat = function (pattern) {
                var descriptors = [];
                var curPattern = '', prevCh = '', isBegin = false, liternalNext = false, i, ch;
                for (i = 0; i < pattern.length; i++) {
                    ch = pattern.charAt(i);
                    if (liternalNext) {
                        descriptors.push(this.createDescriptor(-1, ch));
                        curPattern = '';
                        liternalNext = false;
                        continue;
                    }
                    if (ch === '\\') {
                        liternalNext = true;
                        if (curPattern.length > 0) {
                            if (!this.handlePattern(curPattern, descriptors)) {
                                descriptors.push(this.createDescriptor(-1, prevCh));
                            }
                            curPattern = '';
                        }
                        continue;
                    }
                    if (ch === '\'') {
                        if (isBegin) {
                            isBegin = false;
                            curPattern = '';
                        } else {
                            isBegin = true;
                            if (curPattern.length > 0) {
                                if (!this.handlePattern(curPattern, descriptors)) {
                                    descriptors.push(this.createDescriptor(-1, prevCh));
                                }
                                curPattern = '';
                            }
                        }
                        continue;
                    }
                    if (isBegin) {
                        descriptors.push(this.createDescriptor(-1, ch));
                        curPattern = '';
                        continue;
                    }
                    if (!i) {
                        prevCh = ch;
                    }
                    if (prevCh !== ch && curPattern.length > 0) {
                        if (!this.handlePattern(curPattern, descriptors)) {
                            descriptors.push(this.createDescriptor(-1, prevCh));
                        }
                        curPattern = '';
                    }
                    curPattern += ch;
                    prevCh = ch;
                }
                if (curPattern.length > 0) {
                    if (!this.handlePattern(curPattern, descriptors)) {
                        descriptors.push(this.createDescriptor(-1, prevCh));
                    }
                }

                return descriptors;
            };

            wijDateTextFormatter.prototype._parseFormatToPattern = function (format) {
                var cf = this.inputWidget._getCulture().calendar, pattern = cf.patterns.d;
                if (format.length <= 1) {
                    switch (format) {
                        case "":
                        case "d":
                            pattern = cf.patterns.d;
                            break;
                        case "D":
                            pattern = cf.patterns.D;
                            break;
                        case "f":
                            pattern = cf.patterns.D + " " + cf.patterns.t;
                            break;
                        case "F":
                            pattern = cf.patterns.D + " " + cf.patterns.T;
                            break;
                        case "g":
                            pattern = cf.patterns.d + " " + cf.patterns.t;
                            break;
                        case "G":
                            pattern = cf.patterns.d + " " + cf.patterns.T;
                            break;
                        case "m":
                            pattern = cf.patterns.M;
                            break;
                        case "M":
                            pattern = cf.patterns.M;
                            break;
                        case "s":
                            pattern = cf.patterns.S;
                            break;
                        case "t":
                            pattern = cf.patterns.t;
                            break;
                        case "T":
                            pattern = cf.patterns.T;
                            break;
                        case "u":
                            pattern = cf.patterns.S;
                            break;
                        case "U":
                            // Full date and time (long date and long time) using universal time
                            pattern = cf.patterns.D + " " + cf.patterns.T;
                            break;
                        case "y":
                            pattern = cf.patterns.Y;
                            break;
                        case "Y":
                            pattern = cf.patterns.Y;
                            break;
                        case "r":
                        case "R":
                            pattern = "ddd, dd MMM yyyy HH:mm:ss G\\M\\T";
                            break;
                        case "E":
                            pattern = "E";
                            break;
                    }
                } else {
                    pattern = format;
                }

                return pattern;
            };

            wijDateTextFormatter.prototype.createDescriptor = function (t, liternal) {
                var desc = null, id = this.maskPartsCount++;
                switch (t) {
                    case -1:
                        desc = new _dateDescriptor(this, id);
                        desc.liternal = liternal;
                        break;
                    case 20:
                        desc = new _dateDescriptor20(this, id);
                        break;
                    case 25:
                        desc = new _dateDescriptor25(this, id);
                        break;
                    case 26:
                        desc = new _dateDescriptor26(this, id);
                        break;
                    case 27:
                        desc = new _dateDescriptor27(this, id);
                        break;
                    case 30:
                        desc = new _dateDescriptor30(this, id);
                        break;
                    case 31:
                        desc = new _dateDescriptor31(this, id);
                        break;
                    case 100:
                        desc = new _dateDescriptor100(this, id);
                        break;
                    case 101:
                        desc = new _dateDescriptor101(this, id);
                        break;
                    case 10:
                        desc = new _dateDescriptor10(this, id);
                        break;
                    case 1:
                        desc = new _dateDescriptor1(this, id);
                        break;
                    case 2:
                        desc = new _dateDescriptor2(this, id);
                        break;
                    case 45:
                        desc = new _dateDescriptor45(this, id);
                        break;
                    case 46:
                        desc = new _dateDescriptor46(this, id);
                        break;
                    case 47:
                        desc = new _dateDescriptor47(this, id);
                        break;
                    case 48:
                        desc = new _dateDescriptor48(this, id);
                        break;
                    case 250:
                        desc = new _dateDescriptor250(this, id);
                        break;
                    case 251:
                        desc = new _dateDescriptor251(this, id);
                        break;
                    case 50:
                        desc = new _dateDescriptor50(this, id);
                        break;
                    case 51:
                        desc = new _dateDescriptor51(this, id);
                        break;
                    case 60:
                        desc = new _dateDescriptor60(this, id);
                        break;
                    case 61:
                        desc = new _dateDescriptor61(this, id);
                        break;
                    case 70:
                        desc = new _dateDescriptor70(this, id);
                        break;
                    case 71:
                        desc = new _dateDescriptor71(this, id);
                        break;
                    case 72:
                        desc = new _dateDescriptor72(this, id);
                        break;
                    case 73:
                        desc = new _dateDescriptor73(this, id);
                        break;
                    case 74:
                        desc = new _dateDescriptor74(this, id);
                        break;
                    case 75:
                        desc = new _dateDescriptor75(this, id);
                        break;
                    case 80:
                        desc = new _dateDescriptor80(this, id);
                        break;
                    default:
                        break;
                }
                return desc;
            };

            wijDateTextFormatter.prototype.handlePattern = function (p, descriptors) {
                var reg = new RegExp('y{3,10}'), suc = reg.test(p);
                if (suc) {
                    if (this.inputWidget) {
                        if (this.inputWidget.options.cultureCalendar === "Japanese") {
                            descriptors.push(this.createDescriptor(71));
                            return true;
                        }
                    }
                    descriptors.push(this.createDescriptor(10));
                    return true;
                }
                reg = new RegExp('y{2,2}');
                suc = reg.test(p);
                if (suc) {
                    if (this.inputWidget) {
                        if (this.inputWidget.options.cultureCalendar === "Japanese") {
                            descriptors.push(this.createDescriptor(71));
                            return true;
                        }
                    }
                    descriptors.push(this.createDescriptor(2));
                    return true;
                }
                reg = new RegExp('y{1,1}');
                suc = reg.test(p);
                if (suc) {
                    if (this.inputWidget) {
                        if (this.inputWidget.options.cultureCalendar === "Japanese") {
                            descriptors.push(this.createDescriptor(70));
                            return true;
                        }
                    }
                    descriptors.push(this.createDescriptor(1));
                    return true;
                }
                reg = new RegExp('d{4,4}');
                suc = reg.test(p);
                if (suc) {
                    descriptors.push(this.createDescriptor(101));
                    return true;
                }
                reg = new RegExp('d{3,3}');
                suc = reg.test(p);
                if (suc) {
                    descriptors.push(this.createDescriptor(100));
                    return true;
                }
                reg = new RegExp('d{2,2}');
                suc = reg.test(p);
                if (suc) {
                    descriptors.push(this.createDescriptor(30));
                    return true;
                }
                reg = new RegExp('d{1,1}');
                suc = reg.test(p);
                if (suc) {
                    descriptors.push(this.createDescriptor(31));
                    return true;
                }
                reg = new RegExp('M{4,4}');
                suc = reg.test(p);
                if (suc) {
                    descriptors.push(this.createDescriptor(27));
                    return true;
                }
                reg = new RegExp('M{3,3}');
                suc = reg.test(p);
                if (suc) {
                    descriptors.push(this.createDescriptor(26));
                    return true;
                }
                reg = new RegExp('M{2,2}');
                suc = reg.test(p);
                if (suc) {
                    descriptors.push(this.createDescriptor(20));
                    return true;
                }
                reg = new RegExp('M{1,1}');
                suc = reg.test(p);
                if (suc) {
                    descriptors.push(this.createDescriptor(25));
                    return true;
                }
                reg = new RegExp('h{2,2}');
                suc = reg.test(p);
                if (suc) {
                    descriptors.push(this.createDescriptor(46));
                    return true;
                }
                reg = new RegExp('h{1,1}');
                suc = reg.test(p);
                if (suc) {
                    descriptors.push(this.createDescriptor(45));
                    return true;
                }
                reg = new RegExp('H{2,2}');
                suc = reg.test(p);
                if (suc) {
                    descriptors.push(this.createDescriptor(48));
                    return true;
                }
                reg = new RegExp('H{1,1}');
                suc = reg.test(p);
                if (suc) {
                    descriptors.push(this.createDescriptor(47));
                    return true;
                }
                reg = new RegExp('m{2,2}');
                suc = reg.test(p);
                if (suc) {
                    descriptors.push(this.createDescriptor(50));
                    return true;
                }
                reg = new RegExp('m{1,1}');
                suc = reg.test(p);
                if (suc) {
                    descriptors.push(this.createDescriptor(51));
                    return true;
                }
                reg = new RegExp('s{2,2}');
                suc = reg.test(p);
                if (suc) {
                    descriptors.push(this.createDescriptor(60));
                    return true;
                }
                reg = new RegExp('s{1,1}');
                suc = reg.test(p);
                if (suc) {
                    descriptors.push(this.createDescriptor(61));
                    return true;
                }
                reg = new RegExp('t{2,2}');
                suc = reg.test(p);
                if (suc) {
                    descriptors.push(this.createDescriptor(251));
                    return true;
                }
                reg = new RegExp('t{1,1}');
                suc = reg.test(p);
                if (suc) {
                    descriptors.push(this.createDescriptor(250));
                    return true;
                }
                reg = new RegExp('e{2,10}');
                suc = reg.test(p);
                if (suc) {
                    descriptors.push(this.createDescriptor(71));
                    return true;
                }
                reg = new RegExp('e{1,1}');
                suc = reg.test(p);
                if (suc) {
                    descriptors.push(this.createDescriptor(70));
                    return true;
                }
                reg = new RegExp('g{3,10}');
                suc = reg.test(p);
                if (suc) {
                    descriptors.push(this.createDescriptor(74));
                    return true;
                }
                reg = new RegExp('g{2,2}');
                suc = reg.test(p);
                if (suc) {
                    if (this.inputWidget) {
                        if (this.inputWidget.options.cultureCalendar === "Japanese") {
                            descriptors.push(this.createDescriptor(74));
                            return true;
                        }
                    }
                    descriptors.push(this.createDescriptor(73));
                    return true;
                }
                reg = new RegExp('g{1,1}');
                suc = reg.test(p);
                if (suc) {
                    if (this.inputWidget) {
                        if (this.inputWidget.options.cultureCalendar === "Japanese") {
                            descriptors.push(this.createDescriptor(74));
                            return true;
                        }
                    }
                    descriptors.push(this.createDescriptor(72));
                    return true;
                }

                if (this.isDisplayFormat) {
                    reg = new RegExp('E{1,10}');
                    suc = reg.test(p);
                    if (suc) {
                        descriptors.push(this.createDescriptor(75));
                        return true;
                    }

                    reg = new RegExp('A{1,1}');
                    suc = reg.test(p);
                    if (suc) {
                        descriptors.push(this.createDescriptor(80));
                        return true;
                    }
                }

                return false;
            };

            wijDateTextFormatter.prototype.daysInMonth = function (m, y) {
                m = m - 1;
                var d = new Date(y, ++m, 1, -1).getDate();
                return d;
            };

            wijDateTextFormatter.prototype._isDigitString = function (s) {
                s = $.trim(s);
                if (s.length === 0) {
                    return true;
                }

                var c = s.charAt(0), f, t;
                if (c === '+' || c === '-') {
                    s = s.substr(1);
                    s = $.trim(s);
                }
                if (s.length === 0) {
                    return true;
                }
                try  {
                    f = parseFloat(s);
                    t = f.toString();
                    return t === s;
                } catch (e) {
                    return false;
                }
            };

            wijDateTextFormatter.prototype._internalSetDate = function (date) {
                if (this.inputWidget) {
                    this.inputWidget._internalSetDate(date);
                }
            };

            wijDateTextFormatter.prototype._isValidDate = function (dt) {
                return this.inputWidget._isValidDate(dt);
            };

            wijDateTextFormatter.prototype._setFormat = function (format) {
                var culture = this.inputWidget._getCulture();
                if (culture == null) {
                    return;
                }

                this.pattern = this._parseFormatToPattern(format);
                this.descriptors = this._parseFormat(this.pattern);
                this.fields = $.grep(this.descriptors, function (d) {
                    return d.type !== -1;
                });
            };

            wijDateTextFormatter.prototype._isEraFormatExist = function () {
                for (var i = 0; i < this.descriptors.length; i++) {
                    if (this.descriptors[i].type >= 70 && this.descriptors[i].type <= 75) {
                        return true;
                    }
                }

                return false;
            };

            wijDateTextFormatter.prototype.getDate = function () {
                return (!!this.inputWidget) ? new Date(this.inputWidget._safeGetDate(true).getTime()) : undefined;
            };

            wijDateTextFormatter.prototype.setDate = function (value) {
                if (this.inputWidget) {
                    this.inputWidget._setData(value);
                }
            };

            wijDateTextFormatter.prototype.getYear = function () {
                return this.getDate().getFullYear();
            };

            wijDateTextFormatter.prototype.setYear = function (val, resultObj, chkBounds) {
                try  {
                    if (resultObj && resultObj.isfullreset) {
                        resultObj.offset = 1;
                        val = '1970';
                    }
                    if (typeof val === 'string') {
                        if (!this._isDigitString(val)) {
                            return false;
                        }
                    }
                    val = val * 1;

                    var o = this.inputWidget.options, minYear = 1, maxYear = 9999, currentDate, testDate, mmm;

                    if (chkBounds) {
                        if (o.minDate) {
                            minYear = Math.max(minYear, o.minDate.getFullYear());
                        }

                        if (o.maxDate) {
                            maxYear = Math.min(maxYear, o.maxDate.getFullYear());
                        }
                    }

                    if (resultObj && resultObj.isreset) {
                        val = minYear;
                    }

                    if (val < minYear) {
                        val = minYear;
                    }

                    if (val > maxYear) {
                        val = maxYear;
                    }

                    currentDate = this.getDate();
                    testDate = new Date(currentDate.getTime());
                    testDate.setFullYear(val);
                    if (this._isValidDate(testDate)) {
                        mmm = this.daysInMonth(this.getMonth(), this.getYear());
                        if (mmm === currentDate.getDate()) {
                            testDate = new Date(currentDate.getTime());
                            testDate.setDate(1);
                            testDate.setFullYear(val);

                            //mmm = this.daysInMonth((testDate.getMonth() + 1),
                            //   testDate.getFullYear());
                            testDate.setDate(mmm);
                            if (this._isValidDate(testDate)) {
                                this._internalSetDate(testDate);
                                return true;
                            } else {
                                return false;
                            }
                        }
                        currentDate.setFullYear(val);
                        this._internalSetDate(currentDate);
                        return true;
                    } else {
                        if (resultObj && resultObj.isreset) {
                            currentDate.setFullYear(1);
                            this._internalSetDate(currentDate);
                            return true;
                        }
                        return false;
                    }
                } catch (e) {
                    return false;
                }
            };

            wijDateTextFormatter.prototype.getMonth = function () {
                return (this.getDate().getMonth() + 1);
            };

            wijDateTextFormatter.prototype.setMonth = function (val, allowChangeOtherParts, resultObj) {
                try  {
                    if (resultObj && resultObj.isfullreset) {
                        val = '1';
                    }
                    val = val * 1;
                    var currentDate = this.getDate(), mmm, testDate;
                    if (typeof (allowChangeOtherParts) !== 'undefined' && !allowChangeOtherParts) {
                        if (val > 12 || val < 1) {
                            if (resultObj && resultObj.isreset) {
                                val = 1;
                            } else {
                                return false;
                            }
                        }
                    }
                    mmm = this.daysInMonth(this.getMonth(), this.getYear());
                    if (mmm === this.getDate().getDate()) {
                        testDate = new Date(currentDate.getTime());
                        testDate.setDate(1);
                        testDate.setMonth(val - 1);
                        mmm = this.daysInMonth((testDate.getMonth() + 1), testDate.getFullYear());
                        testDate.setDate(mmm);
                        if (this._isValidDate(testDate)) {
                            this._internalSetDate(testDate);
                            return true;
                        } else {
                            return false;
                        }
                    } else {
                        testDate = new Date(currentDate.getTime());
                        testDate.setMonth(val - 1);
                        if (this._isValidDate(testDate)) {
                            this._internalSetDate(testDate);
                            return true;
                        } else {
                            return false;
                        }
                    }
                } catch (e) {
                    return false;
                }
            };

            wijDateTextFormatter.prototype.getHours = function () {
                return this.getDate().getHours();
            };

            wijDateTextFormatter.prototype.setHours = function (val, allowChangeOtherParts) {
                try  {
                    val = val * 1;
                    if (typeof (allowChangeOtherParts) !== 'undefined' && !allowChangeOtherParts) {
                        if (val > 24) {
                            return false;
                        }
                    }
                    var testDate = new Date(this.getDate().getTime());
                    testDate.setHours(val);
                    if (this._isValidDate(testDate)) {
                        this._internalSetDate(testDate);
                        return true;
                    } else {
                        return false;
                    }
                } catch (e) {
                    return false;
                }
            };

            wijDateTextFormatter.prototype.getMinutes = function () {
                return this.getDate().getMinutes();
            };

            wijDateTextFormatter.prototype.setMinutes = function (val, allowChangeOtherParts) {
                try  {
                    val = val * 1;
                    if (typeof (allowChangeOtherParts) !== 'undefined' && !allowChangeOtherParts) {
                        if (val > 60) {
                            return false;
                        }
                    }
                    var testDate = new Date(this.getDate().getTime());
                    testDate.setMinutes(val);
                    if (this._isValidDate(testDate)) {
                        this._internalSetDate(testDate);
                        return true;
                    } else {
                        return false;
                    }
                } catch (e) {
                    return false;
                }
            };

            wijDateTextFormatter.prototype.getSeconds = function () {
                return this.getDate().getSeconds();
            };

            wijDateTextFormatter.prototype.setSeconds = function (val, allowChangeOtherParts) {
                try  {
                    val = val * 1;
                    if (typeof (allowChangeOtherParts) !== 'undefined' && !allowChangeOtherParts) {
                        if (val > 60) {
                            return false;
                        }
                    }
                    var testDate = new Date(this.getDate().getTime());
                    testDate.setSeconds(val);
                    if (this._isValidDate(testDate)) {
                        this._internalSetDate(testDate);
                        return true;
                    } else {
                        return false;
                    }
                } catch (e) {
                    return false;
                }
            };

            wijDateTextFormatter.prototype.getDayOfMonth = function () {
                return this.getDate().getDate();
            };

            wijDateTextFormatter.prototype.setDayOfMonth = function (val, allowChangeOtherParts, resultObj) {
                try  {
                    if (resultObj && resultObj.isfullreset) {
                        return this.setDayOfMonth(1, allowChangeOtherParts);
                    }
                    var currentDate = this.getDate(), mmm, testDate;
                    val = val * 1;
                    if (typeof (allowChangeOtherParts) !== 'undefined' && !allowChangeOtherParts) {
                        mmm = this.daysInMonth(this.getMonth(), this.getYear());
                        if (val > mmm || val < 1) {
                            if (resultObj && resultObj.isreset) {
                                return this.setDayOfMonth(1, allowChangeOtherParts, resultObj);
                            }
                            return false;
                        }
                    }
                    testDate = new Date(currentDate.getTime());
                    testDate.setDate(val);
                    if (this._isValidDate(testDate)) {
                        this._internalSetDate(testDate);
                        return true;
                    } else {
                        return false;
                    }
                } catch (e) {
                    return false;
                }
            };

            wijDateTextFormatter.prototype.getDayOfWeek = function () {
                return (this.getDate().getDay() + 1);
            };

            wijDateTextFormatter.prototype.setDayOfWeek = function (val) {
                try  {
                    val = val * 1;
                    var aDif = val - this.getDayOfWeek();
                    return this.setDayOfMonth(this.getDayOfMonth() + aDif, true);
                } catch (e) {
                    return false;
                }
            };

            wijDateTextFormatter.prototype._getCulture = function () {
                return this.inputWidget._getCulture();
            };

            wijDateTextFormatter.prototype.findAlikeArrayItemIndex = function (arr, txt) {
                var index = -1, pos = 99999, i, k;
                for (i = 0; i < arr.length; i++) {
                    k = arr[i].toLowerCase().indexOf(txt.toLowerCase());
                    if (k !== -1 && k < pos) {
                        pos = k;
                        index = i;
                    }
                }
                return index;
            };

            wijDateTextFormatter.prototype.toString = function () {
                if (this._isEraFormatExist()) {
                    if (this.inputWidget.options.date != null) {
                        var minDate = this.inputWidget._getRealEraMinDate();
                        var maxDate = this.inputWidget._getRealEraMaxDate();
                        if (this.inputWidget.options.date < minDate || this.inputWidget.options.date > maxDate) {
                            return "";
                        }
                    }
                }

                var s = '', l = 0, i, txt, j;
                this.desPostions = new Array(0);
                for (i = 0; i < this.descriptors.length; i++) {
                    this.descriptors[i].startIndex = s.length;
                    txt = '' || this.descriptors[i].getText();
                    s += txt;
                    for (j = 0; j < txt.length; j++) {
                        this.desPostions.push({
                            desc: this.descriptors[i],
                            pos: j,
                            text: txt,
                            length: txt.length
                        });
                        l++;
                        if (this.desPostions.length !== l) {
                            throw 'Fatal Error !!!!!!!!!!!!!!!';
                        }
                    }
                }
                return s;
            };
            return wijDateTextFormatter;
        })();
        input.wijDateTextFormatter = wijDateTextFormatter;
        ;

        //#region format library
        /** @ignore */
        var wijInputDateImpl = (function () {
            function wijInputDateImpl(options) {
                this.options = options;
                options.format = options.format || "M/d/yyyy";
                options.amDesignator = options.amDesignator || "";
                options.pmDesignator = options.pmDesignator || "";
                if (options.hour12As0 === undefined) {
                    options.hour12As0 = false;
                }
                if (options.midnightAs0 === undefined) {
                    options.midnightAs0 = true;
                }
            }
            wijInputDateImpl.prototype._getInnerIncrement = function () {
                return 1;
            };

            wijInputDateImpl.prototype._getCulture = function () {
                return Globalize.findClosestCulture(this.options.culture);
            };

            wijInputDateImpl.prototype._getRealEraMaxDate = function () {
                if (this.options.maxDate) {
                    return DateTimeInfo.GetEraMax() < this.options.maxDate ? DateTimeInfo.GetEraMax() : this.options.maxDate;
                }

                return DateTimeInfo.GetEraMax();
            };

            wijInputDateImpl.prototype._getRealEraMinDate = function () {
                if (this.options.minDate) {
                    return DateTimeInfo.GetEraMin() > this.options.minDate ? DateTimeInfo.GetEraMin() : this.options.minDate;
                }

                return DateTimeInfo.GetEraMin();
            };

            wijInputDateImpl.prototype._safeGetDate = function (ignoreCheckRange) {
                var date = this.options.date;
                if (date == null) {
                    date = new Date();
                }
                if (!ignoreCheckRange) {
                    date = this._checkRange(date);
                }
                return date;
            };

            wijInputDateImpl.prototype._safeSetDate = function (date, ignoreCheckRange) {
                var cache = date;

                if (!ignoreCheckRange) {
                    date = this._checkRange(date);
                }

                if (isNaN(date)) {
                    date = cache;
                }

                this.options.date = date;
                return true;
            };

            wijInputDateImpl.prototype._getAllowSpinLoop = function () {
                return false;
            };

            wijInputDateImpl.prototype._getRealMinDate = function () {
                if (this.options.minDate) {
                    return this.options.minDate;
                }

                var minDate = new Date(1, 0, 1, 0, 0, 0);
                minDate.setFullYear(1);

                return minDate;
            };

            wijInputDateImpl.prototype._getRealMaxDate = function () {
                return this.options.maxDate ? this.options.maxDate : new Date(9999, 11, 31, 23, 59, 59);
            };

            wijInputDateImpl.prototype._setData = function (val) {
                this.options.date = val;
            };

            wijInputDateImpl.prototype._isValidDate = function (date, chkBounds) {
                if (date === undefined) {
                    return false;
                }

                if (isNaN(date)) {
                    return false;
                }

                if (date.getFullYear() < 1 || date.getFullYear() > 9999) {
                    return false;
                }

                if (chkBounds) {
                    if (this.options.minDate) {
                        if (date < this.options.minDate) {
                            return false;
                        }
                    }

                    if (this.options.maxDate) {
                        if (date > this.options.maxDate) {
                            return false;
                        }
                    }
                }

                return true;
            };

            wijInputDateImpl.prototype._getInnerAmDesignator = function () {
                return this.options.amDesignator == "" ? this._getStandardAMPM("AM") : this.options.amDesignator;
            };

            wijInputDateImpl.prototype._getInnerPmDesignator = function () {
                return this.options.pmDesignator == "" ? this._getStandardAMPM("PM") : this.options.pmDesignator;
            };

            wijInputDateImpl.prototype.isFocused = function () {
                return false;
            };

            wijInputDateImpl.prototype._internalSetDate = function (date) {
            };

            wijInputDateImpl.prototype._checkRange = function (date) {
                if (date) {
                    if (this.options.minDate && date < this.options.minDate) {
                        date = new Date(Math.max(this.options.minDate.valueOf(), date.valueOf()));
                    }

                    if (this.options.maxDate && date > this.options.maxDate) {
                        date = new Date(Math.min(this.options.maxDate.valueOf(), date.valueOf()));
                    }
                }

                return date;
            };

            wijInputDateImpl.prototype._getStandardAMPM = function (value) {
                var culture = this._getCulture();
                if (culture && culture.calendar) {
                    var tmp = culture.calendars.standard[value];
                    if (tmp) {
                        return tmp[0];
                    }
                }
                return value;
            };
            return wijInputDateImpl;
        })();
        input.wijInputDateImpl = wijInputDateImpl;

        function dateFormatter(date, format, options) {
            if (!(date instanceof Date)) {
                return "";
            }
            if (!format) {
                format = 'd';
            }

            if (!options) {
                if (typeof format === "string") {
                    options = {};
                } else {
                    options = format;
                }
            }
            if (typeof format === "string") {
                options.format = format;
            }
            options.date = date;

            var wijInputDate = new wijInputDateImpl(options);

            var _formatter = new wijDateTextFormatter(wijInputDate, options.format, true);

            return _formatter.toString();
        }

        var $ = jQuery;
        $.wijinputcore = $.wijinputcore || {};
        ;
        $.wijinputcore.formatdate = $.wijinputcore.formatdate || dateFormatter;

        //#endregion
        //#region parse library
        function dateParser(value, format, culture) {
            if (Globalize.findClosestCulture(format)) {
                culture = format;
                format = undefined;
            }

            var cf = Globalize.findClosestCulture(culture).calendars.standard, pattern = cf.patterns.d;

            if (format) {
                if (format.length <= 1) {
                    pattern = parseShortPattern(format, cf.patterns);
                } else {
                    pattern = format;
                }
            } else {
                pattern = cf.patterns.d;
            }

            var wijInputDate = new wijInputDateImpl({});
            var _formatter = new wijDateTextFormatter(wijInputDate, pattern, true);

            if (hasEraYear(_formatter.descriptors)) {
                return parseEraDate(value, _formatter, cf);
            } else {
                return Globalize.parseDate(value, pattern, culture);
            }
        }

        function hasEraYear(descriptors) {
            for (var i = 0; i < descriptors.length; i++) {
                if (descriptors[i].type === 70 /* EraYear */ || descriptors[i].type === 71 /* TwoEraYear */ || descriptors[i].type === 72 /* EraName */ || descriptors[i].type === 73 /* TwoEraName */ || descriptors[i].type === 74 /* ThreeEraName */ || descriptors[i].type === 75 /* EraYearBig */) {
                    return true;
                }
            }
            return false;
        }

        function parseEraDate(value, _formatter, cultureFormat) {
            var ch = "", chs = "", charIndex = 0;
            var era = 0, eraYear = 1, month = 1, date = 1, hour = 0, minute = 0, second = 0;

            var isNextReachSeparator = function () {
                return (charIndex < value.length && i + 1 < _formatter.descriptors.length && _formatter.descriptors[i + 1].type === -1 /* liternal */ && value.charAt(charIndex) !== _formatter.descriptors[i + 1].liternal || i === _formatter.descriptors.length - 1 && charIndex + 1 <= value.length);
            };

            for (var i = 0; i < _formatter.descriptors.length; i++) {
                var breakToNextDesc = false;

                for (; charIndex < value.length;) {
                    ch = value.charAt(charIndex++);
                    chs += ch;

                    for (var j = 0; j < DateTimeInfo.GetEraCount(); j++) {
                        var isMatched_g = chs.toLocaleLowerCase() === DateTimeInfo.GetEraShortNames()[j].toLowerCase() && _formatter.descriptors[i].type === 72 /* EraName */;
                        var isMatched_gg = chs.toLocaleLowerCase() === DateTimeInfo.GetEraAbbreviations()[j].toLowerCase() && _formatter.descriptors[i].type === 73 /* TwoEraName */;
                        var isMatched_ggg = chs.toLocaleLowerCase() === DateTimeInfo.GetEraNames()[j].toLowerCase() && _formatter.descriptors[i].type === 74 /* ThreeEraName */;

                        if (isMatched_g || isMatched_gg || isMatched_ggg) {
                            era = j;
                            chs = "";
                            breakToNextDesc = true;
                            break;
                        }
                    }
                    if (breakToNextDesc) {
                        break;
                    }

                    if (_formatter.descriptors[i].type === -1 /* liternal */ && _formatter.descriptors[i].liternal === chs) {
                        chs = "";
                        break;
                    }

                    switch (_formatter.descriptors[i].type) {
                        case 70 /* EraYear */:
                        case 71 /* TwoEraYear */:
                            if (isNextReachSeparator()) {
                                break;
                            }

                            eraYear = parseInt(chs, 10);
                            if (isNaN(eraYear)) {
                                eraYear = 1;
                            }
                            chs = "";
                            breakToNextDesc = true;
                            break;
                        case 75 /* EraYearBig */:
                            if (isNextReachSeparator()) {
                                break;
                            }

                            if (chs === '\u5143') {
                                eraYear = 1;
                            } else {
                                eraYear = parseInt(chs, 10);
                                if (isNaN(eraYear)) {
                                    eraYear = 1;
                                }
                            }
                            chs = "";
                            breakToNextDesc = true;
                            break;
                        case 20 /* TwoDigitMonth */:
                        case 25 /* Month */:
                            if (isNextReachSeparator()) {
                                break;
                            }

                            month = parseInt(chs, 10);
                            if (isNaN(month)) {
                                month = 1;
                            }
                            chs = "";
                            breakToNextDesc = true;
                            break;
                        case 26 /* AbbreviatedMonthNames */:
                            if (isNextReachSeparator()) {
                                break;
                            }
                            for (var m = 0; m < cultureFormat.months.namesAbbr.length; m++) {
                                if (chs.toLocaleLowerCase() === cultureFormat.months.namesAbbr[m]) {
                                    month = m + 1;
                                    chs = "";
                                    break;
                                }
                            }
                            breakToNextDesc = true;
                            break;
                        case 27 /* MonthNames */:
                            if (isNextReachSeparator()) {
                                break;
                            }
                            for (var k = 0; k < cultureFormat.months.names.length; k++) {
                                if (chs.toLocaleLowerCase() === cultureFormat.months.names[k]) {
                                    month = k + 1;
                                    chs = "";
                                    break;
                                }
                            }
                            breakToNextDesc = true;
                            break;
                        case 30 /* TwoDigityDayOfMonth */:
                        case 31 /* DayOfMonth */:
                            if (isNextReachSeparator()) {
                                break;
                            }

                            date = parseInt(chs, 10);
                            if (isNaN(date)) {
                                date = 1;
                            }
                            chs = "";
                            breakToNextDesc = true;
                            break;

                        case 45 /* h */:
                        case 46 /* hh */:
                        case 47 /* H */:
                        case 48 /* HH */:
                            if (isNextReachSeparator()) {
                                break;
                            }

                            hour = parseInt(chs, 10);
                            if (isNaN(hour)) {
                                hour = 1;
                            }
                            chs = "";
                            breakToNextDesc = true;
                            break;

                        case 51 /* m */:
                        case 50 /* mm */:
                            if (isNextReachSeparator()) {
                                break;
                            }

                            minute = parseInt(chs, 10);
                            if (isNaN(minute)) {
                                minute = 1;
                            }
                            chs = "";
                            breakToNextDesc = true;
                            break;
                        case 61 /* s */:
                        case 60 /* ss */:
                            if (isNextReachSeparator()) {
                                break;
                            }

                            second = parseInt(chs, 10);
                            if (isNaN(second)) {
                                second = 1;
                            }
                            chs = "";
                            breakToNextDesc = true;
                            break;

                        case 250 /* ShortAmPm */:
                        case 251 /* AmPm */:
                            if (isNextReachSeparator()) {
                                break;
                            }
                            for (var l = 0; l < cultureFormat.PM.length; l++) {
                                if (chs.toLocaleLowerCase() === cultureFormat.PM[l]) {
                                    hour += 12;
                                    break;
                                }
                            }
                            chs = "";
                            breakToNextDesc = true;
                            break;

                        case 1 /* OneDigitYear */:
                        case 2 /* TwoDigitYear */:
                        case 10 /* FourDigitYear */:

                        case 100 /* AbbreviatedDayNames */:
                        case 101 /* DayNames */:

                        case 80 /* AD */:
                            if (isNextReachSeparator()) {
                                break;
                            }

                            chs = "";
                            breakToNextDesc = true;
                            break;

                        default:
                    }
                    if (breakToNextDesc) {
                        break;
                    }
                }
            }

            return DateTimeInfo.ConvertToGregorianDate(era, eraYear, month, date, hour, minute, second, false);
        }

        function parseShortPattern(shortPattern, culturePatterns) {
            var pattern = shortPattern;
            if (shortPattern && shortPattern.length <= 1) {
                switch (shortPattern) {
                    case "":
                    case "d":
                        pattern = culturePatterns.patterns.d;
                        break;
                    case "D":
                        pattern = culturePatterns.patterns.D;
                        break;
                    case "f":
                        pattern = culturePatterns.patterns.D + " " + culturePatterns.patterns.t;
                        break;
                    case "F":
                        pattern = culturePatterns.patterns.D + " " + culturePatterns.patterns.T;
                        break;
                    case "g":
                        pattern = culturePatterns.patterns.d + " " + culturePatterns.patterns.t;
                        break;
                    case "G":
                        pattern = culturePatterns.patterns.d + " " + culturePatterns.patterns.T;
                        break;
                    case "m":
                        pattern = culturePatterns.patterns.M;
                        break;
                    case "M":
                        pattern = culturePatterns.patterns.M;
                        break;
                    case "s":
                        pattern = culturePatterns.patterns.S;
                        break;
                    case "t":
                        pattern = culturePatterns.patterns.t;
                        break;
                    case "T":
                        pattern = culturePatterns.patterns.T;
                        break;
                    case "u":
                        pattern = culturePatterns.patterns.S;
                        break;
                    case "U":
                        // Full date and time (long date and long time) using universal time
                        pattern = culturePatterns.patterns.D + " " + culturePatterns.patterns.T;
                        break;
                    case "y":
                        pattern = culturePatterns.patterns.Y;
                        break;
                    case "Y":
                        pattern = culturePatterns.patterns.Y;
                        break;
                    case "r":
                    case "R":
                        pattern = "ddd, dd MMM yyyy HH:mm:ss G\\M\\T";
                        break;
                }
            }
            return pattern;
        }

        $.wijinputcore.parseDate = $.wijinputcore.parseDate || dateParser;

        //#endregion
        //#region validate library
        function dateValidator(value, minDate, maxDate, format, culture) {
            var dateValue = dateParser(value, format, culture);
            return dateValue >= minDate && dateValue <= maxDate;
        }

        $.wijinputcore.validateDate = $.wijinputcore.validateDate || dateValidator;
    })(wijmo.input || (wijmo.input = {}));
    var input = wijmo.input;
})(wijmo || (wijmo = {}));
;
/// <reference path="jquery.wijmo.wijinputcore.ts"/>
/// <reference path="jquery.wijmo.wijinputdateformat.ts"/>
var wijmo;
(function (wijmo) {
    (function (input) {
        /** @ignore */
        var wijinputdateroller = (function () {
            function wijinputdateroller(owner) {
                this._owner = owner;
            }
            //#endregion
            //#region DatePicker
            wijinputdateroller.prototype._initDatePicker = function () {
                var datePicker = this._owner.element.data('datePicker');
                if (datePicker != undefined) {
                    return;
                }

                var self = this;
                var minYear = this._owner.element.data('pickerMinYear');
                var maxYear = this._owner.element.data('pickerMaxYear');
                var height = this._owner.element.data('itemHeight') * 5;
                var pickerWidth = this._owner.element.data('pickerWidth');
                var itemHeight = this._owner.element.data('itemHeight') + "px";
                var indicatorHeight = this._owner.element.data('indicatorHeight') + "px";
                var indicatorTranslateTop = this._owner.element.data('indicatorTranslateTop');
                var indicatorTranslateDown = this._owner.element.data('indicatorTranslateDown');
                var indicatorTranslateSelector = this._owner.element.data('indicatorTranslateSelector');
                var indicatorTranslateContent = this._owner.element.data('indicatorTranslateContent');

                var div = this._createDivElement(document.body, pickerWidth + "px");
                var divIndicator = this._createDivIndicatiorElement(div, itemHeight, "", indicatorTranslateSelector);
                var table = this._createTableElement(div, height + "px", "-", indicatorTranslateContent);
                var trDate = $("<tr/>").appendTo(table);

                var tdYearWidth = "33%";
                var tdMonthWidth = "33%";
                var tdDayWidth = "33%";

                if (this._owner.element.data('pickerDateMonthFormat') == "MMMM") {
                    tdYearWidth = "30%";
                    tdMonthWidth = "45%";
                    tdDayWidth = "25%";
                }

                // Year
                var tdYear = $("<td/>").css({ "width": tdYearWidth });
                var divYear = this._createPickerDivElement(tdYear, height);
                var divYearMask = this._createMaskElement(divYear, height);
                var pickerYearArray = new Array();
                for (var i = minYear; i <= maxYear; i++) {
                    var text = this._getRollText(i, this._owner.element.data('pickerDateYearFormat'));
                    var itemDiv = this._createItemElement(i, divYearMask, itemHeight, text);
                    pickerYearArray[i - minYear] = itemDiv;
                }

                // Month
                var tdMonth = $("<td/>").css({ "width": tdMonthWidth });
                var divMonth = this._createPickerDivElement(tdMonth, height);
                var divMonthMask = this._createMaskElement(divMonth, height);
                var pickerMonthArray = {};
                var i;
                for (i = 1; i <= 12; i++) {
                    var text = this._getRollText(i, this._owner.element.data('pickerDateMonthFormat'));
                    var itemDiv = this._createItemElement(i - 1, divMonthMask, itemHeight, text);
                    pickerMonthArray[i - 1] = itemDiv;
                }

                //Day
                var tdDay = $("<td/>").css({ "width": tdDayWidth });
                var divDay = this._createPickerDivElement(tdDay, height);
                var divDayMask = this._createMaskElement(divDay, height);
                var pickerDayArray = {};
                for (i = 1; i <= 31; i++) {
                    var text = this._getRollText(i, this._owner.element.data('pickerDateDayFormat'));
                    var itemDiv = this._createItemElement(i, divDayMask, itemHeight, text);
                    pickerDayArray[i - 1] = itemDiv;
                }

                var pickerDateFormat = this._owner.element.data('pickerDateFormat');
                var yearAdded = false, monthAdded = false, dayAdded = false;
                for (i = 0; i < pickerDateFormat.length; i++) {
                    if ((pickerDateFormat[i] == "yyyy") && !yearAdded) {
                        tdYear.appendTo(trDate);
                        yearAdded = true;
                    }

                    if ((pickerDateFormat[i] == "M" || pickerDateFormat[i] == "MM" || pickerDateFormat[i] == "MMM" || pickerDateFormat[i] == "MMMM") && !monthAdded) {
                        tdMonth.appendTo(trDate);
                        monthAdded = true;
                    }

                    if ((pickerDateFormat[i] == "d" || pickerDateFormat[i] == "dd") && !dayAdded) {
                        tdDay.appendTo(trDate);
                        dayAdded = true;
                    }
                }

                this._owner.element.data('datePicker', div);

                this._owner.element.data('divYear', divYear);
                this._owner.element.data('divMonth', divMonth);
                this._owner.element.data('divDay', divDay);

                this._owner.element.data('divYearMask', divYearMask);
                this._owner.element.data('divMonthMask', divMonthMask);
                this._owner.element.data('divDayMask', divDayMask);

                this._owner.element.data('pickerYearArray', pickerYearArray);
                this._owner.element.data('pickerMonthArray', pickerMonthArray);
                this._owner.element.data('pickerDayArray', pickerDayArray);

                if (!input.CoreUtility.IsIE8OrBelow()) {
                    var divYearIndicatorTop = this._createIndicatiorElement(divYear, indicatorHeight, "-", indicatorTranslateTop);
                    var divYearIndicatorDown = this._createIndicatiorElement(divYear, indicatorHeight, "-", indicatorTranslateDown);
                    var divMonthIndicatorTop = this._createIndicatiorElement(divMonth, indicatorHeight, "-", indicatorTranslateTop);
                    var divMonthIndicatorDown = this._createIndicatiorElement(divMonth, indicatorHeight, "-", indicatorTranslateDown);
                    var divDayIndicatorTop = this._createIndicatiorElement(divDay, indicatorHeight, "-", indicatorTranslateTop);
                    var divDayIndicatorDown = this._createIndicatiorElement(divDay, indicatorHeight, "-", indicatorTranslateDown);
                    this._owner.element.data('divYearIndicatorTop', divYearIndicatorTop);
                    this._owner.element.data('divMonthIndicatorTop', divMonthIndicatorTop);
                    this._owner.element.data('divDayIndicatorTop', divDayIndicatorTop);
                    this._owner.element.data('divYearIndicatorDown', divYearIndicatorDown);
                    this._owner.element.data('divMonthIndicatorDown', divMonthIndicatorDown);
                    this._owner.element.data('divDayIndicatorDown', divDayIndicatorDown);
                }

                this._initDatePickerEvent();
                this._initTouchPickerEvent("Year");
                this._initTouchPickerEvent("Month");
                this._initTouchPickerEvent("Day");
            };

            wijinputdateroller.prototype._initDatePickerEvent = function () {
                var self = this;
                var divYear = this._owner.element.data('divYear');
                var divMonth = this._owner.element.data('divMonth');
                var divDay = this._owner.element.data('divDay');

                divYear.mousewheel(function (e, arg) {
                    self._yearMouseWheel(e, arg);
                });

                divMonth.mousewheel(function (e, arg) {
                    self._monthMouseWheel(e, arg);
                });

                divDay.mousewheel(function (e, arg) {
                    self._dayMouseWheel(e, arg);
                });
            };

            //#endregion
            //#region TimePicker
            wijinputdateroller.prototype._initTimePicker = function () {
                var timePicker = this._owner.element.data('timePicker');
                if (timePicker != undefined) {
                    return;
                }

                var self = this;
                var height = this._owner.element.data('itemHeight') * 5;
                var pickerWidth = this._owner.element.data('pickerWidth');
                var itemHeight = this._owner.element.data('itemHeight') + "px";
                var indicatorHeight = this._owner.element.data('indicatorHeight') + "px";
                var indicatorTranslateTop = this._owner.element.data('indicatorTranslateTop');
                var indicatorTranslateDown = this._owner.element.data('indicatorTranslateDown');
                var indicatorTranslateSelector = this._owner.element.data('indicatorTranslateSelector');
                var indicatorTranslateContent = this._owner.element.data('indicatorTranslateContent');

                var div = this._createDivElement(document.body, pickerWidth + "px");
                var divIndicator = this._createDivIndicatiorElement(div, itemHeight, "", indicatorTranslateSelector);
                var table = this._createTableElement(div, height + "px", "-", indicatorTranslateContent);
                var trTime = $("<tr/>").appendTo(table);

                // Hour
                var tdHour = $("<td/>").css({ "width": "33%" });
                var divHour = this._createPickerDivElement(tdHour, height);
                var divHourMask = this._createMaskElement(divHour, height);
                var pickerHourArray = {};
                for (var i = 1; i <= 12; i++) {
                    var text = this._getRollText(i, this._owner.element.data('pickerTimeHourFormat'));
                    var itemDiv = this._createItemElement(i, divHourMask, itemHeight, text);
                    pickerHourArray[i - 1] = itemDiv;
                }

                //Minute
                var tdMinute = $("<td/>").css({ "width": "33%" });
                var divMinute = this._createPickerDivElement(tdMinute, height);
                var divMinuteMask = this._createMaskElement(divMinute, height);
                var pickerMinuteArray = {};
                for (var i = 0; i < 60; i++) {
                    var text = this._getRollText(i, this._owner.element.data('pickerTimeMinuteFormat'));
                    var itemDiv = this._createItemElement(i, divMinuteMask, itemHeight, text);
                    pickerMinuteArray[i] = itemDiv;
                }

                //AM
                var tdAM = $("<td/>").css({ "width": "34%" });
                var divAM = this._createPickerDivElement(tdAM, height);
                var divAMMask = this._createMaskElement(divAM, height);
                var pickerAMArray = {};
                for (var i = 0; i < 2; i++) {
                    var text = this._getRollText(i, this._owner.element.data('pickerTimeAMFormat'));
                    var itemDiv = this._createItemElement(i, divAMMask, itemHeight, text);
                    pickerAMArray[i] = itemDiv;
                }

                var pickerTimeFormat = this._owner.element.data('pickerTimeFormat');
                var hourAdded = false, minuteAdded = false, amAdded = false;
                for (var i = 0; i < pickerTimeFormat.length; i++) {
                    if ((pickerTimeFormat[i] == "h" || pickerTimeFormat[i] == "hh") && !hourAdded) {
                        tdHour.appendTo(trTime);
                        hourAdded = true;
                    }

                    if ((pickerTimeFormat[i] == "m" || pickerTimeFormat[i] == "mm") && !minuteAdded) {
                        tdMinute.appendTo(trTime);
                        minuteAdded = true;
                    }

                    if ((pickerTimeFormat[i] == "t" || pickerTimeFormat[i] == "tt") && !amAdded) {
                        tdAM.appendTo(trTime);
                        amAdded = true;
                    }
                }

                this._owner.element.data('timePicker', div);

                this._owner.element.data('divHour', divHour);
                this._owner.element.data('divMinute', divMinute);
                this._owner.element.data('divAM', divAM);

                this._owner.element.data('divHourMask', divHourMask);
                this._owner.element.data('divMinuteMask', divMinuteMask);
                this._owner.element.data('divAMMask', divAMMask);

                this._owner.element.data('pickerHourArray', pickerHourArray);
                this._owner.element.data('pickerMinuteArray', pickerMinuteArray);
                this._owner.element.data('pickerAMArray', pickerAMArray);

                if (!input.CoreUtility.IsIE8OrBelow()) {
                    var divHourIndicatorTop = this._createIndicatiorElement(divHour, indicatorHeight, "-", indicatorTranslateTop);
                    var divHourIndicatorDown = this._createIndicatiorElement(divHour, indicatorHeight, "-", indicatorTranslateDown);
                    var divMinuteIndicatorTop = this._createIndicatiorElement(divMinute, indicatorHeight, "-", indicatorTranslateTop);
                    var divMinuteIndicatorDown = this._createIndicatiorElement(divMinute, indicatorHeight, "-", indicatorTranslateDown);
                    var divAMIndicatorTop = this._createIndicatiorElement(divAM, indicatorHeight, "-", indicatorTranslateTop);
                    var divAMIndicatorDown = this._createIndicatiorElement(divAM, indicatorHeight, "-", indicatorTranslateDown);
                    this._owner.element.data('divHourIndicatorTop', divHourIndicatorTop);
                    this._owner.element.data('divMinuteIndicatorTop', divMinuteIndicatorTop);
                    this._owner.element.data('divAMIndicatorTop', divAMIndicatorTop);
                    this._owner.element.data('divHourIndicatorDown', divHourIndicatorDown);
                    this._owner.element.data('divMinuteIndicatorDown', divMinuteIndicatorDown);
                    this._owner.element.data('divAMIndicatorDown', divAMIndicatorDown);
                }

                this._initTimePickerEvent();
                this._initTouchPickerEvent("Hour");
                this._initTouchPickerEvent("Minute");
                this._initTouchPickerEvent("AM");
            };

            wijinputdateroller.prototype._initTimePickerEvent = function () {
                var self = this;
                var divHour = this._owner.element.data('divHour');
                var divMinute = this._owner.element.data('divMinute');
                var divAM = this._owner.element.data('divAM');

                divHour.mousewheel(function (e, arg) {
                    self._hourMouseWheel(e, arg);
                });

                divMinute.mousewheel(function (e, arg) {
                    self._minuteMouseWheel(e, arg);
                });

                divAM.mousewheel(function (e, arg) {
                    self._amMouseWheel(e, arg);
                });
            };

            //#endregion
            //#region Method
            wijinputdateroller.prototype._isValidatePickerFormat = function (format) {
                switch (format) {
                    case "yyyy":
                    case "M":
                    case "MM":
                    case "MMM":
                    case "MMMM":
                    case "d":
                    case "dd":
                    case "h":
                    case "hh":
                    case "m":
                    case "mm":
                    case "t":
                    case "tt":
                        return true;
                }

                return false;
            };

            wijinputdateroller.prototype._getDatePickerMinYear = function () {
                var realMinDate = this._owner._isEraFormatExist() ? this._owner._getRealEraMinDate() : this._owner._getRealMinDate();
                var minYear = realMinDate.getFullYear();
                var pickerValue = this._owner._getPickerValue();
                var year = this._owner._max(pickerValue.getFullYear() - 50, minYear);
                return year;
            };

            wijinputdateroller.prototype._getDatePickerMaxYear = function () {
                var realMaxDate = this._owner._isEraFormatExist() ? this._owner._getRealEraMaxDate() : this._owner._getRealMaxDate();
                var maxYear = realMaxDate.getFullYear();
                var pickerValue = this._owner._getPickerValue();
                var year = this._owner._min(pickerValue.getFullYear() + 50, maxYear);
                return year;
            };

            wijinputdateroller.prototype._getCorrentPickerFormat = function (formats) {
                for (var i = 0; i < formats.length - 1; i++) {
                    for (var j = i + 1; j < formats.length; j++) {
                        if (formats[j].index < formats[i].index) {
                            var tmp = formats[i];
                            formats[i] = formats[j];
                            formats[j] = tmp;
                        }
                    }
                }

                var result = "";
                for (var i = 0; i < formats.length; i++) {
                    result += formats[i].value;
                    if (i < formats.length - 1) {
                        result += ",";
                    }
                }

                return result;
            };

            wijinputdateroller.prototype._getDefaultDatePickerFormat = function () {
                var culture = this._owner._getCulture();

                if (culture == null) {
                    return "yyyy,M,d";
                }

                var cf = culture.calendars.standard;
                var pattern = cf.patterns.d;
                var y = { "index": pattern.indexOf('y'), "value": "yyyy" };
                var M = { "index": pattern.indexOf('M'), "value": "MM" };
                var d = { "index": pattern.indexOf('d'), "value": "dd" };

                if (y.index == -1 || M.index == -1 || d.index == -1) {
                    return "yyyy,M,d";
                }

                var formats = new Array();
                formats[0] = y;
                formats[1] = M;
                formats[2] = d;

                return this._getCorrentPickerFormat(formats);
            };

            wijinputdateroller.prototype._getDefaultTimePickerFormat = function () {
                if (this._owner.options.culture.length >= 2) {
                    var subString = this._owner.options.culture.substr(0, 2);
                    if (subString == 'ja' || subString == 'zh') {
                        return "tt,hh,mm";
                    }
                }

                return "hh,mm,tt";
            };

            wijinputdateroller.prototype._updateTimePicker = function () {
                var hour = this._owner.element.data("pickerHour") - 1;
                var minute = this._owner.element.data("pickerMinute");
                var am = this._owner.element.data("pickerAM");

                var divHourMask = this._owner.element.data('divHourMask');
                var divMinuteMask = this._owner.element.data('divMinuteMask');
                var divAMMask = this._owner.element.data('divAMMask');

                this._updateItemTransform("Hour", hour);
                this._updateItemTransform("Minute", minute);
                this._updateItemTransform("AM", am);

                this._scrollTheView("Hour", hour, hour, true);
                this._scrollTheView("Minute", minute, minute, true);
                this._scrollTheView("AM", am, am, true);

                this._owner.element.data('pickerHourScrollDelay', 5);
                this._owner.element.data('pickerMinuteScrollDelay', 5);
                this._owner.element.data('pickerAMScrollDelay', 5);

                this._owner.element.data('pickerHourScrollRate', 1);
                this._owner.element.data('pickerMinuteScrollRate', 1);
                this._owner.element.data('pickerAMScrollRate', 1);
            };

            wijinputdateroller.prototype._updateDatePicker = function () {
                var minYear = this._owner.element.data('pickerMinYear');
                var year = this._owner.element.data("pickerYear");
                var month = this._owner.element.data("pickerMonth");
                var day = this._owner.element.data("pickerDay");

                var maxDayCount = input.DateTimeInfo.DaysInMonth(year, month);

                this._updateItemTransform("Year", year - minYear);
                this._updateItemTransform("Month", month - 1);
                this._updateItemTransform("Day", day - 1);

                this._scrollTheView("Year", year - minYear, year - minYear, true);
                this._scrollTheView("Month", month - 1, month - 1, true);
                this._scrollTheView("Day", day - 1, day - 1, true);

                this._owner.element.data('pickerYearScrollDelay', 5);
                this._owner.element.data('pickerMonthScrollDelay', 5);
                this._owner.element.data('pickerDayScrollDelay', 5);

                this._owner.element.data('pickerYearScrollRate', 1);
                this._owner.element.data('pickerMonthScrollRate', 1);
                this._owner.element.data('pickerDayScrollRate', 1);

                this._updateDayPickerMaxCount();
            };

            wijinputdateroller.prototype._getRollText = function (index, format) {
                var culture = this._owner._getCulture();
                var text = "";
                switch (format) {
                    case "M":
                    case "h":
                        text = (index).toString();
                        break;
                    case "MM":
                    case "hh":
                        text = index < 10 ? "0" + (index).toString() : (index).toString();
                        break;
                    case "m":
                    case "d":
                    case "yyyy":
                        text = index.toString();
                        break;
                    case "mm":
                    case "dd":
                        text = index < 10 ? "0" + index.toString() : index.toString();
                        break;
                    case "t":
                        text = index == 0 ? this._owner._getStandardAMPM("AM") : this._owner._getStandardAMPM("PM");
                        text = text.substr(0, 1);
                        break;
                    case "tt":
                        text = index == 0 ? this._owner._getStandardAMPM("AM") : this._owner._getStandardAMPM("PM");
                        break;
                    case "MMM":
                        text = culture.calendars.standard.months.namesAbbr[index - 1];
                        break;
                    case "MMMM":
                        text = culture.calendars.standard.months.names[index - 1];
                        break;
                    default:
                }

                return text;
            };

            wijinputdateroller.prototype._initTouchPickerEvent = function (pickerType) {
                var div = this._owner.element.data('div' + pickerType);
                var divMask = this._owner.element.data('div' + pickerType + 'Mask');
                this._addPickerTouchEvent(divMask, pickerType);

                if (!input.CoreUtility.IsIE8OrBelow()) {
                    var divIndicatorTop = this._owner.element.data('div' + pickerType + 'IndicatorTop');
                    var divIndicatorDown = this._owner.element.data('div' + pickerType + 'IndicatorDown');
                    this._addPickerTouchEvent(divIndicatorTop, pickerType);
                    this._addPickerTouchEvent(divIndicatorDown, pickerType);
                }
            };

            wijinputdateroller.prototype._addPickerTouchEvent = function (element, pickerType) {
                var self = this;
                element.bind("touchstart", function (evt) {
                    self._touchStart(evt, pickerType);
                    evt.preventDefault();
                }).bind("touchmove", function (evt) {
                    self._touchMove(evt, pickerType);
                    evt.preventDefault();
                }).bind("touchend", function (evt) {
                    self._touchEnd(evt, pickerType);
                    evt.preventDefault();
                });
            };

            wijinputdateroller.prototype._getRollFormat = function (pickerDateFormat, format) {
                for (var i = 0; i < pickerDateFormat.length; i++) {
                    if (pickerDateFormat[i].indexOf(format) != -1) {
                        return pickerDateFormat[i];
                    }
                }

                return "";
            };

            wijinputdateroller.prototype._adjustTouchPosition = function (pickerType, newY) {
                var touchPositionArray = this._getTouchPositionArray(pickerType);
                var index = this._getItemIndexByPosition(pickerType, newY);
                var value = this._itemIndexToValue(pickerType, index);
                this._owner.element.data("picker" + pickerType, value);
                this._scrollTheViewByTouch(pickerType, touchPositionArray[index]);
            };

            wijinputdateroller.prototype._itemIndexToValue = function (pickerType, index) {
                switch (pickerType) {
                    case "Minute":
                    case "AM":
                        return index;
                    case "Hour":
                    case "Month":
                    case "Day":
                        return index + 1;
                    case "Year":
                        var minYear = this._owner.element.data('pickerMinYear');
                        return minYear + index;
                }

                return -1;
            };

            wijinputdateroller.prototype._getItemLength = function (pickerType) {
                switch (pickerType) {
                    case "Hour":
                    case "Month":
                        return 12;
                    case "Year":
                        var minYear = this._owner.element.data('pickerMinYear');
                        var maxYear = this._owner.element.data('pickerMaxYear');
                        return maxYear - minYear + 1;
                    case "Day":
                        return 31;
                    case "Minute":
                        return 60;
                    case "AM":
                        return 2;
                }

                return -1;
            };

            wijinputdateroller.prototype._updateItemTransform = function (pickerType, itemIndex) {
                if (input.CoreUtility.IsIE8OrBelow()) {
                    return;
                }

                if (itemIndex < 0) {
                    return;
                }

                var itemArray = this._owner.element.data("picker" + pickerType + "Array");
                var length = this._getItemLength(pickerType);
                var transform = "skew(0deg) scale(1.2, 1.2) translate(0px, 0px)";
                var transform1 = "skew(-5deg) scale(0.9, 0.9) translate(0px, 0px)";
                var transform2 = "skew(-10deg) scale(0.7, 0.7) translate(0px, 0px)";
                var transform3 = "skew(-15deg) scale(0.5, 0.5) translate(0px, 0px)";

                for (var i = 0; i < length; i++) {
                    if (i == itemIndex - 3) {
                        this._setCssTransform(itemArray[i], "", transform3, true);
                    } else if (i == itemIndex - 2) {
                        this._setCssTransform(itemArray[i], "", transform2, true);
                    } else if (i == itemIndex - 1) {
                        this._setCssTransform(itemArray[i], "", transform1, true);
                    } else if (i == itemIndex) {
                        this._setCssTransform(itemArray[i], "", transform, true);
                    } else if (i == itemIndex + 1) {
                        this._setCssTransform(itemArray[i], "", transform1, true);
                    } else if (i == itemIndex + 2) {
                        this._setCssTransform(itemArray[i], "", transform2, true);
                    } else if (i == itemIndex + 3) {
                        this._setCssTransform(itemArray[i], "", transform3, true);
                    } else {
                        this._setCssTransform(itemArray[i], "", "", true);
                    }
                }
            };

            wijinputdateroller.prototype._updateDayPickerMaxCount = function () {
                var year = this._owner.element.data("pickerYear");
                var month = this._owner.element.data("pickerMonth");
                var day = this._owner.element.data("pickerDay");

                var maxDayCount = input.DateTimeInfo.DaysInMonth(year, month);
                this._owner.element.data('pickerDayMaxCount', maxDayCount);

                var pickerDayArray = this._owner.element.data('pickerDayArray');

                for (var i = 29; i <= 31; i++) {
                    var display = i > maxDayCount ? "none" : "";
                    pickerDayArray[i - 1].css("display", display);
                }

                if (day > maxDayCount) {
                    var divDayMask = this._owner.element.data('divDayMask');
                    day = maxDayCount;
                    this._updateItemTransform("Day", day - 1);
                    this._scrollTheView("Day", day - 1, null, false);
                    this._owner.element.data("pickerDay", day);
                }
            };

            wijinputdateroller.prototype._getTouchPositionArray = function (pickerType) {
                var positionArray = {};
                var itemHeight = this._owner.element.data('itemHeight');
                var length = this._getItemLength(pickerType);

                for (var i = 0; i < length; i++) {
                    positionArray[i] = (2 - i) * itemHeight;
                }

                return positionArray;
            };

            wijinputdateroller.prototype._getItemIndexByPosition = function (pickerType, newY) {
                var touchPositionArray = this._getTouchPositionArray(pickerType);
                var length = this._getItemLength(pickerType);

                if (pickerType == "Day") {
                    if (length > this._owner.element.data('pickerDayMaxCount')) {
                        length = this._owner.element.data('pickerDayMaxCount');
                    }
                }

                var index = -1;
                for (var i = 0; i < length; i++) {
                    if (i == 0) {
                        if (newY > touchPositionArray[i]) {
                            index = 0;
                            break;
                        }
                    } else {
                        if (newY <= touchPositionArray[i - 1] && newY >= touchPositionArray[i]) {
                            var offsetTop = touchPositionArray[i - 1] - newY;
                            var offsetBottom = newY - touchPositionArray[i];
                            index = offsetTop > offsetBottom ? i : i - 1;
                            break;
                        }
                    }

                    if (i == length - 1) {
                        if (newY < touchPositionArray[i]) {
                            index = i;
                            break;
                        }
                    }
                }

                return index;
            };

            wijinputdateroller.prototype._hideItemInIE7 = function (pickerType, pickerScrollCurrent) {
                if (!input.CoreUtility.IsIE7()) {
                    return;
                }

                var lastItemIndex = this._owner.element.data('picker' + pickerType + 'LastItemIndex');
                var itemIndex = this._getItemIndexByPosition(pickerType, pickerScrollCurrent);
                if (itemIndex == lastItemIndex) {
                    return;
                }

                var minItemIndex = itemIndex - 2;
                var maxItemIndex = itemIndex + 2;
                var itemArray = this._owner.element.data("picker" + pickerType + "Array");
                var length = this._getItemLength(pickerType);

                for (var i = 0; i < length; i++) {
                    if (i >= minItemIndex && i <= maxItemIndex) {
                        itemArray[i].css("visibility", "");
                    } else {
                        itemArray[i].css("visibility", "hidden");
                    }
                }

                this._owner.element.data('picker' + pickerType + 'LastItemIndex', itemIndex);
            };

            wijinputdateroller.prototype._scrollTheView = function (pickerType, newValue, oldValue, ignoreScroll) {
                var itemHeight = this._owner.element.data('itemHeight');
                var newOffset = (2 - newValue) * itemHeight;
                this._owner.element.data('picker' + pickerType + 'ScrollTo', newOffset);
                if (ignoreScroll == true) {
                    var divMask = this._owner.element.data('div' + pickerType + 'Mask');
                    var pickerScrollCurrent = newOffset;
                    this._setCssTransform(divMask, "", pickerScrollCurrent, false);
                    this._hideItemInIE7(pickerType, pickerScrollCurrent);
                    this._owner.element.data('picker' + pickerType + 'ScrollCurrent', pickerScrollCurrent);
                } else {
                    this._scrollPicker(pickerType);
                }
            };

            wijinputdateroller.prototype._scrollPicker = function (pickerType) {
                var divMask = this._owner.element.data('div' + pickerType + 'Mask');
                var pickerScrollTo = this._owner.element.data('picker' + pickerType + 'ScrollTo');
                var pickerScrollCurrent = this._owner.element.data('picker' + pickerType + 'ScrollCurrent');
                var pickerScrollDelay = this._owner.element.data('picker' + pickerType + 'ScrollDelay');

                if (pickerScrollCurrent == undefined) {
                    pickerScrollCurrent = pickerScrollTo;
                    this._setCssTransform(divMask, "", pickerScrollCurrent, false);
                    this._owner.element.data('picker' + pickerType + 'ScrollCurrent', pickerScrollCurrent);
                }

                if (pickerScrollTo == pickerScrollCurrent || pickerScrollCurrent == undefined) {
                    return false;
                }

                pickerScrollCurrent += pickerScrollTo > pickerScrollCurrent ? 1 : -1;
                var transform = "translate(0," + pickerScrollCurrent + "px) ";
                this._setCssTransform(divMask, "", pickerScrollCurrent, false);
                this._hideItemInIE7(pickerType, pickerScrollCurrent);
                this._owner.element.data('picker' + pickerType + 'ScrollCurrent', pickerScrollCurrent);

                var self = this;
                setTimeout(function () {
                    self._scrollPicker(pickerType);
                }, pickerScrollDelay);

                return true;
            };

            wijinputdateroller.prototype._scrollTheViewByTouch = function (pickerType, clientY) {
                var itemHeight = this._owner.element.data('itemHeight');
                var pickerScrollCurrent = this._owner.element.data('picker' + pickerType + 'ScrollCurrent');
                var pickerScrollTo = this._owner.element.data('picker' + pickerType + 'ScrollTo');
                this._owner.element.data('picker' + pickerType + 'ScrollTo', clientY);
                this._scrollPickerByTouch(pickerType);
            };

            wijinputdateroller.prototype._scrollPickerByTouch = function (pickerType) {
                var divMask = this._owner.element.data('div' + pickerType + 'Mask');
                var pickerScrollTo = this._owner.element.data('picker' + pickerType + 'ScrollTo');
                var pickerScrollCurrent = this._owner.element.data('picker' + pickerType + 'ScrollCurrent');

                if (pickerScrollCurrent == undefined) {
                    pickerScrollCurrent = pickerScrollTo;
                    this._setCssTransform(divMask, "", pickerScrollCurrent, false);
                    this._owner.element.data('picker' + pickerType + 'ScrollCurrent', pickerScrollCurrent);
                }

                if (pickerScrollTo == pickerScrollCurrent) {
                    this._owner.element.data('picker' + pickerType + 'ScrollRate', 1);
                    this._owner.element.data('picker' + pickerType + 'ScrollDelay', 5);
                    this._owner.element.data('touchQuickScroll', false);
                    if (pickerType == "Month" || pickerType == "Year") {
                        this._updateDayPickerMaxCount();
                    } else if (pickerType == "Hour") {
                        var itemIndex = this._getItemIndexByPosition(pickerType, pickerScrollCurrent);
                        var am = this._owner.element.data("pickerAM");

                        if (itemIndex == 11) {
                            if (am == 0) {
                                am = 1;
                                this._updateItemTransform("AM", am);
                                this._scrollTheView("AM", am, 0, false);
                                this._owner.element.data("pickerAM", am);
                            }
                        } else {
                            if (am == 1) {
                                am = 0;
                                this._updateItemTransform("AM", am);
                                this._scrollTheView("AM", am, 1, false);
                                this._owner.element.data("pickerAM", am);
                            }
                        }
                    }

                    return false;
                }

                var itemHeight = this._owner.element.data('itemHeight');
                var scrollDelay = this._owner.element.data('picker' + pickerType + 'ScrollDelay');
                var scrollRate = this._owner.element.data('picker' + pickerType + 'ScrollRate');
                var offset = Math.abs(pickerScrollTo - pickerScrollCurrent);
                var rate = offset > scrollRate ? scrollRate : offset;

                if (this._owner.element.data('touchQuickScroll') == true) {
                    if (offset < itemHeight) {
                        scrollDelay = 80;
                    } else if (offset < itemHeight * 2) {
                        scrollDelay = 50;
                    } else if (offset < itemHeight * 5) {
                        scrollDelay = 30;
                    } else if (offset < itemHeight * 8) {
                        scrollDelay = 20;
                    } else if (offset < itemHeight * 10) {
                        scrollDelay = 10;
                    }

                    this._owner.element.data('picker' + pickerType + 'ScrollDelay', scrollDelay);
                }

                pickerScrollCurrent += pickerScrollTo > pickerScrollCurrent ? rate : -1 * rate;
                this._setCssTransform(divMask, "", pickerScrollCurrent, false);
                this._owner.element.data('picker' + pickerType + 'ScrollCurrent', pickerScrollCurrent);

                var itemIndex = this._getItemIndexByPosition(pickerType, pickerScrollCurrent);
                var lastItemIndex = this._owner.element.data('picker' + pickerType + 'LastItemIndex');
                if (itemIndex != lastItemIndex) {
                    this._updateItemTransform(pickerType, itemIndex);
                }
                this._owner.element.data('picker' + pickerType + 'LastItemIndex', lastItemIndex);

                var self = this;
                setTimeout(function () {
                    self._scrollPickerByTouch(pickerType);
                }, scrollDelay);

                return true;
            };

            //#endregion
            //#region Event
            wijinputdateroller.prototype._touchStart = function (evt, pickerType) {
                var touch = evt.originalEvent.touches[0] || evt.originalEvent.changedTouches[0];
                var clientY = touch.clientY;

                this._owner.element.data("touch" + pickerType + "StartY", clientY);
                this._owner.element.data("touch" + pickerType + "BaseY", this._owner.element.data('picker' + pickerType + 'ScrollCurrent'));
                this._owner.element.data("touch" + pickerType + "Started", true);
                this._owner.element.data("touchStartTime", new Date());

                var pickerScrollCurrent = this._owner.element.data('picker' + pickerType + 'ScrollCurrent');
                this._owner.element.data('picker' + pickerType + 'ScrollTo', pickerScrollCurrent);
            };

            wijinputdateroller.prototype._touchMove = function (evt, pickerType) {
                if (!this._owner._allowEdit()) {
                    return;
                }

                if (this._owner.element.data("touch" + pickerType + "Started") != true) {
                    return;
                }

                var touch = evt.originalEvent.touches[0] || evt.originalEvent.changedTouches[0];
                var clientY = touch.clientY;

                var touchStartY = this._owner.element.data("touch" + pickerType + "StartY");
                var touchBaseY = this._owner.element.data("touch" + pickerType + "BaseY");
                var newY = touchBaseY + clientY - touchStartY;

                this._scrollTheViewByTouch(pickerType, newY);
            };

            wijinputdateroller.prototype._touchEnd = function (evt, pickerType) {
                var touch = evt.originalEvent.touches[0] || evt.originalEvent.changedTouches[0];
                var touchStartY = this._owner.element.data("touch" + pickerType + "StartY");
                var touchBaseY = this._owner.element.data("touch" + pickerType + "BaseY");
                var offset = touch.clientY - touchStartY;
                var newY = touchBaseY + offset;

                if (Math.abs(offset) < 10) {
                    var pickerScrollCurrent = this._owner.element.data('picker' + pickerType + 'ScrollCurrent');
                    this._owner.element.data('picker' + pickerType + 'ScrollTo', pickerScrollCurrent);
                    this._adjustTouchPosition(pickerType, pickerScrollCurrent);
                    return;
                }

                this._owner.element.data("touch" + pickerType + "StartY", -1);
                this._owner.element.data("touch" + pickerType + "BaseY", -1);
                this._owner.element.data("touch" + pickerType + "Started", false);

                var now = new Date();
                var offsetTime = now - this._owner.element.data("touchStartTime");
                if (offsetTime < 200) {
                    var itemHeight = this._owner.element.data("itemHeight") * 5;
                    var negative = offset < 0 ? -1 : 1;
                    offset = offset * 4;
                    offset = Math.abs(offset) < itemHeight ? negative * itemHeight : offset;
                    newY += offset;
                    this._owner.element.data("touchQuickScroll", true);
                    this._owner.element.data('picker' + pickerType + 'ScrollRate', 3);
                }

                this._adjustTouchPosition(pickerType, newY);
            };

            wijinputdateroller.prototype._yearMouseWheel = function (e, arg) {
                if (!this._owner._allowEdit()) {
                    return;
                }

                if (isNaN(arg)) {
                    return;
                }

                var minYear = this._owner.element.data("pickerMinYear");
                var maxYear = this._owner.element.data("pickerMaxYear");
                var year = this._owner.element.data("pickerYear");
                var oldYear = this._owner.element.data("pickerYear");

                year -= arg;
                year = year < minYear ? minYear : year;
                year = year > maxYear ? maxYear : year;

                this._updateItemTransform("Year", year - minYear);
                this._scrollTheView("Year", year - minYear, oldYear - minYear, false);
                this._owner.element.data("pickerYear", year);
                this._updateDayPickerMaxCount();
                if (e.preventDefault) {
                    e.preventDefault();
                }
            };

            wijinputdateroller.prototype._monthMouseWheel = function (e, arg) {
                if (!this._owner._allowEdit()) {
                    return;
                }

                if (isNaN(arg)) {
                    return;
                }

                var month = this._owner.element.data("pickerMonth");
                var oldMonth = this._owner.element.data("pickerMonth");

                month -= arg;
                month = month < 1 ? 1 : month;
                month = month > 12 ? 12 : month;

                this._updateItemTransform("Month", month - 1);
                this._scrollTheView("Month", month - 1, oldMonth, false);
                this._owner.element.data("pickerMonth", month);
                this._updateDayPickerMaxCount();
                if (e.preventDefault) {
                    e.preventDefault();
                }
            };

            wijinputdateroller.prototype._dayMouseWheel = function (e, arg) {
                if (!this._owner._allowEdit()) {
                    return;
                }

                if (isNaN(arg)) {
                    return;
                }

                var maxDayCount = this._owner.element.data('pickerDayMaxCount');
                var oldDay = this._owner.element.data("pickerDay");

                var day = this._owner.element.data("pickerDay");
                day -= arg;
                day = day < 1 ? 1 : day;
                day = day > maxDayCount ? maxDayCount : day;

                this._updateItemTransform("Day", day - 1);
                this._scrollTheView("Day", day - 1, oldDay - 1, false);
                this._owner.element.data("pickerDay", day);
                if (e.preventDefault) {
                    e.preventDefault();
                }
            };

            wijinputdateroller.prototype._hourMouseWheel = function (e, arg) {
                if (!this._owner._allowEdit()) {
                    return;
                }

                if (isNaN(arg)) {
                    return;
                }

                var oldHour = this._owner.element.data("pickerHour");
                var hour = this._owner.element.data("pickerHour");
                var lastHour = hour;

                hour -= arg;
                hour = hour < 1 ? 1 : hour;
                hour = hour > 12 ? 12 : hour;

                var am = this._owner.element.data("pickerAM");
                if (hour == 12) {
                    if (am == 0) {
                        am = 1;
                        this._updateItemTransform("AM", am);
                        this._scrollTheView("AM", am, 0, false);
                        this._owner.element.data("pickerAM", am);
                    }
                } else if (lastHour == 12) {
                    if (am == 1) {
                        am = 0;
                        this._updateItemTransform("AM", am);
                        this._scrollTheView("AM", am, 1, false);
                        this._owner.element.data("pickerAM", am);
                    }
                }

                this._updateItemTransform("Hour", hour - 1);
                this._scrollTheView("Hour", hour - 1, oldHour - 1, false);
                this._owner.element.data("pickerHour", hour);
                if (e.preventDefault) {
                    e.preventDefault();
                }
            };

            wijinputdateroller.prototype._minuteMouseWheel = function (e, arg) {
                if (!this._owner._allowEdit()) {
                    return;
                }

                if (isNaN(arg)) {
                    return;
                }

                var oldMinute = this._owner.element.data("pickerMinute");
                var minute = this._owner.element.data("pickerMinute");
                minute -= arg;
                minute = minute < 0 ? 0 : minute;
                minute = minute > 59 ? 59 : minute;

                this._updateItemTransform("Minute", minute);
                this._scrollTheView("Minute", minute, oldMinute, false);
                this._owner.element.data("pickerMinute", minute);
                if (e.preventDefault) {
                    e.preventDefault();
                }
            };

            wijinputdateroller.prototype._amMouseWheel = function (e, arg) {
                if (!this._owner._allowEdit()) {
                    return;
                }

                if (isNaN(arg)) {
                    return;
                }

                var oldAM = $(e.currentTarget).data('pickerAM');
                var am = this._owner.element.data("pickerAM");

                am -= arg;
                am = am < 0 ? 0 : am;
                am = am > 1 ? 1 : am;

                this._updateItemTransform("AM", am);
                this._scrollTheView("AM", am, oldAM, false);
                this._owner.element.data("pickerAM", am);
                if (e.preventDefault) {
                    e.preventDefault();
                }
            };

            //#endregion
            //#region CreateElement
            wijinputdateroller.prototype._createDivElement = function (container, width) {
                var div = $("<div/>").appendTo(container).css({ "width": width + "px", "display": "block", "left": "", "top": "", "position": "" }).bind("touchstart", function (evt) {
                    evt.preventDefault();
                }).bind("touchmove", function (evt) {
                    evt.preventDefault();
                });

                return div;
            };

            wijinputdateroller.prototype._createDivIndicatiorElement = function (div, height, prefix, transform) {
                var indicator = $("<div/>").appendTo(div).css({ "height": height, "opacity": "0.5", "lineHeight": height, "margin": "0px", "cursor": "default" }).attr("class", "ui-state-active");
                this._setCssTransform(indicator, prefix, transform, false);
                return indicator;
            };

            wijinputdateroller.prototype._createIndicatiorElement = function (div, height, prefix, transform) {
                var indicator = $("<div/>").appendTo(div).css({ "height": height, "opacity": "0.5", "lineHeight": height, "border-width": "0px", "cursor": "default" }).attr("class", "ui-widget-content");
                this._setCssTransform(indicator, prefix, transform, false);
                return indicator;
            };

            wijinputdateroller.prototype._setCssTransform = function (element, prefix, transform, setDirect) {
                var newTransform = transform;

                if (!setDirect) {
                    newTransform = "translate(0, " + prefix + transform + "px)";
                }

                element.css("position", "");
                element.css("top", "");

                if (input.CoreUtility.IsIE8OrBelow()) {
                    element.css("position", "relative");
                    element.css("top", prefix + transform + "px");
                } else if (input.CoreUtility.IsIE9()) {
                    element.css("-ms-transform", newTransform);
                } else {
                    element.css("transform", newTransform);
                }
            };

            wijinputdateroller.prototype._createTableElement = function (div, height, prefix, transform) {
                var table = $("<table/>").appendTo(div).css({ "width": "100%", "height": height + "px" }).attr({ "cellspacing": "0px", "cellpadding": "0px" });

                this._setCssTransform(table, prefix, transform, false);

                return table;
            };

            wijinputdateroller.prototype._createItemElement = function (index, div, height, text) {
                var item = $("<div/>").appendTo(div).css({ "height": height, "lineHeight": height, "cursor": "default" }).html(text).data("rollValue", index);

                return item;
            };

            wijinputdateroller.prototype._createPickerDivElement = function (div, height) {
                var pickerDiv = $("<div/>").appendTo(div).css({ "height": height, "border": "0px", "text-align": "center", "overflow": "hidden", "background": "transparent" });

                return pickerDiv;
            };

            wijinputdateroller.prototype._createMaskElement = function (div, height) {
                var mask = $("<div/>").appendTo(div).css({ "height": height });

                return mask;
            };
            return wijinputdateroller;
        })();
        input.wijinputdateroller = wijinputdateroller;
    })(wijmo.input || (wijmo.input = {}));
    var input = wijmo.input;
})(wijmo || (wijmo = {}));
;
/// <reference path="jquery.wijmo.wijstringinfo.ts"/>
/// <reference path="jquery.wijmo.wijinputcore.ts"/>
/// <reference path="../wijcalendar/jquery.wijmo.wijcalendar.ts"/>
/// <reference path="jquery.wijmo.wijinputdateformat.ts"/>
/// <reference path="jquery.wijmo.wijinputdateroller.ts"/>
/// <reference path="../wijtabs/jquery.wijmo.wijtabs.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*globals  wijDateTextProvider wijinputcore wijInputResult window document Globalize jQuery*/
    /*
    * Depends:
    *	jquery-1.4.2.js
    *	jquery.ui.core.js
    *	jquery.ui.widget.js
    *	jquery.ui.position.js
    *	jquery.effects.core.js
    *	jquery.effects.blind.js
    *	globalize.js
    *	jquery.mousewheel.js
    *	jquery.wijmo.wijpopup.js
    *	jquery.wijmo.wijcalendar.js
    *	jquery.wijmo.wijcharex.js
    *	jquery.wijmo.wijstringinfo.js
    *	jquery.wijmo.wijinputcore.js
    *  jquery.wijmo.wijinputdateformat.js
    *  jquery.wijmo.wijtabs.js
    *
    */
    (function (input) {
        var $ = jQuery, jqKeyCode = wijmo.getKeyCodeEnum();

        //	var wijdigits = {
        //		useDefault: -2,
        //		asIs: -1,
        //		zero: 0,
        //		one: 1,
        //		two: 2,
        //		three: 3,
        //		four: 4,
        //		five: 5,
        //		six: 6,
        //		seven: 7,
        //		eight: 8
        //	}
        /** @widget */
        var wijinputdate = (function (_super) {
            __extends(wijinputdate, _super);
            function wijinputdate() {
                _super.apply(this, arguments);
            }
            wijinputdate.prototype._create = function () {
                if (input.CoreUtility.chrome) {
                    this.element.attr("type", "text");
                }
                this.element.uniqueId();
                this._id = this.element.attr("id");

                this._wijinputdateroller = null;
                if (typeof (input.wijinputdateroller) !== "undefined") {
                    this._wijinputdateroller = new input.wijinputdateroller(this);
                }

                _super.prototype._create.call(this);

                this.element.attribute("aria-label", "wijinputdate");
                this.element.attr("role", "spinbutton");
            };

            wijinputdate.prototype._createTextProvider = function () {
                this._textProvider = new wijDateTextProvider(this, this.options.dateFormat, this.options.displayFormat);
            };

            wijinputdate.prototype._strToDate = function (str) {
                return this._textProvider.parseDate(str);
            };

            wijinputdate.prototype._beginUpdate = function () {
                var strDate, date = null;
                _super.prototype._beginUpdate.call(this);

                if (this.options.minDate) {
                    if (typeof this.options.minDate === 'string') {
                        var minDate = new Date(this.options.minDate);
                        if (isNaN(minDate.getTime())) {
                            minDate = this._strToDate(this.options.minDate);
                        }
                        this.options.minDate = minDate;
                    }
                }

                if (this.options.maxDate) {
                    if (typeof this.options.maxDate === 'string') {
                        var maxDate = new Date(this.options.maxDate);
                        if (isNaN(maxDate.getTime())) {
                            maxDate = this._strToDate(this.options.maxDate);
                        }
                        this.options.maxDate = maxDate;
                    }
                }

                if (this.options.date === undefined) {
                    if (!!this.element.data('elementValue')) {
                        strDate = this.element.data('elementValue');
                    }
                } else {
                    if (typeof this.options.date === 'string') {
                        strDate = this.options.date;
                    } else {
                        date = this.options.date;
                    }
                }

                if (this.options.date === undefined) {
                    this.options.date = new Date();
                }

                if (strDate) {
                    date = new Date(strDate);
                    if (isNaN(date.getTime())) {
                        date = this._strToDate(strDate);
                    }
                }

                if (date == null) {
                    date = this.options.date;
                }

                this._safeSetDate(date);

                var culture = this._getCulture();
                if (culture != null) {
                    if (this.options.amDesignator == "") {
                        this.options.amDesignator = this._getStandardAMPM("AM");
                    }
                    if (this.options.pmDesignator == "") {
                        this.options.pmDesignator = this._getStandardAMPM("PM");
                    }
                }

                this.element.data({
                    defaultDate: date === null ? date : new Date(date.getTime()),
                    preDate: date === null ? date : new Date(date.getTime())
                });

                this._resetTimeStamp();
                this._initPicker();

                if (this.options.calendar) {
                    var calendar = this.element.data('calendar');
                    if (calendar) {
                        calendar.wijcalendar("option", this.options.calendar);
                    }
                }

                this.element.addClass(this.options.wijCSS.wijinputdate).attribute({
                    'aria-valuemin': new Date(1900, 1, 1).getTime(),
                    'aria-valuemax': new Date(2099, 1, 1).getTime()
                });
                if (this.options.date instanceof Date === true) {
                    this.element.attribute('aria-valuenow', this.options.date.getTime());
                }
            };

            wijinputdate.prototype._endUpdate = function () {
                var _this = this;
                _super.prototype._endUpdate.call(this);
                this.element.bind("click.wijinput", function () {
                    if (!_this._allowEdit()) {
                        return;
                    }

                    var oldActiveField = _this.options.activeField;
                    var range = _this.element.wijtextselection();
                    _this._updateText();
                    try  {
                        _this.element.wijtextselection(range);
                    } catch (e) {
                    }

                    if (_this.element.data('ignoreHighLight') != true) {
                        _this._highLightCursor();
                    }

                    if (input.CoreUtility.chrome) {
                        if (_this.element.data('needResoteActiveField') == true) {
                            _this._setOption('activeField', oldActiveField);
                        }
                    }

                    _this.element.data('ignoreHighLight', false);
                });
            };

            wijinputdate.prototype._getInnerNullText = function () {
                if (this.options.placeholder != null) {
                    return this.options.placeholder;
                }

                if (this.options.showNullText) {
                    return this.options.nullText;
                }

                return null;
            };

            wijinputdate.prototype._getInnerAmDesignator = function () {
                return this.options.amDesignator == "" ? this._getStandardAMPM("AM") : this.options.amDesignator;
            };

            wijinputdate.prototype._getInnerPmDesignator = function () {
                return this.options.pmDesignator == "" ? this._getStandardAMPM("PM") : this.options.pmDesignator;
            };

            wijinputdate.prototype._getInnerIncrement = function () {
                var increment = Number(this.options.increment);
                if (isNaN(increment)) {
                    increment = 1;
                }
                return increment;
            };

            wijinputdate.prototype._getAllowSpinLoop = function () {
                return !!this.options.allowSpinLoop;
            };

            wijinputdate.prototype._getRealMaxDate = function () {
                return this.options.maxDate ? this.options.maxDate : new Date(9999, 11, 31, 23, 59, 59);
            };

            wijinputdate.prototype._getRealMinDate = function () {
                if (this.options.minDate) {
                    return this.options.minDate;
                }

                var minDate = new Date(1, 0, 1, 0, 0, 0);
                minDate.setFullYear(1);

                return minDate;
            };

            wijinputdate.prototype._getRealEraMaxDate = function () {
                if (this.options.maxDate) {
                    return input.DateTimeInfo.GetEraMax() < this.options.maxDate ? input.DateTimeInfo.GetEraMax() : this.options.maxDate;
                }

                return input.DateTimeInfo.GetEraMax();
            };

            wijinputdate.prototype._getRealEraMinDate = function () {
                if (this.options.minDate) {
                    return input.DateTimeInfo.GetEraMin() > this.options.minDate ? input.DateTimeInfo.GetEraMin() : this.options.minDate;
                }

                return input.DateTimeInfo.GetEraMin();
            };

            wijinputdate.prototype._isEraFormatExist = function () {
                return this._textProvider._isEraFormatExist();
            };

            wijinputdate.prototype._checkDate = function () {
                var oldDate = this.options.date;
                var newDate = this._checkRange(this.options.date);
                if (!input.DateTimeInfo.Equal(oldDate, newDate)) {
                    this._setOption("date", newDate);
                    this._trigger('valueBoundsExceeded', null);
                }
            };

            wijinputdate.prototype._checkRange = function (date) {
                if (date) {
                    if (this.options.minDate && date < this.options.minDate) {
                        date = new Date(Math.max(this.options.minDate, date));
                    }

                    if (this.options.maxDate && date > this.options.maxDate) {
                        date = new Date(Math.min(this.options.maxDate, date));
                    }
                }

                return date;
            };

            wijinputdate.prototype._safeSetDate = function (date, ignoreCheckRange) {
                var cache = date;

                if (!ignoreCheckRange) {
                    date = this._checkRange(date);
                }

                if (isNaN(date)) {
                    date = cache;
                }

                this.options.date = date;
                return true;
            };

            wijinputdate.prototype._safeGetDate = function (ignoreCheckRange) {
                var date = this.options.date;
                if (date == null) {
                    date = new Date();
                }
                if (!ignoreCheckRange) {
                    date = this._checkRange(date);
                }
                return date;
            };

            wijinputdate.prototype._setOption = function (key, value) {
                _super.prototype._setOption.call(this, key, value);

                switch (key) {
                    case 'calendar':
                        var calendar = this.element.data('calendar');
                        if (calendar) {
                            calendar.wijcalendar("option", value);
                        }
                        break;
                    case 'pickers':
                        this._reInitPicker();
                        break;
                    case 'minDate':
                    case 'maxDate':
                        if (typeof this.options[key] === 'string') {
                            var tmpDate = this._strToDate(value);
                            tmpDate = tmpDate === null ? new Date(value) : tmpDate;
                            this.options[key] = tmpDate;
                        }
                        var date = this.options.date;
                        if (date === null) {
                            date = new Date();
                        }

                        var minDate = this._getRealMinDate();
                        var maxDate = this._getRealMaxDate();

                        if (date < minDate || date > maxDate) {
                            this._safeSetDate(date);
                        }

                        this._updateText();
                        this._highLightField();
                        break;
                    case 'date':
                        if (!!value) {
                            if (typeof value === "string") {
                                var tmpValue = this._strToDate(value);
                                value = tmpValue === null ? new Date(value) : tmpValue;
                            } else if (typeof value === "object") {
                                value = new Date(value.getTime());
                            } else {
                                value = new Date(value);
                            }

                            if (isNaN(value)) {
                                value = new Date();
                            }
                        }
                        this._safeSetDate(value);
                        this._updateText();
                        this._highLightField();
                        break;
                    case 'midnightAs0':
                    case 'hour12As0':
                    case 'amDesignator':
                    case 'pmDesignator':
                    case 'promptChar':
                        this._updateText();
                        this._highLightField();
                        break;
                    case 'culture':
                    case 'cultureCalendar':
                        this._textProvider._setFormat(this.options.dateFormat);
                        var displayFormat = this.options.displayFormat == "" ? this.options.dateFormat : this.options.displayFormat;
                        this._textProvider._setDisplayFormat(displayFormat);

                        this.options.amDesignator = this._getStandardAMPM("AM");
                        this.options.pmDesignator = this._getStandardAMPM("PM");

                        this._updateText();
                        var calendar = this.element.data('calendar');
                        if (calendar) {
                            calendar.wijcalendar("option", key, value);
                        }

                        this._reInitPicker();
                        break;
                    case 'dateFormat':
                        this._textProvider._setFormat(this.options.dateFormat);
                        if (this.options.displayFormat == "") {
                            this._textProvider._setDisplayFormat(this.options.dateFormat);
                        }

                        if (this._isEraFormatExist() && this.options.date != null) {
                            var minYear = this._getRealEraMinDate();
                            var maxYear = this._getRealEraMaxDate();

                            if (this.options.date < minYear) {
                                this._setOption("date", minYear);
                            } else if (this.options.date > maxYear) {
                                this._setOption("date", maxYear);
                            }
                        }

                        this._updateText();

                        // update the calendar 's culture
                        var calendar = this.element.data('calendar');
                        if (calendar) {
                            calendar.wijcalendar("option", key, value);
                        }
                        this._reInitPicker();
                        break;
                    case 'displayFormat':
                        var displayFormat = this.options.displayFormat == "" ? this.options.dateFormat : this.options.displayFormat;
                        this._textProvider._setDisplayFormat(displayFormat);
                        this._updateText();
                        break;
                    case 'activeField':
                        value = Math.min(value, this._textProvider.getFieldCount() - 1);
                        value = Math.max(value, 0);
                        this.options.activeField = value;
                        this._checkDate();
                        if (this.element.data('ignoreHighLight') != true) {
                            this._highLightField();
                        }
                        this._resetTimeStamp();
                        break;

                    case 'nextTooltip':
                    case 'prevTooltip':
                    case 'titleFormat':
                    case 'toolTipFormat':
                        // update the calendar 's tooltip
                        var calendar = this.element.data('calendar', calendar);
                        if (calendar) {
                            calendar.wijcalendar("option", key, value);
                        }
                        break;
                    case "comboItems":
                        this._reInitPicker();
                        break;
                }
            };

            wijinputdate.prototype._setData = function (val) {
                this.option('date', val);
            };

            wijinputdate.prototype._resetData = function () {
                var d = this.element.data('defaultDate');
                if (d === undefined || d === null) {
                    if (this.options.date !== null) {
                        d = this.element.data('elementValue');
                        if (d !== undefined && d !== null && d !== "") {
                            this.setText(d);
                        } else {
                            this._setData(null);
                        }
                    }
                } else {
                    this._setData(d);
                }
            };

            wijinputdate.prototype._resetTimeStamp = function () {
                this.element.data('cursorPos', 0);
                this.element.data('timeStamp', new Date('1900/1/1'));
                this.element.data("lastInputChar", "");
            };

            /** Gets the text value when the container form is posted back to server.
            */
            wijinputdate.prototype.getPostValue = function () {
                if (!this._isInitialized()) {
                    return this.element.val();
                }
                if (_super.prototype._showNullText.call(this) && this.isDateNull()) {
                    return "";
                }

                var val = this._textProvider.toString();
                if (val === this.options.nullText) {
                    return "";
                }

                return val;
            };

            wijinputdate.prototype._highLightAllField = function () {
                if (this.isFocused()) {
                    var range = this._textProvider.getAllRange();
                    if (range) {
                        try  {
                            this.element.wijtextselection(range);
                        } catch (e) {
                        }
                    }
                }
            };

            wijinputdate.prototype._highLightField = function (index) {
                if (typeof index === "undefined") { index = this.options.activeField; }
                if (this.isFocused()) {
                    var range = this._textProvider.getFieldRange(index);
                    if (range) {
                        try  {
                            this.element.wijtextselection(range);
                        } catch (e) {
                        }
                    }
                }
            };

            wijinputdate.prototype._highLightCursor = function (pos) {
                if (this._isNullText()) {
                    return;
                }

                if (pos === undefined) {
                    pos = Math.max(0, this.element.wijtextselection().start);
                }

                var index = this._textProvider.getCursorField(pos);
                if (index < 0) {
                    return;
                }
                this._setOption('activeField', index);
            };

            wijinputdate.prototype._toNextField = function () {
                this._setOption('activeField', this.options.activeField + 1);
            };

            wijinputdate.prototype._toPrevField = function () {
                this._setOption('activeField', this.options.activeField - 1);
            };

            wijinputdate.prototype._toFirstField = function () {
                this._setOption('activeField', 0);
            };

            wijinputdate.prototype._toLastField = function () {
                this._setOption('activeField', this._textProvider.getFieldCount());
            };

            wijinputdate.prototype._clearField = function (index) {
                if (typeof index === "undefined") { index = this.options.activeField; }
                var range = this._textProvider.getFieldRange(index), rh, self = this;
                if (range) {
                    rh = new input.wijInputResult();
                    this._textProvider.removeAt(range.start, range.end, rh);
                    this._updateText();
                    window.setTimeout(function () {
                        self._highLightField();
                    }, 1);
                }
            };

            /** Performs spin up by the active field and increment value.
            */
            wijinputdate.prototype.spinUp = function () {
                this._doSpin(true, false);
            };

            /** Performs spin down by the active field and increment value.
            */
            wijinputdate.prototype.spinDown = function () {
                this._doSpin(false, false);
            };

            /** Open the dropdown window.
            */
            wijinputdate.prototype.drop = function () {
                _super.prototype._onTriggerClicked.call(this);
            };

            /** Set the focus to the widget.
            */
            wijinputdate.prototype.focus = function () {
                _super.prototype.focus.call(this);
                this._addState('focus', this.outerDiv);
                this._updateText();
                if (this.options.highlightText == "all") {
                    this._highLightAllField();
                    this._setOption('activeField', 0);
                } else {
                    this._highLightField();
                }
            };

            /** Determines whether the date is a null value.
            */
            wijinputdate.prototype.isDateNull = function () {
                return this.options.date === null || this.options.date === undefined;
            };

            wijinputdate.prototype._min = function (value1, value2) {
                if (value2 == undefined) {
                    return value1;
                }
                return value1 < value2 ? value1 : value2;
            };

            wijinputdate.prototype._max = function (value1, value2) {
                if (value2 == undefined) {
                    return value1;
                }
                return value1 > value2 ? value1 : value2;
            };

            wijinputdate.prototype._allowEdit = function () {
                return !this.option('disableUserInput');
            };

            wijinputdate.prototype._onFocus = function (e) {
                _super.prototype._onFocus.call(this, e);

                if (!this._allowEdit()) {
                    return;
                }
                this._updateText();

                if (this.element.data('IsInSelectTextMethod') == true) {
                    return;
                }

                if (input.CoreUtility.chrome) {
                    var self = this;
                    self.element.data('needResoteActiveField', true);
                    window.setTimeout(function () {
                        self.element.data('needResoteActiveField', false);
                        if (self.options.highlightText == "all") {
                            self._highLightAllField();
                            this._setOption('activeField', 0);
                        } else {
                            self._highLightField();
                        }
                    }, 200);
                } else {
                    if (this.options.highlightText == "all") {
                        this._highLightAllField();
                        this.element.data('ignoreHighLight', true);
                        this._setOption('activeField', 0);
                    } else {
                        this._highLightField();
                    }
                }
            };

            wijinputdate.prototype._simulate = function (text) {
                var str = null;

                if (typeof text === "string") {
                    str = text;
                } else {
                    var range = this.element.wijtextselection();
                    var start = this.element.data('lastSelection').start;
                    var end = range.end;

                    if (end >= start) {
                        str = this.element.val().substring(start, end);
                    }
                }

                for (var era = 0; era < input.DateTimeInfo.GetEraCount(); era++) {
                    if ((str.toLowerCase() === input.DateTimeInfo.GetEraShortNames()[era].toLowerCase()) || (str.toLowerCase() === input.DateTimeInfo.GetEraAbbreviations()[era].toLowerCase()) || (str.toLowerCase() === input.DateTimeInfo.GetEraSymbols()[era].toLowerCase()) || (str.toLowerCase() === input.DateTimeInfo.GetEraNames()[era].toLowerCase())) {
                        str = input.DateTimeInfo.GetEraShortNames()[era].toLowerCase();
                        break;
                    }
                }

                _super.prototype._simulate.call(this, str);
            };

            wijinputdate.prototype._doSpin = function (up, repeating) {
                var _this = this;
                if (!this._allowEdit()) {
                    return false;
                }
                if (repeating && this.element.data('breakSpinner')) {
                    return false;
                }

                if (up) {
                    this._trigger('spinUp', null);
                } else {
                    this._trigger('spinDown', null);
                }

                if (this.options.date == null) {
                    this._setDefaultDate(up);
                    return;
                }

                var spinResult = false;
                if (up) {
                    spinResult = this._textProvider.incEnumPart();
                } else {
                    spinResult = this._textProvider.decEnumPart();
                }

                if (spinResult) {
                    this._updateText();

                    //#68654
                    if (input.CoreUtility.chrome) {
                        var self = this;
                        setTimeout(function () {
                            self.element.focus();
                            self._highLightField();
                        }, 10);
                    } else {
                        this._highLightField();
                    }
                }

                if (repeating && !this.element.data('breakSpinner')) {
                    var spinTimer = window.setTimeout(function () {
                        return _this._doSpin(up, true);
                    }, this._calcSpinInterval());
                    this.element.data("spintimer", spinTimer);
                }

                return true;
            };

            wijinputdate.prototype._setDefaultDate = function (up) {
                if (up) {
                    this.options.date = this._isEraFormatExist() ? this._getRealEraMinDate() : this._getRealMinDate();
                } else {
                    this.options.date = this._isEraFormatExist() ? this._getRealEraMaxDate() : this._getRealMaxDate();
                }

                this._updateText();
                this._highLightField();
            };

            wijinputdate.prototype._onChange = function () {
            };

            wijinputdate.prototype._afterFocused = function () {
                if (this._isNullText()) {
                    this._doFocus();
                }
                //var hc = () => {
                //	this._highLightCursor();
                //	this._resetTimeStamp();
                //};
                // to fixed the issue 27522. remove this time out. by dail 2012-9-6
                //window.setTimeout(hc, 10);
            };

            wijinputdate.prototype._onBlur = function (e) {
                _super.prototype._onBlur.call(this, e);
                this._checkDate();
                this._removeState('focus', this.outerDiv);
                this._updateText();
            };

            wijinputdate.prototype._keyDownPreview = function (e) {
                // Fix bug 69276:Time cannot be edited for the second time. The reason is in iOS Safari:
                // No click event fires after tap the text while input element is focus-in status;
                // No click and touch event fire after tap the first cursor position of the text while input element is focus-in status.
                // So we have to correct highlight in keydown.
                if (input.CoreUtility.IPadAndIPhone && this.element.data('ignoreHighLight') != true) {
                    var range = this.element.wijtextselection();
                    if (range != null && range.end == range.start) {
                        this._highLightCursor();
                    }
                }

                if (_super.prototype._keyDownPreview.call(this, e)) {
                    return true;
                }

                var key = e.keyCode || e.which, selRange;
                switch (key) {
                    case jqKeyCode.UP:
                    case jqKeyCode.DOWN:
                        if (e.altKey) {
                            this._onTriggerClicked();
                            return true;
                        } else {
                            if (this.element.data("pickerCurrentTab") != "List") {
                                this._doSpin(key == jqKeyCode.UP, false);
                                this._stopEvent(e);
                                return true;
                            }
                        }
                        break;
                    case jqKeyCode.LEFT:
                        if (this.options.activeField == 0 && (this.options.blurOnLeftRightKey.toLowerCase() == "left" || this.options.blurOnLeftRightKey.toLowerCase() == "both")) {
                            input.CoreUtility.MoveFocus(this.element.get(0), false);
                            this._trigger('keyExit');
                        } else {
                            this._toPrevField();
                        }
                        return true;
                    case jqKeyCode.RIGHT:
                        if (this.options.activeField == this._textProvider.getFieldCount() - 1 && (this.options.blurOnLeftRightKey.toLowerCase() == "right" || this.options.blurOnLeftRightKey.toLowerCase() == "both")) {
                            input.CoreUtility.MoveFocus(this.element.get(0), true);
                            this._trigger('keyExit');
                        } else {
                            this._toNextField();
                        }

                        return true;
                    case jqKeyCode.ENTER:
                        if (this._wasPopupShowing) {
                            if (this.element.data("pickerCurrentTab") == "Calendar") {
                                if (this.options.date == null) {
                                    this._setOption('date', new Date());
                                }
                            } else if (this.element.data("pickerCurrentTab") == "List") {
                                this._processKeyForDropDownList(e);
                            } else {
                                this._okButtonMouseDown(null, null);
                            }
                            this._hidePopup();
                            return true;
                        } else {
                            if (this.options.hideEnter) {
                                _super.prototype._stopEvent.call(this, e);
                            }
                        }
                        break;
                    case jqKeyCode.TAB:
                        if (this.options.tabAction !== "field" || this.options.highlightText !== "field") {
                            this._trigger('keyExit');
                            break;
                        }

                        selRange = this.element.wijtextselection();
                        if (selRange && selRange.end - selRange.start !== this.element.val().length) {
                            if (e.shiftKey) {
                                if (this.options.activeField > 0) {
                                    this._toPrevField();
                                } else {
                                    this._trigger('keyExit');
                                    break;
                                }
                            } else {
                                if (this.options.activeField < this._textProvider.getFieldCount() - 1) {
                                    this._toNextField();
                                } else {
                                    this._trigger('keyExit');
                                    break;
                                }
                            }
                            return true;
                        }
                        break;
                    case jqKeyCode.SPACE:
                    case 188:
                    case 190:
                    case 110:
                    case 191:
                        if (e.shiftKey) {
                            if (this.options.activeField > 0) {
                                this._toPrevField();
                                return true;
                            }
                        } else {
                            if (this.options.activeField < this._textProvider.getFieldCount() - 1) {
                                this._toNextField();
                                return true;
                            }
                        }
                        break;
                    case jqKeyCode.HOME:
                        if (e.ctrlKey) {
                            this._setOption('date', new Date());
                        } else {
                            this._toFirstField();
                        }
                        return true;
                    case jqKeyCode.END:
                        if (e.ctrlKey) {
                            this._processClearButton();
                        } else {
                            this._toLastField();
                        }
                        return true;
                    case jqKeyCode.BACKSPACE:
                    case jqKeyCode.DELETE:
                        if (this._allowEdit()) {
                            this._processDeleteKey();
                            return true;
                        }
                        break;
                }

                return false;
            };

            wijinputdate.prototype._processDeleteKey = function () {
                if (this.options.date == null) {
                    return;
                }

                var selRange = this.element.wijtextselection();
                if (selRange.end - selRange.start === this.element.val().length) {
                    var minDate = this._isEraFormatExist() ? this._getRealEraMinDate() : this._getRealMinDate();
                    if (this.options.date > minDate) {
                        this._setOption('date', minDate);
                        return;
                    }
                } else {
                    var activeField = this.options.activeField;
                    var oldText = this._textProvider.getFiledText(activeField);
                    this._clearField();
                    var newText = this._textProvider.getFiledText(activeField);
                    if (oldText != newText) {
                        return;
                    }
                }

                this._processClearButton();
            };

            wijinputdate.prototype._autoMoveToNextField = function (pos, ch) {
                if (!this.options.autoNextField) {
                    return;
                }

                if (this._textProvider.needToMove(this.options.activeField, pos, ch)) {
                    this._toNextField();
                }
            };

            wijinputdate.prototype._processClearButton = function () {
                if (this._allowEdit()) {
                    this._setOption('date', null);
                } else {
                    this._updateText();
                }
            };

            wijinputdate.prototype._autoMoveToNextControl = function (pos, ch, activeField) {
                if (!this.options.blurOnLastChar || activeField !== this._textProvider.getFieldCount() - 1) {
                    return;
                }

                if (this._textProvider.needToMove(activeField, pos, ch)) {
                    input.CoreUtility.MoveFocus(this.element.get(0), true);
                    this._trigger('keyExit');
                }
            };

            wijinputdate.prototype._keyPressPreview = function (e) {
                var key = e.keyCode || e.which, range, ch, fieldSep, cursor, now, newAction, lastTime, pos, ret, lastInput;

                if (key === jqKeyCode.ENTER) {
                    if (this.isDateNull()) {
                        this._setOption("date", new Date());
                    }
                    return false;
                }

                range = this._textProvider.getFieldRange(this.options.activeField);
                if (range) {
                    if (key === jqKeyCode.TAB) {
                        return true;
                    }

                    if (key === jqKeyCode.SPACE) {
                        this._stopEvent(e);
                        return true;
                    }

                    ch = String.fromCharCode(key);
                    fieldSep = this._textProvider.isFieldSep(ch, this.options.activeField);
                    if (fieldSep) {
                        this._toNextField();
                        this._stopEvent(e);
                        return true;
                    }

                    cursor = this.element.data('cursorPos');
                    now = new Date();
                    lastTime = this.element.data('timeStamp');
                    lastInput = this.element.data('lastInput');
                    newAction = (now.getTime() - lastTime.getTime()) > this.options.keyDelay;
                    var inputChar = ch;
                    if (newAction) {
                        cursor = 0;
                    } else if (lastInput) {
                        inputChar = lastInput + inputChar;
                    }
                    this.element.data({ timeStamp: now, lastInput: inputChar });

                    pos = range.start + cursor;
                    this.element.data('cursorPos', ++cursor);

                    var nullFlag = this.options.date == null;
                    ret = this._textProvider.addToField(inputChar, this.options.activeField, pos);
                    var activeField = this.options.activeField;
                    if (ret) {
                        this._updateText();
                        this._autoMoveToNextField(cursor, ch);
                        this._highLightField();
                        this._autoMoveToNextControl(cursor, ch, activeField);
                    } else {
                        if (nullFlag) {
                            this._setOption("date", null);
                        }
                        this._resetTimeStamp();
                        this._fireIvalidInputEvent();
                    }

                    if (activeField != this.options.activeField) {
                        this.element.data("lastInputChar", "");
                    } else {
                        this.element.data("lastInputChar", ch);
                    }

                    this._stopEvent(e);
                    return true;
                }

                return false;
            };

            wijinputdate.prototype._raiseDataChanged = function () {
                var d = this.options.date, prevDt = this.element.data('preDate');
                this.element.data('preDate', !d ? null : new Date(d.getTime()));

                if ((!prevDt && d) || (prevDt && !d) || (prevDt && d && (prevDt.getTime() !== d.getTime()))) {
                    if (this._popupVisible()) {
                        // DaryLuo 2013/09/04, improve performance on IE7.
                        // Sync calendar will cost a lot of time.
                        this._syncCalendar();
                    }
                    if (d instanceof Date === true) {
                        this.element.attribute('aria-valuenow', d.getTime());
                    }
                    this._trigger('dateChanged', null, { date: d });
                }
            };

            wijinputdate.prototype._isMinDate = function (date) {
                return date.getFullYear() === 1 && date.getMonth() === 0 && date.getDate() === 1;
            };

            wijinputdate.prototype._reInitPicker = function () {
                this._destroyPicker();
                this._initPicker();
            };

            wijinputdate.prototype._destroy = function () {
                _super.prototype._destroy.call(this);
                this._destroyPicker();
            };

            wijinputdate.prototype._destroyPicker = function () {
                var tablePicker = this.element.data('pickers');
                if (tablePicker != undefined) {
                    this.element.data('pickers', null);
                    this.element.data('calendar', null);
                    this.element.data('datePicker', null);
                    this.element.data('timePicker', null);
                    this._comboDiv = undefined;
                }
            };

            wijinputdate.prototype._initPicker = function () {
                var _this = this;
                var tablePicker = this.element.data('pickers');
                if (tablePicker != undefined) {
                    return;
                }

                var self = this;
                this._initPickerData();

                var pickerCount = this._getPickerCount();
                var pickerWidth = this.element.data('pickerWidth');
                var pickerHeight = this.element.data('pickerHeight');
                var pickerAreaHeight = this.element.data('pickerAreaHeight');

                if (pickerCount > 1) {
                    pickerHeight += 8;
                    pickerAreaHeight += 8;
                }

                var pickerDivHeight = pickerCount > 1 ? pickerHeight : pickerAreaHeight;

                tablePicker = $("<table/>").appendTo(document.body).attr({ "class": "ui-widget-content ui-corner-all", "borderWidth": "0px", "cellspacing": "0px", "cellpadding": "0px", "cursor": "default" }).css({ "font-size": "12px" }).mouseup(function (e) {
                    e.stopPropagation();
                });

                var trPicker = $("<tr/>").appendTo(tablePicker);

                var trButton = $("<tr/>").appendTo(tablePicker);

                var tdPicker = $("<td/>").appendTo(trPicker).css({ "width": "100%", "height": "100%" });

                var tdButton = $("<td/>").appendTo(trButton).attr("align", "center").css({ "width": "100%", "height": "30px", "display": "none" });

                var divOK = $("<input type='button'/>").appendTo(tdButton).attr({ "class": "ui-state-active ui-widget", "value": "OK" }).css({ "width": "80px", "height": "26px", "margin": "1px", "text-align": "center", "cursor": "pointer", "visibility": "hidden" }).mousedown(function (e) {
                    self._okButtonMouseDown(e);
                });

                var divPickers = $("<div/>").appendTo(tdPicker).css({ "width": "100%", "height": "100%", "padding": "0px", "margin": "0px", "borderWidth": "0px", "overflow": "hidden" });

                var ulPicker = $("<ul/>").css({ "line-height": "1px", "font-size": "12px" });

                if (pickerCount > 1) {
                    ulPicker.appendTo(divPickers);
                }

                var currentTab = "";
                if (this._isCalendarPickerShown()) {
                    if (pickerCount > 1) {
                        this._addPickerTab(ulPicker, "Calendar", "#" + this._id + "_CalendarDiv");
                    } else {
                        if (input.CoreUtility.IsIE9()) {
                            tdPicker.css({ "width": "" });
                            divPickers.css({ "width": "" });
                        }
                    }

                    this._initCalendarPicker();
                    var calendar = this.element.data('calendar');
                    this._addPickerEditor(divPickers, calendar, this._id + "_CalendarDiv");
                    currentTab = "Calendar";
                }

                if (this._isListPickerShown()) {
                    if (pickerCount > 1) {
                        this._addPickerTab(ulPicker, "List", "#" + this._id + "_listDiv");
                    }
                    this._initListPicker();
                    this._addPickerEditor(divPickers, this._comboDiv, this._id + "_listDiv");

                    currentTab = currentTab == "" ? "List" : currentTab;
                }

                if (this._isDatePickerShown()) {
                    if (pickerCount > 1) {
                        this._addPickerTab(ulPicker, "Date", "#" + this._id + "_dateDiv");
                    }
                    this._wijinputdateroller._initDatePicker();
                    var datePicker = this.element.data('datePicker');
                    this._addPickerEditor(divPickers, datePicker, this._id + "_dateDiv");
                    currentTab = currentTab == "" ? "Date" : currentTab;
                }

                if (this._isTimePickerShown()) {
                    if (pickerCount > 1) {
                        this._addPickerTab(ulPicker, "Time", "#" + this._id + "_timeDiv");
                    }
                    this._wijinputdateroller._initTimePicker();
                    var timePicker = this.element.data('timePicker');
                    this._addPickerEditor(divPickers, timePicker, this._id + "_timeDiv");
                    currentTab = currentTab == "" ? "Time" : currentTab;
                }

                if (currentTab == "Calendar") {
                    tablePicker.css({ "width": pickerWidth + "px", "height": "", "font-size": "" });
                } else if (currentTab == "Date" || currentTab == "Time") {
                    tdButton.css({ "display": "" });
                    tablePicker.css({ "width": pickerWidth + "px", "height": pickerHeight + "px", "font-size": "12px" });
                    divPickers.css({ "height": pickerDivHeight + "px" });
                }

                this.element.data("pickerCurrentTab", currentTab);

                var self = this;
                divPickers.wijtabs({
                    select: function (e, arg) {
                        var tabText = arg.tab.outerText || arg.tab.text;
                        tdButton.css({ "display": "none" });
                        self.element.data("pickerCurrentTab", tabText);
                        if (tabText == "Calendar") {
                            if (!input.CoreUtility.IsPad()) {
                                self.focus();
                            }
                            tablePicker.css({ "width": pickerWidth + "px", "height": "", "font-size": "" });
                            divPickers.css({ "height": "100%" });
                        } else if (tabText == "List") {
                            var listWidth = self._getListPickerWidth();
                            self._comboDiv.wijlist("option", "width", listWidth);
                            tablePicker.css({ "width": listWidth, "height": "", "font-size": "" });
                            divPickers.css({ "height": "100%" });
                            self._comboDiv.wijlist('renderList');
                            if (!input.CoreUtility.IPadAndIPhone) {
                                self._comboDiv.focus();
                            }
                        } else {
                            if (!input.CoreUtility.IsPad()) {
                                self.focus();
                            }
                            if (tabText == "Time" || tabText == "Date") {
                                tdButton.css({ "display": "" });
                                tablePicker.css({ "width": pickerWidth + "px", "height": pickerHeight + "px", "font-size": "12px" });
                                divPickers.css({ "height": pickerDivHeight + "px" });
                            }
                        }
                    }
                });

                tablePicker.wijpopup({
                    autoHide: true,
                    hidden: function () {
                        _this._trigger('dropDownClose');
                        _this._wasPopupShowing = false;
                    },
                    shown: function () {
                        _this._trigger('dropDownOpen');
                        _this._wasPopupShowing = true;

                        var calOpts = _this.options.calendar, calEle, calendar, calGrid;
                        if (!calOpts || !calOpts.calendarMode) {
                            return;
                        }
                        calEle = _this.element.data('calendar');
                        calendar = calEle.data("wijmo-wijcalendar");
                        if (calendar != null) {
                            setTimeout(function () {
                                calGrid = calendar._getMyGrid();
                                calGrid.gridType = calOpts.calendarMode;
                                calendar._updateMyGrid(1);
                            }, 0);
                        }
                    }
                });

                this.element.data('pickers', tablePicker);
                this.element.data('divPickers', divPickers);
                this.element.data('divOK', divOK);
            };

            wijinputdate.prototype._initPickerData = function () {
                var tabWidth = 70;
                var tabHeight = 32;
                var listItemHeight = 26;
                var buttonHeight = 30;
                var minPickerWidth = 150;
                var minPickerHeight = 100;
                var minCalendarPickerWidth = 235;
                var minCalendarPickerHeight = 242;
                var minDateTimePickerWidth = 220;
                var minDateTimePickerHeight = 220;
                var pickerCount = this._getPickerCount();

                var minWidth = pickerCount * tabWidth;
                var minHeight = minPickerHeight;

                minWidth = minWidth < minPickerWidth ? minPickerWidth : minWidth;
                if (this._isCalendarPickerShown()) {
                    minWidth = minWidth < minCalendarPickerWidth ? minCalendarPickerWidth : minWidth;
                    minHeight = minHeight < minCalendarPickerHeight ? minCalendarPickerHeight : minHeight;
                }

                if (this._isListPickerShown()) {
                    var listItem = this._getcomboItems();
                    if (listItem != undefined) {
                        var minListHeight = listItem.length * listItemHeight;
                        minHeight = minHeight < minListHeight ? minListHeight : minHeight;
                    }
                }

                if (this._isDatePickerShown()) {
                    minWidth = minWidth < minDateTimePickerWidth ? minDateTimePickerWidth : minWidth;
                    minHeight = minHeight < minDateTimePickerWidth ? minDateTimePickerWidth : minHeight;

                    var pickerMinYear = this._wijinputdateroller._getDatePickerMinYear();
                    var pickerMaxYear = this._wijinputdateroller._getDatePickerMaxYear();
                    var defaultDateFormat = this._wijinputdateroller._getDefaultDatePickerFormat();
                    var pickerFormat = this.options.pickers.datePicker.format != undefined ? this.options.pickers.datePicker.format : defaultDateFormat;
                    var pickerDateFormat = pickerFormat.split(',');

                    if (pickerDateFormat.length != 3) {
                        pickerDateFormat = defaultDateFormat.split(',');
                        this.options.pickers.datePicker.format = defaultDateFormat;
                    }

                    var yearFormat = this._wijinputdateroller._getRollFormat(pickerDateFormat, "y");
                    var monthFormat = this._wijinputdateroller._getRollFormat(pickerDateFormat, "M");
                    var dayFormat = this._wijinputdateroller._getRollFormat(pickerDateFormat, "d");

                    if (!this._wijinputdateroller._isValidatePickerFormat(yearFormat) || !this._wijinputdateroller._isValidatePickerFormat(monthFormat) || !this._wijinputdateroller._isValidatePickerFormat(dayFormat)) {
                        pickerDateFormat = defaultDateFormat.split(',');
                        yearFormat = this._wijinputdateroller._getRollFormat(pickerDateFormat, "y");
                        monthFormat = this._wijinputdateroller._getRollFormat(pickerDateFormat, "M");
                        dayFormat = this._wijinputdateroller._getRollFormat(pickerDateFormat, "d");
                        this.options.pickers.datePicker.format = defaultDateFormat;
                    }

                    this.element.data('pickerDateYearFormat', yearFormat);
                    this.element.data('pickerDateMonthFormat', monthFormat);
                    this.element.data('pickerDateDayFormat', dayFormat);
                    this.element.data('pickerMinYear', pickerMinYear);
                    this.element.data('pickerMaxYear', pickerMaxYear);
                    this.element.data('pickerDateFormat', pickerDateFormat);
                }

                if (this._isTimePickerShown()) {
                    minWidth = minWidth < minDateTimePickerWidth ? minDateTimePickerWidth : minWidth;
                    minHeight = minHeight < minDateTimePickerWidth ? minDateTimePickerWidth : minHeight;

                    var defaultTimeFormat = this._wijinputdateroller._getDefaultTimePickerFormat();
                    var format = this.options.pickers.timePicker.format != undefined ? this.options.pickers.timePicker.format : defaultTimeFormat;
                    var pickerTimeFormat = format.split(',');

                    if (pickerTimeFormat.length != 3) {
                        pickerTimeFormat = defaultTimeFormat.split(',');
                        this.options.pickers.timePicker.format = defaultTimeFormat;
                    }

                    var hourFormat = this._wijinputdateroller._getRollFormat(pickerTimeFormat, "h");
                    var minuteFormat = this._wijinputdateroller._getRollFormat(pickerTimeFormat, "m");
                    var amFormat = this._wijinputdateroller._getRollFormat(pickerTimeFormat, "t");

                    if (!this._wijinputdateroller._isValidatePickerFormat(hourFormat) || !this._wijinputdateroller._isValidatePickerFormat(minuteFormat) || !this._wijinputdateroller._isValidatePickerFormat(amFormat)) {
                        pickerTimeFormat = defaultTimeFormat.split(',');
                        hourFormat = this._wijinputdateroller._getRollFormat(pickerTimeFormat, "h");
                        minuteFormat = this._wijinputdateroller._getRollFormat(pickerTimeFormat, "m");
                        amFormat = this._wijinputdateroller._getRollFormat(pickerTimeFormat, "t");
                        this.options.pickers.timePicker.format = defaultTimeFormat;
                    }

                    this.element.data('pickerTimeHourFormat', hourFormat);
                    this.element.data('pickerTimeMinuteFormat', minuteFormat);
                    this.element.data('pickerTimeAMFormat', amFormat);
                    this.element.data('pickerTimeFormat', pickerTimeFormat);
                }

                var pickerWidth = this.options.pickers.width != undefined ? this.options.pickers.width : 0;
                var pickerHeight = this.options.pickers.height != undefined ? this.options.pickers.height : 0;

                pickerWidth = pickerWidth < minWidth ? minWidth : pickerWidth;
                pickerHeight = pickerHeight < minHeight ? minHeight : pickerHeight;
                pickerHeight -= pickerCount > 1 ? tabHeight : 0;

                var pickerAreaHeight = pickerHeight - buttonHeight;
                var itemHeight = Math.floor(pickerAreaHeight / 5) + 1;
                var indicatorHeight = itemHeight * 2;
                var indicatorTranslateTop = itemHeight * 5 + 6;
                var indicatorTranslateDown = itemHeight * 4 - 3;
                var indicatorTranslateSelector = itemHeight * 2 + 2;
                var indicatorTranslateContent = itemHeight;

                this.element.data('itemHeight', itemHeight);
                this.element.data('indicatorHeight', indicatorHeight);
                this.element.data('pickerWidth', pickerWidth);
                this.element.data('pickerHeight', pickerHeight);
                this.element.data('pickerAreaHeight', pickerAreaHeight);
                this.element.data('indicatorTranslateTop', indicatorTranslateTop);
                this.element.data('indicatorTranslateDown', indicatorTranslateDown);
                this.element.data('indicatorTranslateSelector', indicatorTranslateSelector);
                this.element.data('indicatorTranslateContent', indicatorTranslateContent);
            };

            wijinputdate.prototype._initListPicker = function () {
                var _this = this;
                if (this._comboDiv !== undefined) {
                    return;
                }

                this._comboDiv = $("<div/>").css({ "overflow": "hidden", "display": "block", "left": "", "top": "", "position": "" });

                var content = this._normalize(this._getcomboItems());
                this._comboDiv.wijlist({
                    maxItemsCount: 5,
                    autoSize: true,
                    selected: function (event, ui) {
                        if (!_this.options.disableUserInput) {
                            _this._setData(ui.item.value);
                        }

                        var pickers = _this.element.data('pickers');
                        setTimeout(function () {
                            try  {
                                if (pickers != undefined) {
                                    pickers.wijpopup('hide');
                                }
                            } catch (e) {
                            }
                        }, 250);
                        _this._trySetFocus();
                    }
                });

                this._comboDiv.wijlist('setItems', content);
                this._comboDiv.wijlist('renderList');

                if (input.CoreUtility.IsIE7()) {
                    this._comboDiv.attr("align", "left");
                }
            };

            wijinputdate.prototype._initCalendarPicker = function () {
                var _this = this;
                var calendar = this.element.data('calendar');
                if (calendar != undefined) {
                    return;
                }

                //var c = this.options.calendar;
                //if (c === undefined || c === null) {
                //    return;
                //}
                //if (typeof (c) === 'boolean' || c === 'default') {
                //    c = $("<div/>");
                //}
                var c = $("<div/>");
                calendar = $(c);
                if (calendar.length !== 1) {
                    return;
                }

                this.element.data('calendar', calendar);

                // if the localization from the resource files.
                if (this.options.localization) {
                    this.options.nextTooltip = this.options.localization.nextTooltip;
                    this.options.prevTooltip = this.options.localization.prevTooltip;
                    this.options.titleFormat = this.options.localization.titleFormat;
                    this.options.toolTipFormat = this.options.localization.toolTipFormat;
                }

                calendar.wijcalendar({
                    popupMode: true,
                    culture: this.options.culture,
                    cultureCalendar: this.options.cultureCalendar,
                    //add for localization(tooltip)
                    nextTooltip: this.options.nextTooltip || 'Next',
                    prevTooltip: this.options.prevTooltip || 'Previous',
                    titleFormat: this.options.titleFormat || 'MMMM yyyy',
                    toolTipFormat: this.options.toolTipFormat || 'dddd, MMMM dd, yyyy',
                    afterSlide: function () {
                        if (_this.options.afterSlide != null) {
                            _this.options.afterSlide.call(_this, null);
                        }
                    },
                    selectedDatesChanged: function () {
                        var selDate = calendar.wijcalendar("getSelectedDate"), curDate = _this.option('date');
                        _this._wasPopupShowing = false;

                        var pickers = _this.element.data('pickers');
                        setTimeout(function () {
                            try  {
                                if (pickers != undefined) {
                                    pickers.wijpopup('hide');
                                }
                                if (selDate) {
                                    if (curDate) {
                                        selDate.setHours(curDate.getHours());
                                        selDate.setMinutes(curDate.getMinutes());
                                        selDate.setSeconds(curDate.getSeconds());
                                        selDate.setMilliseconds(curDate.getMilliseconds());
                                    }

                                    if (_this._allowEdit()) {
                                        _this.option('date', selDate);
                                        _this.selectText();
                                    }
                                }
                                _this._trySetFocus();
                            } catch (e) {
                            }
                        }, 250);
                    }
                });

                calendar.css({ "display": "block", "left": "", "top": "", "position": "", "margin-bottom": "0px" });

                this._syncCalendar();
                this._updateCalendarPicker();
                // the bind event can't trigger.!!!
                //            calendar.bind('wijcalendarselectedDatesChanged', function () {
                //                var selDate = $(this).wijcalendar("getSelectedDate");
                //                $(this).wijcalendar("close");
                //                if (!!selDate) { self.option('date', selDate); }
                //                self._trySetFocus();
                //               });
            };

            wijinputdate.prototype._updateCalendarPicker = function () {
                var calendar = this.element.data('calendar');
                var pickers = this.options.pickers;
                if (calendar == undefined || pickers == undefined) {
                    return;
                }

                if (pickers.calendar == undefined) {
                    return;
                }

                if (pickers.calendar.allowQuickPick != undefined) {
                    calendar.wijcalendar('option', 'allowQuickPick', pickers.calendar.allowQuickPick);
                }

                if (pickers.calendar.navButtons != undefined) {
                    calendar.wijcalendar('option', 'navButtons', pickers.calendar.navButtons);
                }

                if (pickers.calendar.nextTooltip != undefined) {
                    calendar.wijcalendar('option', 'nextTooltip', pickers.calendar.nextTooltip);
                }

                if (pickers.calendar.prevTooltip != undefined) {
                    calendar.wijcalendar('option', 'prevTooltip', pickers.calendar.prevTooltip);
                }

                if (pickers.calendar.showDayPadding != undefined) {
                    calendar.wijcalendar('option', 'showDayPadding', pickers.calendar.showDayPadding);
                }

                if (pickers.calendar.showOtherMonthDays != undefined) {
                    calendar.wijcalendar('option', 'showOtherMonthDays', pickers.calendar.showOtherMonthDays);
                }

                if (pickers.calendar.showTitle != undefined) {
                    calendar.wijcalendar('option', 'showTitle', pickers.calendar.showTitle);
                }

                if (pickers.calendar.showWeekDays != undefined) {
                    calendar.wijcalendar('option', 'showWeekDays', pickers.calendar.showWeekDays);
                }

                if (pickers.calendar.showWeekNumbers != undefined) {
                    calendar.wijcalendar('option', 'showWeekNumbers', pickers.calendar.showWeekNumbers);
                }

                if (pickers.calendar.titleFormat != undefined) {
                    calendar.wijcalendar('option', 'titleFormat', pickers.calendar.titleFormat);
                }

                if (pickers.calendar.toolTipFormat != undefined) {
                    calendar.wijcalendar('option', 'toolTipFormat', pickers.calendar.toolTipFormat);
                }

                if (pickers.calendar.weekDayFormat != undefined) {
                    calendar.wijcalendar('option', 'weekDayFormat', pickers.calendar.weekDayFormat);
                }
            };

            wijinputdate.prototype._okButtonMouseDown = function (e, arg) {
                var year = this.element.data("pickerYear");
                var month = this.element.data("pickerMonth") - 1;
                var day = this.element.data("pickerDay");
                var hour = this.element.data("pickerHour");
                var minute = this.element.data("pickerMinute");
                var am = this.element.data("pickerAM");

                if (hour == 12) {
                    hour = 0;
                }

                if (am == 1) {
                    hour += 12;
                }

                var date = this._getPickerValue();
                date.setFullYear(year);
                date.setMonth(month);
                date.setDate(day);
                date.setHours(hour);
                date.setMinutes(minute);

                this._wasPopupShowing = false;

                var pickers = this.element.data('pickers');
                setTimeout(function () {
                    if (pickers != undefined) {
                        try  {
                            pickers.wijpopup('hide');
                        } catch (e) {
                        }
                    }
                }, 250);

                if (this._allowEdit()) {
                    this.option('date', date);
                    this.selectText();
                }
                this._trySetFocus();
            };

            wijinputdate.prototype._getListPickerWidth = function () {
                var comboWidth = this._getcomboWidth();
                var pickerWidth = this.element.data("pickerWidth");
                var width = comboWidth != undefined ? comboWidth : this.outerDiv.width();
                return pickerWidth > width ? pickerWidth + "px" : width + "px";
            };

            wijinputdate.prototype._getPickerValue = function () {
                var pickerValue = this.options.date;
                pickerValue = pickerValue == null ? new Date() : pickerValue;
                return pickerValue;
            };

            wijinputdate.prototype._getStandardAMPM = function (value) {
                var culture = this._getCulture();
                if (culture && culture.calendar) {
                    var tmp = culture.calendars.standard[value];
                    if (tmp) {
                        return tmp[0];
                    }
                }
                return value;
            };

            wijinputdate.prototype._syncCalendar = function () {
                var calendar = this.element.data('calendar');
                if (!calendar) {
                    return;
                }

                var date = this._safeGetDate();
                if (date == null || this._isMinDate(date)) {
                    date = new Date();
                }

                //HelenLiu: 2014/12/17 Fix bug 98538.
                //calendar.wijcalendar('option', 'displayDate', date);
                calendar.wijcalendar('option', 'displayDate', new Date(date.getFullYear(), date.getMonth(), 1));

                if (this.options.minDate) {
                    calendar.wijcalendar('option', 'minDate', this.options.minDate);
                }

                if (this.options.maxDate) {
                    calendar.wijcalendar('option', 'maxDate', this.options.maxDate);
                }

                calendar.wijcalendar('unSelectAll');
                calendar.wijcalendar('selectDate', date);
                calendar.wijcalendar('refresh');
            };

            wijinputdate.prototype._showPopup = function () {
                var _this = this;
                if (this._isDatePickerNeedReInit()) {
                    this._reInitPicker();
                }

                var pickers = this.element.data('pickers');
                if (pickers == undefined) {
                    return false;
                }

                pickers.wijpopup('show', $.extend({}, this.options.popupPosition, { of: this.outerDiv })).one("mousedown", function () {
                    _this._deferClearBlurTimeout();
                });

                var pickerValue = this._getPickerValue();
                var hour = pickerValue.getHours();
                if (hour > 12) {
                    hour -= 12;
                } else if (hour == 0) {
                    hour = 12;
                }

                this.element.data("pickerValue", pickerValue);
                this.element.data("pickerYear", pickerValue.getFullYear());
                this.element.data("pickerMonth", pickerValue.getMonth() + 1);
                this.element.data("pickerDay", pickerValue.getDate());
                this.element.data("pickerHour", hour);
                this.element.data("pickerMinute", pickerValue.getMinutes());
                this.element.data("pickerAM", pickerValue.getHours() < 12 ? 0 : 1);
                this.element.data('divOK').css("visibility", "");

                if (this._isTimePickerShown()) {
                    this._wijinputdateroller._updateTimePicker();
                    pickers.attr({ "class": "ui-widget-content ui-corner-all" });
                }

                if (this._isDatePickerShown()) {
                    this._wijinputdateroller._updateDatePicker();
                    pickers.css({ "font-size": "12px" }).attr({ "class": "ui-widget-content ui-corner-all" });
                }

                if (this._isListPickerShown()) {
                    if (this._getPickerCount() == 1) {
                        pickers.attr({ "class": "" });
                        this._comboDiv.focus();
                    }

                    if (this.element.data("pickerCurrentTab") == "List") {
                        var listWidth = this._getListPickerWidth();
                        pickers.css({ "width": listWidth, "height": "" });
                        pickers.css({ "font-size": "" });
                        var parentElement = this._comboDiv[0].parentElement;
                        this._comboDiv.wijlist("destroy");
                        this._comboDiv.remove();
                        delete this._comboDiv;
                        this._initListPicker();
                        this._comboDiv.appendTo(parentElement);
                        this._comboDiv.focus();
                    }

                    this._comboDiv.one("focus", function () {
                        _this._clearBlurTimeout();
                    });
                }

                if (this._isCalendarPickerShown()) {
                    this._syncCalendar();

                    if (this.element.data("pickerCurrentTab") == "Calendar") {
                        if (this._getPickerCount() <= 1) {
                            pickers.css({ "width": "" });
                        }
                        pickers.css({ "font-size": "" });
                    }
                }

                return true;
            };

            wijinputdate.prototype._hidePopup = function () {
                var pickers = this.element.data('pickers');
                if (pickers != undefined) {
                    pickers.wijpopup('hide');
                }

                this.element.data('divOK').css("visibility", "hidden");
            };

            wijinputdate.prototype._popupVisible = function () {
                var pickers = this.element.data('pickers');
                if (pickers != undefined) {
                    return pickers.wijpopup('isVisible');
                }

                return false;
            };

            //Add comments by Ryanwu@20160520.
            //For fixing the issue#151957,152107.
            //_isComboListVisible(): boolean {
            //	return this._popupVisible();
            //}
            //end by RyanWu@20160520.
            wijinputdate.prototype._isValidDate = function (date, chkBounds) {
                if (date === undefined) {
                    return false;
                }

                if (isNaN(date)) {
                    return false;
                }

                if (date.getFullYear() < 1 || date.getFullYear() > 9999) {
                    return false;
                }

                if (chkBounds) {
                    if (this.options.minDate) {
                        if (date < this.options.minDate) {
                            return false;
                        }
                    }

                    if (this.options.maxDate) {
                        if (date > this.options.maxDate) {
                            return false;
                        }
                    }
                }

                return true;
            };

            wijinputdate.prototype._isDatePickerNeedReInit = function () {
                if (!this._isDatePickerShown()) {
                    return false;
                }

                var pickerMinYear = this.element.data("pickerMinYear");
                var pickerMaxYear = this.element.data("pickerMaxYear");
                var year = this._getPickerValue().getFullYear();
                if (year < pickerMinYear || year > pickerMaxYear) {
                    return true;
                }

                var minYear = this._isEraFormatExist() ? this._getRealEraMinDate().getFullYear() : this._getRealMinDate().getFullYear();
                var maxYear = this._isEraFormatExist() ? this._getRealEraMaxDate().getFullYear() : this._getRealMaxDate().getFullYear();

                if (pickerMinYear < minYear || pickerMaxYear > maxYear) {
                    return true;
                }

                return false;
            };

            wijinputdate.prototype._isDropDownButtonShown = function () {
                return this.options.showDropDownButton;
            };

            wijinputdate.prototype._isCalendarPickerShown = function () {
                return (this.options.pickers.calendar != undefined && this.options.pickers.calendar.visible !== false) || this._getPickerCount() == 0;
            };

            wijinputdate.prototype._isListPickerShown = function () {
                var comboItems = this._getcomboItems();
                if (comboItems != undefined && comboItems.length != undefined) {
                    return comboItems.length > 0;
                }

                return false;
            };

            wijinputdate.prototype._isTimePickerShown = function () {
                return this.options.pickers.timePicker != undefined && this.options.pickers.timePicker.visible !== false && this._wijinputdateroller !== null;
            };

            wijinputdate.prototype._isDatePickerShown = function () {
                return this.options.pickers.datePicker != undefined && this.options.pickers.datePicker.visible !== false && this._wijinputdateroller !== null;
            };

            wijinputdate.prototype._getPickerCount = function () {
                var count = 0;
                var calendarVisible = this.options.pickers.calendar != undefined && this.options.pickers.calendar.visible !== false;
                count += calendarVisible ? 1 : 0;
                count += this._isListPickerShown() ? 1 : 0;
                count += this._isTimePickerShown() ? 1 : 0;
                count += this._isDatePickerShown() ? 1 : 0;

                return count;
            };

            wijinputdate.prototype._addPickerEditor = function (pickerDiv, picker, pickerName) {
                var div = $("<div/>").attr({ "id": pickerName, "align": "center" }).css({ "padding": "0px" }).append(picker).appendTo(pickerDiv);
            };

            wijinputdate.prototype._addPickerTab = function (ul, tab, href) {
                var li = $("<li/>").appendTo(ul).css("line-height", "1px");

                var a = $("<a/>").attr("href", href).html(tab).appendTo(li);
            };

            wijinputdate.prototype._internalSetDate = function (date) {
                var self = this, o = this.options, inputElement = this.element, typing = !!inputElement.data('typing'), chkBounds;

                if (typing) {
                    o.date = date;

                    chkBounds = function () {
                        var now = new Date(), lastTime = inputElement.data('timeStamp');
                        if (lastTime) {
                            if ((now.getTime() - lastTime.getTime()) > o.keyDelay) {
                                self._safeSetDate(o.date, true);
                                self._updateText();
                                self._highLightField();
                            } else {
                                window.setTimeout(chkBounds, o.keyDelay);
                            }
                        }
                    };

                    window.setTimeout(chkBounds, o.keyDelay);
                } else {
                    this._safeSetDate(date);
                }
            };

            /** Selects a range of text in the widget.
            * @param {Number} start Start of the range.
            * @param {Number} end End of the range.
            * @example
            * // Select first two symbols in a wijinputdate
            * $(".selector").wijinputdate("selectText", 0, 2);
            */
            wijinputdate.prototype.selectText = function (start, end) {
                if (typeof start === "undefined") { start = 0; }
                if (typeof end === "undefined") { end = this.getText().length; }
                if (this.isFocused()) {
                    _super.prototype.selectText.call(this, start, end);
                } else {
                    this.element.data('IsInSelectTextMethod', true);
                    this.focus();
                    var obj = this;
                    setTimeout(function () {
                        try  {
                            obj.selectText(start, end);
                        } catch (e) {
                        }
                    }, 0);
                    this.element.data('IsInSelectTextMethod', false);
                }
            };
            return wijinputdate;
        })(input.wijinputcore);
        input.wijinputdate = wijinputdate;

        var wijinputdate_options = (function () {
            function wijinputdate_options() {
                this.wijCSS = {
                    wijinputdate: input.wijinputcore.prototype.options.wijCSS.wijinput + "-date"
                };
                /** Determines the initial date value shown for the wijdateinput widget.
                */
                this.date = undefined;
                /** Determines the earliest, or minimum, date that can be entered.
                */
                this.minDate = null;
                /** Determines the latest, or maximum date, that can be entered.
                */
                this.maxDate = null;
                /** The format pattern to display the date value when control got focus.
                *
                * @remarks
                * wijinputdate supports two types of formats:  <br />
                * Standard Format and Custom Format. <br />
                * <br />
                * A standard date and time format string uses a single format specifier  <br />
                * to define the text representation of a date and time value. <br />
                * <br />
                * Possible values for Standard Format are: <br />
                * "d": ShortDatePattern <br />
                * "D": LongDatePattern <br />
                * "f": Full date and time (long date and short time)  <br />
                * "F": FullDateTimePattern  <br />
                * "g": General (short date and short time)  <br />
                * "G": General (short date and long time)  <br />
                * "m": MonthDayPattern  <br />
                * "M": monthDayPattern  <br />
                * "r": RFC1123Pattern   <br />
                * "R": RFC1123Pattern   <br />
                * "s": SortableDateTimePattern   <br />
                * "t": shortTimePattern   <br />
                * "T": LongTimePattern   <br />
                * "u": UniversalSortableDateTimePattern  <br />
                * "U": Full date and time (long date and long time) using universal time  <br />
                * "y": YearMonthPattern   <br />
                * "Y": yearMonthPattern   <br />
                *
                * Any date and time format string that contains more than one character,  <br/>
                * including white space, is interpreted as a custom date and time format
                * string. For example:    <br/>
                * "mmm-dd-yyyy", "mmmm d, yyyy", "mm/dd/yyyy", "d-mmm-yyyy",
                * "ddd, mmmm dd, yyyy" etc.   <br/>
                *
                * Below are the custom date and time format specifiers:  <br/>
                *   <br/>
                * "d": The day of the month, from 1 through 31.   <br />
                * "dd": The day of the month, from 01 through 31.  <br />
                * "ddd": The abbreviated name of the day of the week.  <br />
                * "dddd": The full name of the day of the week.   <br />
                * "m": The minute, from 0 through 59.   <br />
                * "mm": The minute, from 00 through 59.  <br />
                * "M": The month, from 1 through 12.  <br />
                * "MM": The month, from 01 through 12.  <br />
                * "MMM": The abbreviated name of the month.  <br />
                * "MMMM": The full name of the month.  <br />
                * "y": The year, from 0 to 99.   <br />
                * "yy": The year, from 00 to 99   <br />
                * "yyy": The year, with a minimum of three digits.  <br />
                * "yyyy": The year as a four-digit number   <br />
                * "h": The hour, using a 12-hour clock from 1 to 12.   <br />
                * "hh": The hour, using a 12-hour clock from 01 to 12.   <br />
                * "H": The hour, using a 24-hour clock from 0 to 23.   <br />
                * "HH": The hour, using a 24-hour clock from 00 to 23.  <br />
                * "s": The second, from 0 through 59.   <br />
                * "ss": The second, from 00 through 59.   <br />
                * "t": The first character of the AM/PM designator.   <br />
                * "tt": The AM/PM designator.    <br />
                */
                this.dateFormat = 'd';
                /** The format pattern to display the date value when control lost focus.
                *
                * @remarks
                * wijinputdate supports two types of formats:   <br />
                * Standard Format and Custom Format.   <br />
                * <br />
                * A standard date and time format string uses a single format specifier <br />
                * to define the text representation of a date and time value.   <br />
                *
                * Possible values for Standard Format are:  <br />
                * "d": ShortDatePattern  <br />
                * "D": LongDatePattern  <br />
                * "f": Full date and time (long date and short time) <br />
                * "F": FullDateTimePattern  <br />
                * "g": General (short date and short time)  <br />
                * "G": General (short date and long time)  <br />
                * "m": MonthDayPattern   <br />
                * "M": monthDayPattern  <br />
                * "r": RFC1123Pattern   <br />
                * "R": RFC1123Pattern   <br />
                * "s": SortableDateTimePattern  <br />
                * "t": shortTimePattern  <br />
                * "T": LongTimePattern   <br />
                * "u": UniversalSortableDateTimePattern  <br />
                * "U": Full date and time (long date and long time) using universal time   <br />
                * "y": YearMonthPattern  <br />
                * "Y": yearMonthPattern  <br />
                *
                * Any date and time format string that contains more than one character, <br />
                * including white space, is interpreted as a custom date and time format   <br />
                * string. For example: <br />
                * "mmm-dd-yyyy", "mmmm d, yyyy", "mm/dd/yyyy", "d-mmm-yyyy",
                * "ddd, mmmm dd, yyyy" etc.  <br />
                *
                * Below are the custom date and time format specifiers:  <br />
                *
                * "d": The day of the month, from 1 through 31.   <br />
                * "dd": The day of the month, from 01 through 31.   <br />
                * "ddd": The abbreviated name of the day of the week.  <br />
                * "dddd": The full name of the day of the week.  <br />
                * "m": The minute, from 0 through 59.   <br />
                * "mm": The minute, from 00 through 59.  <br />
                * "M": The month, from 1 through 12.  <br />
                * "MM": The month, from 01 through 12.   <br />
                * "MMM": The abbreviated name of the month.  <br />
                * "MMMM": The full name of the month. <br />
                * "y": The year, from 0 to 99.  <br />
                * "yy": The year, from 00 to 99  <br />
                * "yyy": The year, with a minimum of three digits.  <br />
                * "yyyy": The year as a four-digit number  <br />
                * "h": The hour, using a 12-hour clock from 1 to 12.  <br />
                * "hh": The hour, using a 12-hour clock from 01 to 12.  <br />
                * "H": The hour, using a 24-hour clock from 0 to 23.   <br />
                * "HH": The hour, using a 24-hour clock from 00 to 23.  <br />
                * "s": The second, from 0 through 59.   <br />
                * "ss": The second, from 00 through 59.  <br />
                * "t": The first character of the AM/PM designator.  <br />
                * "tt": The AM/PM designator.    <br />
                * "E": Display the nengo year as a single digit number when possible (first year use Japanese name).  <br />
                */
                this.displayFormat = '';
                /** Determines string designator for hours that are "ante meridiem" (before noon).
                * @remarks
                * The Text set in the amDesignator option is displayed in the position occupied by the keywords "tt" and "t"
                * in the dateFormat or dipslayFormat.  <br />
                * If the custom pattern includes the format pattern "tt" and the time is before noon,
                * the value of amDesignator is displayed in place of the "tt" in the dateFormat or displayFormat pattern.   <br />
                * If the custom pattern includes the format pattern "t", only the first character of amDesignator is displayed.   <br />
                * If setting "tt" in format and not setting amDesignator/pmDesignator options,
                * it will show the string getting from the specified culture.    <br />
                * If not set, it will show "午前"/"午後" in Japanese culture and "AM"/"PM" in English culture.   <br />
                * If setting "t" in format and not setting amDesignator/pmDesignator options, it will show the string getting from current culture.  <br />
                * If not set, it will display "午" in Japanese culture and "A"/"P" in English culture.  <br />
                */
                this.amDesignator = "";
                /** Determines the string designator for hours that are "post meridiem" (after noon).
                * @remarks
                * The Text set in the amDesignator option is displayed in the position occupied by the keywords "tt" and "t"
                * in the dateFormat or dipslayFormat.  <br />
                * If the custom pattern includes the format pattern "tt" and the time is after noon,
                * the value of pmDesignator is displayed in place of the "tt" in the dateFormat or displayFormat pattern.   <br />
                * If the custom pattern includes the format pattern "t", only the first character of pmDesignator is displayed.   <br />
                * If setting "tt" in format and not setting amDesignator/pmDesignator options,
                * it will show the string getting from the specified culture.    <br />
                * If not set, it will show "午前"/"午後" in Japanese culture and "AM"/"PM" in English culture.   <br />
                * If setting "t" in format and not setting amDesignator/pmDesignator options, it will show the string getting from current culture.  <br />
                * If not set, it will display "午" in Japanese culture and "A"/"P" in English culture.  <br />
                */
                this.pmDesignator = "";
                /** A boolean value determines whether to express midnight as 24:00.
                */
                this.midnightAs0 = true;
                /** A boolean value determines the range of hours that can be entered in the control.
                * @remarks
                * If set this property to false,
                * the control sets the range for the hour field from 1 - 12.  If set to true
                * the range is set to 0 - 11.
                */
                this.hour12As0 = false;
                /** Determins whether or not the next control in the tab order receives
                * the focus as soon as the control is filled at the last character.
                */
                this.blurOnLastChar = false;
                /** Gets or set whether the focus automatically moves to the next or previous
                * tab ordering control when pressing the left, right arrow keys.
                */
                this.blurOnLeftRightKey = "none";
                /** Gets or sets whether the tab key moves the focus between controls or between
                * fields within the control, possible values is "field", "control".
                * @remarks
                * The caret moves to the next field when this property is "field".
                * If the caret is in the last field, the input focus leaves this control when pressing the TAB key.
                * If the value is "control", the behavior is similar to the standard control.
                */
                this.tabAction = "field";
                /** Determines how the control should interpret 2-digits year inputted in year field.
                * when the "smartInputMode" option is set to true.
                * @remarks
                * For example, if "startYear" is set to 1950 (the default value), and "smartInputMode" is true.   <br />
                * Enter 2-digit year value which is greater than 50 [e.g., 88]  <br />
                * ‘1988’ displays in year part.  <br />
                * Enter 2-digit year value which is less than 50 [e.g., 12]  <br />
                * ‘2012’ displays in year part.  <br />
                */
                this.startYear = 1950;
                /** Determines the character that appears when the widget has focus but no input has been entered.
                */
                this.promptChar = '';
                /** Determines whether the control should interpret 2-digits year inputted in year field.
                * using the value provided in the "startYear" option.
                * @remarks
                * For example, when "smartInputMode" is false (the default value), and "startYear" is 1950. <br />
                * Enter 2-digit year value which is greater than 50 [e.g., 88]  <br />
                * ‘0088’ displays in year part.    <br />
                * Enter 2-digit year value which is less than 50 [e.g., 12]  <br />
                * ‘0012’ displays in year part.  <br />
                * Set "smartInputMode" to true.  <br />
                * Enter 2-digit year value which is greater than 50 [e.g., 88]  <br />
                * ‘1988’ displays in year part when smartInputMode is true.   <br />
                * Enter 2-digit year value which is less than 50 [e.g., 12]  <br />
                * ‘2012’ displays in year part. <br />
                */
                this.smartInputMode = false;
                /** Determines the active field index.
                */
                this.activeField = 0;
                /** Determines the time span, in milliseconds,
                * between two input intentions.
                * @remarks
                * when press a keyboard, and the widget will delay a time and then handle
                * the next keyboard press. Use this option to control the speed of the key press.
                */
                this.keyDelay = 800;
                /** Determines whether to automatically moves to the next field.
                * @remarks
                * For example, if user want input the '2012-9-20' in inputdate widget,
                * if this option's value is true, when user type '2012' in textbox,
                * it will auto focus in next field, user can type '9' in second field,
                * if this option's value is false, user want to type '9' in second field,
                * they should focus the second field by manual.
                */
                this.autoNextField = true;
                /** This option will supply an element to init the calendar widget
                * @ignore
                * @remarks
                * If the value is 'default', the widget will create a div and
                * append it to body element, and using this element to init calendar.
                * User can set this option value to an element,
                * and the widget will init the calendar using this element.
                */
                this.calendar = null;
                /** Detemines the popup position of a calendar.
                * See jQuery.ui.position for position options.
                * @example
                * // In the following example, the Y offset between the popup position and wijinputdate is 10 pixel.
                * $("#textbox1").wijinputdate({
                *     popupPosition: { offset: '0 10' },
                *     comboItems: [{ label: "first Day", value: new Date(2013, 1, 1) },
                *         { label: "second day", value: new Date(2013, 3, 3) },
                *         { label: "third day", value: new Date(2013, 4, 5) }]
                * });
                */
                this.popupPosition = {
                    offset: '0 4'
                };
                /** The afterSlide event handler.
                * A function called after the calendar view slided to another month.
                * Cancellable.
                * @event
                */
                this.afterSlide = null;
                /** Gets or sets whether to highlight the control's Text on receiving input focus.
                * possible values is "field", "all" .
                * @example
                * $("#textbox1").wijinputdate({
                *     highlightText: "field"
                * });
                */
                this.highlightText = "field";
                /** Determines how much to increase/decrease the active field when performing spin on the the active field.
                * @example
                * $("#textbox1").wijinputdate({
                *     increment: 2
                * });
                */
                this.increment = 1;
                /** Determines the input method setting of widget.
                * Possible values are: 'auto', 'active', 'inactive', 'disabled'
                * @remarks
                * This property only take effect on IE and firefox browser.
                */
                this.imeMode = "auto";
                /** Determines whether dropdown button is displayed.
                */
                this.showDropDownButton = true;
                /** Determines whether dropdown button is displayed.
                */
                this.showTrigger = undefined;
                /** An object contains the settings for the dropdown list.
                * @example
                * //  The following code show the dropdown calendar, dropdown list,
                * //  and set the dorpdown window's width to 100px, height to 30px;
                * $(".selector").wijinputdate({
                *     pickers: {
                *         calendar: {},
                *         list: [{ label: 'item1', value: 1 }],
                *         width: 100,
                *         height: 30
                *     }
                * });
                *
                * // The following code show the dropdown date picker and dropdown time picker,
                * // also it sets the time picker's format ot "hh hh:mm".
                * $(".selector").wijinputdate({
                *     pickers: {
                *         datePicker: {},
                *         timePicker: { format: "tt hh:mm" }
                *     }
                * });
                *
                * // The following code shows the drpdown date picker and dropdown time picker.
                * // also it sets the date picker's format to "yyyy/MMMM/dd".
                * $(".selector").wijinputdate({
                *     pickers: {
                *         datePicker: { format: "yyyy/MMMM/dd" },
                *         timePicker: {}
                *     }
                * });
                */
                this.pickers = {
                    list: undefined,
                    width: undefined,
                    height: undefined,
                    calendar: undefined,
                    datePicker: undefined,
                    timePicker: undefined
                };
                /** The dateChanged event handler.
                * A function called when the date of the input is changed.
                * @event
                * @dataKey {Date} date The data with this event.
                */
                this.dateChanged = null;
                /** The spinUp event handler.
                * A function called when spin up event fired.
                * @event
                */
                this.spinUp = null;
                /** The spinDown event handler.
                * A function called when spin down event fired.
                * @event
                */
                this.spinDown = null;
                /** The valueBoundsExceeded event hander.
                * A function called when the valueBoundExceeded event fired.
                * @event
                */
                this.valueBoundsExceeded = null;
            }
            return wijinputdate_options;
        })();
        wijinputdate.prototype.options = $.extend(true, {}, input.wijinputcore.prototype.options, new wijinputdate_options());

        $.wijmo.registerWidget("wijinputdate", wijinputdate.prototype);

        /** @ignore */
        var wijDateTextProvider = (function () {
            function wijDateTextProvider(inputWidget, format, displayFormat) {
                this.inputWidget = inputWidget;
                this._disableSmartInputMode = false;
                this.paddingZero = input.paddingZero;
                this.formatter = new input.wijDateTextFormatter(inputWidget, format, false);
                displayFormat = displayFormat == "" ? format : displayFormat;
                this.displayFormatter = new input.wijDateTextFormatter(inputWidget, displayFormat, true);
            }
            wijDateTextProvider.prototype.initialize = function () {
            };

            wijDateTextProvider.prototype.getFiledText = function (index) {
                var desc = this.formatter.fields[index];
                return desc.getText();
            };

            wijDateTextProvider.prototype.getFieldCount = function () {
                return this.formatter.fields.length;
            };

            wijDateTextProvider.prototype.getFieldRange = function (index) {
                if (index >= this.formatter.fields.length) {
                    index = this.formatter.fields.length - 1;
                }
                var desc = this.formatter.fields[index];
                return {
                    start: desc.startIndex,
                    end: desc.startIndex + desc.getText().length
                };
            };

            wijDateTextProvider.prototype.getAllRange = function () {
                return {
                    start: 0,
                    end: this.formatter.toString().length
                };
            };

            wijDateTextProvider.prototype.getCursorField = function (pos) {
                if (this.formatter.desPostions.length == 0) {
                    return 0;
                }

                pos = Math.min(pos, this.formatter.desPostions.length - 1);
                pos = Math.max(pos, 0);
                var desc = this.formatter.desPostions[pos].desc, i;
                if (desc.type === -1) {
                    i = $.inArray(desc, this.formatter.descriptors);
                    if (i > 0 && this.formatter.descriptors[i - 1].type !== -1) {
                        desc = this.formatter.descriptors[i - 1];
                    } else {
                        return -1;
                    }
                }
                return $.inArray(desc, this.formatter.fields);
            };

            wijDateTextProvider.prototype.needToMove = function (index, pos, ch) {
                if (!this.inputWidget._isValidDate(this.inputWidget._safeGetDate(), true)) {
                    return false;
                }

                var desc = this.formatter.fields[index];
                switch (desc.type) {
                    case 72:
                    case 73:
                    case 74:
                        for (var i = 0; i < input.DateTimeInfo.GetEraCount(); i++) {
                            if ((ch.toLowerCase() === input.DateTimeInfo.GetEraShortcuts()[i].toLowerCase()) || (ch.toLowerCase() === input.DateTimeInfo.GetEraShortNames()[i].toLowerCase()) || (ch.toLowerCase() === input.DateTimeInfo.GetEraAbbreviations()[i].toLowerCase()) || (ch.toLowerCase() === input.DateTimeInfo.GetEraNames()[i].toLowerCase())) {
                                return true;
                            }
                        }
                        return false;
                }

                var val = parseInt(ch, 10);
                if (pos === desc.maxLen) {
                    return true;
                }

                if (isNaN(val)) {
                    return false;
                }

                var lastInputChar = this.inputWidget.element.data("lastInputChar");
                switch (desc.type) {
                    case 10:
                        return (this._isSmartInputMode() && pos === 2);
                    case 20:
                    case 25:
                    case 45:
                    case 46: {
                        if (lastInputChar == "0" && val == 1) {
                            return true;
                        }
                        return val > 1;
                    }
                    case 47:
                    case 48: {
                        if (lastInputChar == "0" && val <= 2) {
                            return true;
                        }
                        return val > 2;
                    }
                    case 30:
                    case 31: {
                        if (lastInputChar == "0" && val <= 3) {
                            return true;
                        }
                        return val > 3;
                    }
                    case 50:
                    case 51:
                    case 60:
                    case 61: {
                        if (lastInputChar == "0" && val <= 6) {
                            return true;
                        }
                        return val > 6;
                    }
                    case 70:
                    case 71:
                        return false;
                }

                return false;
            };

            wijDateTextProvider.prototype._isEraFormatExist = function () {
                return this.formatter._isEraFormatExist();
            };

            wijDateTextProvider.prototype._getCulture = function () {
                return this.inputWidget._getCulture();
            };

            wijDateTextProvider.prototype._isDigitString = function (s) {
                s = $.trim(s);
                if (s.length === 0) {
                    return true;
                }

                var c = s.charAt(0), f, t;
                if (c === '+' || c === '-') {
                    s = s.substr(1);
                    s = $.trim(s);
                }
                if (s.length === 0) {
                    return true;
                }
                try  {
                    f = parseFloat(s);
                    t = f.toString();
                    return t === s;
                } catch (e) {
                    return false;
                }
            };

            wijDateTextProvider.prototype._setFormat = function (format) {
                return this.formatter._setFormat(format);
            };

            wijDateTextProvider.prototype._setDisplayFormat = function (displayFormat) {
                return this.displayFormatter._setFormat(displayFormat);
            };

            wijDateTextProvider.prototype._internalSetDate = function (date) {
                if (this.inputWidget) {
                    this.inputWidget._internalSetDate(date);
                }
            };

            wijDateTextProvider.prototype.toString = function () {
                if (this.inputWidget._isEraFormatExist()) {
                    if (this.inputWidget.options.date != null) {
                        var minDate = this.inputWidget._getRealEraMinDate();
                        var maxDate = this.inputWidget._getRealEraMaxDate();
                        if (this.inputWidget.options.date < minDate || this.inputWidget.options.date > maxDate) {
                            return "";
                        }
                    }
                }

                if (!this.inputWidget.isFocused()) {
                    if (this.inputWidget.isDateNull() && this.inputWidget._getInnerNullText() != null) {
                        return this.inputWidget._getInnerNullText();
                    } else {
                        return this.displayFormatter.toString();
                    }
                }

                return this.formatter.toString();
            };

            wijDateTextProvider.prototype.parseDate = function (str) {
                var date;

                //if (this.formatter.pattern === 'dddd' ||
                //    this.formatter.pattern === 'ddd' ||
                //    typeof str === 'object') {
                //    try {
                //        date = new Date(str);
                //        if (isNaN(date)) {
                //            date = new Date();
                //        }
                //    }
                //    catch (e) {
                //        date = new Date();
                //    }
                //} else {
                //    date = Globalize.parseDate(str, this.formatter.pattern, this._getCulture());
                //    if (!date) {
                //        date = this._tryParseDate(str, this.formatter.pattern);
                //    }
                //    if (!date) {
                //        date = null;
                //    }
                //}
                date = $.wijinputcore.parseDate(str, this.formatter.pattern, this._getCulture());

                return date;
            };

            wijDateTextProvider.prototype.setText = function (value) {
                if (value === "") {
                    this._internalSetDate(null);
                } else {
                    var date = new Date(value);
                    if (isNaN(date.getTime())) {
                        date = this.parseDate(value);
                    }

                    if (date == null) {
                        this._internalSetDate(new Date(value));
                    } else {
                        this._internalSetDate(date);
                    }
                }

                return true;
            };

            wijDateTextProvider.prototype.haveEnumParts = function () {
                return false;
            };

            wijDateTextProvider.prototype.removeLiterals = function (s) {
                s = '' + s + '';
                s = s.replace(new RegExp('[+]', 'g'), '');
                s = s.replace(new RegExp('[.]', 'g'), '');
                s = s.replace(new RegExp('[:]', 'g'), '');
                s = s.replace(new RegExp('[-]', 'g'), '');
                s = s.replace(new RegExp('[()=]', 'g'), '');
                return s;
            };

            wijDateTextProvider.prototype.getFirstDelimiterPos = function (aText, bText) {
                var i = 0, j = 0, ch1, ch2;
                while (i < bText.length && j < aText.length) {
                    ch1 = bText.charAt(i);
                    ch2 = aText.charAt(j);
                    if (ch1 === ch2) {
                        j++;
                    } else {
                        return j - 1;
                    }
                    i++;
                }
                return aText.length - 1;
            };

            wijDateTextProvider.prototype.isFieldSep = function (value, activeField) {
                var nextField = activeField++, desc;
                if (nextField < this.formatter.descriptors.length) {
                    desc = this.formatter.descriptors[nextField];
                    if (desc.type !== -1) {
                        return false;
                    }
                    return (value === desc.text);
                }

                return false;
            };

            wijDateTextProvider.prototype.getPositionType = function (pos) {
                var desPos = this.formatter.desPostions[pos];
                return desPos.desc.type;
            };

            wijDateTextProvider.prototype.addToField = function (value, activeField, pos) {
                var desc = this.formatter.fields[activeField], txt, resultObj, ret;

                txt = value;
                resultObj = { val: value, pos: 0, offset: 0, isreset: false };
                this.inputWidget.element.data('typing', true);
                ret = desc.setText(txt, ((value.length === 1) ? false : true), resultObj, this._isSmartInputMode());
                this.inputWidget.element.data('typing', false);
                return ret;
            };

            wijDateTextProvider.prototype.insertAt = function (strInput, position, rh) {
                if (typeof rh === "undefined") { rh = new input.wijInputResult(); }
                rh.testPosition = -1;
                var desPos, oldTxt, pos, txt, tryToExpandAtRight, result, tryToExpandAtLeft, curInsertTxt, resultObj, prevTextLength, posAdjustValue, altInsertText, newTextLength, diff, s, delimOrEndPos, delta;
                if (strInput.length === 1) {
                    desPos = this.formatter.desPostions[position];
                    if (desPos && desPos.desc.type === -1) {
                        if (desPos.text === strInput) {
                            rh.testPosition = position;
                            rh.hint = rh.characterEscaped;
                            return true;
                        }
                    }
                }

                oldTxt = strInput;
                pos = position;
                strInput = this.removeLiterals(strInput);
                txt = strInput;
                tryToExpandAtRight = false;
                tryToExpandAtLeft = false;
                if (pos > 0 && txt.length === 1) {
                    pos--;
                    position = pos;
                    desPos = this.formatter.desPostions[pos];
                    tryToExpandAtRight = true;
                    if (desPos && (desPos.desc.type === -1 || desPos.desc.getText().length !== 1)) {
                        position++;
                        pos++;
                        tryToExpandAtRight = false;
                    }
                }
                result = false;
                while (txt.length > 0 && pos < this.formatter.desPostions.length) {
                    desPos = this.formatter.desPostions[pos];
                    if (desPos.desc.type === -1) {
                        pos = pos + desPos.length;
                        continue;
                    }
                    if (desPos.desc.needAdjustInsertPos()) {
                        curInsertTxt = txt.substr(0, (desPos.length - desPos.pos));
                        curInsertTxt = desPos.text.slice(0, desPos.pos) + curInsertTxt + desPos.text.slice(desPos.pos + curInsertTxt.length, desPos.length);
                        if (tryToExpandAtRight) {
                            curInsertTxt = desPos.text + curInsertTxt;
                        }
                        if (tryToExpandAtLeft) {
                            curInsertTxt = curInsertTxt + desPos.text;
                        }
                        prevTextLength = desPos.desc.getText().length;
                        altInsertText = '';
                        try  {
                            if (strInput.length === 1) {
                                if (!desPos.pos) {
                                    altInsertText = strInput;
                                } else if (desPos.pos > 0) {
                                    altInsertText = curInsertTxt.substring(0, desPos.pos + 1);
                                }
                            }
                        } catch (e) {
                        }
                        if (prevTextLength === 1 && curInsertTxt.length > 1 && strInput.length === 1) {
                            if (desPos.desc.type === 31 || desPos.desc.type === 25) {
                                this._disableSmartInputMode = true;
                            }
                        }
                        resultObj = {
                            val: strInput, pos: desPos.pos,
                            offset: 0, isreset: false
                        };
                        result = desPos.desc.setText(curInsertTxt, ((strInput.length === 1) ? false : true), resultObj);
                        this._disableSmartInputMode = false;
                        if (!result && typeof (altInsertText) !== 'undefined' && altInsertText.length > 0 && (desPos.desc.type === 26 || desPos.desc.type === 27 || desPos.desc.type === 100 || desPos.desc.type === 101 || desPos.desc.type === 250 || desPos.desc.type === 251)) {
                            result = desPos.desc.setText(altInsertText, ((strInput.length === 1) ? false : true), resultObj);
                        }
                        if (result) {
                            rh.hint = rh.success;
                            rh.testPosition = pos + resultObj.offset;
                            if (strInput.length === 1) {
                                newTextLength = desPos.desc.getText().length;
                                posAdjustValue = desPos.pos;
                                if (desPos.pos > (newTextLength - 1)) {
                                    posAdjustValue = newTextLength;
                                }
                                diff = newTextLength - prevTextLength;
                                if (diff > 0 && desPos.pos === prevTextLength - 1) {
                                    posAdjustValue = newTextLength - 1;
                                }
                                s = this.toString();
                                rh.testPosition = desPos.desc.startIndex + posAdjustValue + resultObj.offset;
                            }
                            txt = txt.slice(desPos.length - desPos.pos, txt.length);
                        } else {
                            rh.hint = rh.invalidInput;
                            if (rh.testPosition !== -1) {
                                rh.testPosition = position;
                            }
                            if (desPos.desc.type !== -1 && strInput.length === 1) {
                                return false;
                            }
                        }
                        pos = pos + desPos.length;
                    } else {
                        delimOrEndPos = this.getFirstDelimiterPos(txt, oldTxt);
                        if (delimOrEndPos < 0) {
                            delimOrEndPos = 0;
                        }
                        curInsertTxt = txt.substring(0, delimOrEndPos + 1);
                        resultObj = {
                            val: strInput, pos: desPos.pos,
                            offset: 0, isreset: false
                        };
                        result = desPos.desc.setText(curInsertTxt, ((strInput.length === 1) ? false : true), resultObj);
                        if (result) {
                            rh.hint = rh.success;
                            rh.testPosition = pos + resultObj.offset;
                            txt = txt.slice(delimOrEndPos + 1, txt.length);
                        } else {
                            rh.hint = rh.invalidInput;
                            if (rh.testPosition !== -1) {
                                rh.testPosition = position;
                            }
                        }
                        if (delimOrEndPos < 0) {
                            delimOrEndPos = 0;
                        }
                        delta = delimOrEndPos + 1;
                        pos = pos + delta;
                    }
                }
                return result;
            };

            wijDateTextProvider.prototype.removeAt = function (start, end, rh, skipCheck) {
                try  {
                    var desPos = this.formatter.desPostions[start], curInsertTxt, pos, resultObj, result, widget = this.inputWidget, element = widget.element, dateLength = element.val().length;

                    if (dateLength === end + 1 && start === 0) {
                        widget.isDeleteAll = true;
                    }
                    if (desPos.desc.needAdjustInsertPos()) {
                        curInsertTxt = '0';
                        pos = start;
                        desPos.text = desPos.desc.getText();
                        curInsertTxt = desPos.text.slice(0, desPos.pos) + curInsertTxt + desPos.text.slice(desPos.pos + curInsertTxt.length, desPos.length);

                        if (desPos.desc.name === 'tt') {
                            curInsertTxt = "AM";
                        } else if (desPos.desc.name === 't') {
                            curInsertTxt = "A";
                        } else if (desPos.desc.formatString === 'ee') {
                            curInsertTxt = "01";
                        } else if (desPos.desc.formatString === 'e') {
                            curInsertTxt = "1";
                        }

                        resultObj = {
                            val: curInsertTxt, pos: desPos.pos, offset: 0,
                            isreset: true, isfullreset: false
                        };
                        if ((end - start + 1) >= desPos.length) {
                            resultObj.isfullreset = true;
                            start = start + desPos.length;
                            pos = start;
                        }
                        result = desPos.desc.setText(curInsertTxt, false, resultObj, this._isSmartInputMode());
                        if (result) {
                            rh.hint = rh.success;
                            rh.testPosition = pos;
                        } else {
                            rh.hint = rh.invalidInput;
                            if (rh.testPosition === -1) {
                                rh.testPosition = start;
                            }
                        }
                    }
                    if (start < end) {
                        this.removeAt(start + 1, end, rh);
                    }
                    return true;
                } catch (e) {
                    return false;
                }
            };

            wijDateTextProvider.prototype.incEnumPart = function () {
                var desc = this.formatter.fields[this.inputWidget.options.activeField];
                if (desc) {
                    desc.inc();
                }
                return true;
            };

            wijDateTextProvider.prototype.decEnumPart = function () {
                var desc = this.formatter.fields[this.inputWidget.options.activeField];
                if (desc) {
                    desc.dec();
                }
                return true;
            };

            wijDateTextProvider.prototype._isSmartInputMode = function () {
                if (this._disableSmartInputMode) {
                    return false;
                }
                if (this.inputWidget) {
                    return this.inputWidget.options.smartInputMode;
                }
                return true;
            };

            wijDateTextProvider.prototype._getInt = function (str, i, minlength, maxlength) {
                var x, token;
                for (x = maxlength; x >= minlength; x--) {
                    token = str.substring(i, i + x);
                    if (token.length < minlength) {
                        return null;
                    }
                    if ($.wij.charValidator.isDigit(token)) {
                        return token;
                    }
                }
                return null;
            };

            wijDateTextProvider.prototype._tryParseDate = function (val, pattern) {
                var ci = this._getCulture().calendars, pattern2, sep, patterns, d;
                pattern = pattern || ci.standard.patterns.d;
                if (pattern) {
                    if (pattern.indexOf('MMM') === -1 && pattern.indexOf('MMMM') === -1) {
                        pattern = pattern.replace('MM', 'M');
                    }
                    pattern = pattern.replace('dd', 'd');
                    pattern = pattern.replace('tt', 'a');
                }

                pattern2 = pattern.replace('yyyy', 'yy');
                sep = ci.standard["/"];
                patterns = [
                    pattern, pattern2, pattern.replace(new RegExp(sep, 'g'), '-'),
                    pattern2.replace(new RegExp(sep, 'g'), '-'),
                    pattern.replace(new RegExp(sep, 'g'), '.'),
                    pattern2.replace(new RegExp(sep, 'g'), '.')];
                d = Globalize.parseDate(val, patterns, this._getCulture());

                if (d) {
                    return d;
                }

                // if the val is datetime string,
                // parse the string to datetime. added by dail 2012-6-25
                d = new Date(val);
                if (d.toString() !== "Invalid Date" && val && val !== "") {
                    return d;
                }

                return 0;
            };

            wijDateTextProvider.prototype._formatDate = function (date, format, culture) {
                var _this = this;
                if (!(date.valueOf())) {
                    return '&nbsp;';
                }

                var cf = this.inputWidget._getCulture().calendars.standard, sRes = format.replace(new RegExp('yyyy|MMMM|MMM|MM|M|mm|m|dddd|ddd|dd|d|hh|h|HH|H|ss|s|tt|t|a/p', 'gi'), function (match) {
                    var h;
                    switch (match) {
                        case 'yyyy':
                            return input.paddingZero(date.getFullYear(), 4);
                        case 'MMMM':
                            return culture.dateTimeFormat.monthNames[date.getMonth()];
                        case 'MMM':
                            return culture.dateTimeFormat.abbreviatedMonthNames[date.getMonth()];
                        case 'MM':
                            return _this.paddingZero((date.getMonth() + 1), 2);
                        case 'M':
                            return _this.paddingZero((date.getMonth() + 1), 1);
                        case 'mm':
                            return _this.paddingZero(date.getMinutes(), 2);
                        case 'm':
                            return _this.paddingZero(date.getMinutes(), 1);
                        case 'dddd':
                            return culture.dateTimeFormat.dayNames[date.getDay()];
                        case 'ddd':
                            return culture.dateTimeFormat.abbreviatedDayNames[date.getDay()];
                        case 'dd':
                            return _this.paddingZero(date.getDate(), 2);
                        case 'd':
                            return _this.paddingZero(date.getDate(), 1);
                        case 'hh':
                            h = date.getHours() % 12;
                            return _this.paddingZero(((h) ? h : 12), 2);
                        case 'h':
                            h = date.getHours() % 12;
                            return _this.paddingZero(((h) ? h : 12), 1);
                        case 'HH':
                            return _this.paddingZero(date.getHours(), 2);
                        case 'H':
                            return _this.paddingZero(date.getHours(), 1);
                        case 'ss':
                            return _this.paddingZero(date.getSeconds(), 2);
                        case 's':
                            return _this.paddingZero(date.getSeconds(), 1);
                        case 'tt':
                            return (date.getHours() < 12) ? cf.AM[0] : cf.PM[0];
                        case 't':
                            return (date.getHours() < 12) ? ((cf.AM[0].length > 0) ? cf.AM[0].charAt(0) : '') : ((cf.PM[0].length > 0) ? cf.PM[0].charAt(0) : '');
                        case 'a/p':
                            return (date.getHours() < 12) ? 'a' : 'p';
                    }
                    return 'N';
                });
                return sRes;
            };

            wijDateTextProvider.prototype.replaceWith = function (range, text) {
                var index = range.start;
                var result = new input.wijInputResult();
                if (range.start < range.end) {
                    this.removeAt(range.start, range.end - 1, result, true);
                    index = result.testPosition;
                }
                return this.insertAt(text, index, result) ? result : null;
            };
            return wijDateTextProvider;
        })();
        input.wijDateTextProvider = wijDateTextProvider;
        ;
    })(wijmo.input || (wijmo.input = {}));
    var input = wijmo.input;
})(wijmo || (wijmo = {}));

;
/// <reference path="jquery.wijmo.wijstringinfo.ts"/>
/// <reference path="jquery.wijmo.wijinpututility.ts"/>
/// <reference path="jquery.wijmo.wijinputcore.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*
    * Depends:
    *	jquery-1.4.2.js
    *
    */
    (function (input) {
        var $ = jQuery;

        /** @ignore */
        var CharacterFilter = (function () {
            function CharacterFilter(label, owner, include) {
                this.filterLabel = label;
                this._include = include;
                this._owner = owner;
            }
            CharacterFilter.prototype.Check = function (text, index) {
                var retObj = {};
                retObj.success = false;
                retObj.strValue = "";
                retObj.index = index;

                // Check the character type.
                var checkingText = text.Substring(index, index + 1);

                var isValid = this.IsValid(checkingText);

                //	if ((isValid && this._include) || (!isValid && !this._include))
                //	{
                //		text = text.Substring(index, index + 1);
                //		index++;
                //
                //		retObj.strValue = text;
                //    	retObj.index = index;
                //		return retObj;
                //	}
                if (isValid) {
                    text = text.Substring(index, index + 1);
                    index++;

                    retObj.strValue = text;
                    retObj.index = index;
                    return retObj;
                }

                if (this._owner.GetAutoConvert() && (checkingText.length === 1 || checkingText.length === 3)) {
                    retObj = this.Convert(text, index);

                    if (retObj.success) {
                        return retObj;
                    }
                }

                return retObj;
            };

            CharacterFilter.prototype.IsValid = function (c) {
                if (c.length === 2 && (c.charCodeAt(1) === 0xff9e || c.charCodeAt(1) === 0xff9f)) {
                    // DaryLuo 2013/04/24 fix bug 1050 in IM Web 7.1
                    if (!input.CharProcess.CharEx.IsFullWidth(c) && input.CharProcess.CharEx.IsKatakana(c)) {
                        return this.IsValidTwoByte(c);
                    }
                }
                if (c.length > 1) {
                    return this.IsValidMoreByte(c);
                } else {
                    return this.IsValidTwoByte(c);
                }
            };

            CharacterFilter.prototype.IsValidTwoByte = function (c) {
                return false;
            };
            CharacterFilter.prototype.IsValidMoreByte = function (c) {
                return false;
            };

            CharacterFilter.prototype.Convert = function (text, index) {
                var retObj = {};
                retObj.success = true;
                retObj.strValue = "";
                retObj.index = index;

                var c = text.Substring(index, index + 1);

                var isValid;
                var charEx = input.CharProcess.CharEx;

                //if (true) {
                //    var charLength = {};
                //    var result = IVSCharHelper.ConvertedWithIVS(c, 0, charLength);
                //    if (result.length > 0) {
                //        isValid = this.IsValid(result);
                //        if (isValid) {
                //            index++;
                //            retObj.index = index;
                //            retObj.strValue = result;
                //            return retObj;
                //        }
                //    }
                //}
                // Convert between upper and lower alphabet automatically.
                if (charEx.IsAlphabet(c)) {
                    var r = charEx.IsLower(c) ? c.toUpperCase() : c.toLowerCase();
                    isValid = this.IsValid(r);
                    if ((isValid && this._include) || (!isValid && !this._include)) {
                        index++;
                        retObj.index = index;
                        retObj.strValue = r;
                        return retObj;
                        //return new string(r, 1);
                    }

                    c = charEx.IsFullWidth(c) ? charEx.ToHalfWidth(c) : charEx.ToFullWidth(c).text;
                    isValid = this.IsValid(c);
                    if ((isValid && this._include) || (!isValid && !this._include)) {
                        index++;
                        retObj.index = index;
                        retObj.strValue = c;
                        return retObj;
                        //return new string(c, 1);;
                    }
                    r = charEx.IsFullWidth(r) ? charEx.ToHalfWidth(r) : charEx.ToFullWidth(r).text;
                    isValid = this.IsValid(r);

                    if ((isValid && this._include) || (!isValid && !this._include)) {
                        index++;
                        retObj.index = index;
                        retObj.strValue = r;
                        return retObj;
                        //return new string(r, 1);;
                    }
                    retObj.success = false;
                    return retObj;
                }

                // Convert from Hiragana to DBCS/SBCS Katakana automatically.
                if (charEx.IsHiragana(c)) {
                    // Large < - > Small
                    if (charEx.IsLowerKana(c)) {
                        var u = charEx.ToUpperKana(c);
                        isValid = this.IsValid(u);
                        if ((isValid && this._include) || (!isValid && !this._include)) {
                            index++;
                            retObj.index = index;
                            retObj.strValue = u;
                            return retObj;
                        }
                    } else if (charEx.HasLowerKana(c)) {
                        var l = charEx.ToLowerKana(c);
                        isValid = this.IsValid(l);
                        if ((isValid && this._include) || (!isValid && !this._include)) {
                            index++;
                            retObj.index = index;
                            retObj.strValue = l;
                            return retObj;
                        }
                    }

                    c = charEx.ToKatakana(c);

                    // DaryLuo 2012/05/31 fix bug 116 in IM7. Add this.
                    isValid = this.IsValid(c);
                    if ((isValid && this._include) || (!isValid && !this._include)) {
                        index++;
                        retObj.index = index;
                        retObj.strValue = c;
                        return retObj;
                        //return new string(c, 1);
                    }

                    if (charEx.IsLowerKana(c)) {
                        var u = charEx.ToUpperKana(c);

                        // DaryLuo 2012/05/31 fix bug 116 in IM7. Add this.
                        isValid = this.IsValid(u);
                        if ((isValid && this._include) || (!isValid && !this._include)) {
                            index++;
                            retObj.index = index;
                            retObj.strValue = u;
                            return retObj;
                        }
                    } else if (charEx.HasLowerKana(c)) {
                        var l = charEx.ToLowerKana(c);
                        isValid = this.IsValid(l);
                        if ((isValid && this._include) || (!isValid && !this._include)) {
                            index++;
                            retObj.index = index;
                            retObj.strValue = l;
                            return retObj;
                        }
                    }

                    var chars = charEx.ToHalfWidthEx(c);
                    isValid = this.IsValid(chars);
                    if ((isValid && this._include) || (!isValid && !this._include)) {
                        index++;
                        retObj.index = index;
                        retObj.strValue = chars;
                        return retObj;
                        //return new string(chars);
                    }

                    if (charEx.IsLowerKana(chars)) {
                        chars = charEx.ToUpperKana(chars);
                        isValid = this.IsValid(chars);
                        if ((isValid && this._include) || (!isValid && !this._include)) {
                            index++;
                            retObj.index = index;
                            retObj.strValue = chars;
                            return retObj;
                        }
                    } else if (charEx.HasLowerKana(chars)) {
                        chars = charEx.ToLowerKana(chars);
                        isValid = this.IsValid(chars);
                        if ((isValid && this._include) || (!isValid && !this._include)) {
                            index++;
                            retObj.index = index;
                            retObj.strValue = chars;
                            return retObj;
                        }
                    }

                    retObj.success = false;
                    return retObj;
                }

                // Convert from Katakana to Hiragana (or DBCS <-> SBCS)automatically.
                if (charEx.IsKatakana(c)) {
                    // Large < - > Small
                    if (charEx.IsLowerKana(c)) {
                        var u = charEx.ToUpperKana(c);
                        isValid = this.IsValid(u);
                        if ((isValid && this._include) || (!isValid && !this._include)) {
                            index++;
                            retObj.index = index;
                            retObj.strValue = u;
                            return retObj;
                        }
                    } else if (charEx.HasLowerKana(c)) {
                        var l = charEx.ToLowerKana(c);
                        isValid = this.IsValid(l);
                        if ((isValid && this._include) || (!isValid && !this._include)) {
                            index++;
                            retObj.index = index;
                            retObj.strValue = l;
                            return retObj;
                        }
                    }

                    var r = c;
                    var processedAll = false;

                    // Check the soundex character.
                    if (charEx.IsFullWidth(c)) {
                        var newChars = charEx.ToHalfWidthEx(c);

                        if (newChars.GetLength() > 0) {
                            isValid = this.IsValid(newChars);
                            if ((isValid && this._include) || (!isValid && !this._include)) {
                                index++;
                                retObj.index = index;
                                retObj.strValue = newChars;
                                return retObj;
                                //return new string(newChars);
                            }
                        }

                        if (charEx.IsLowerKana(newChars)) {
                            newChars = charEx.ToUpperKana(newChars);
                            isValid = this.IsValid(newChars);
                            if ((isValid && this._include) || (!isValid && !this._include)) {
                                index++;
                                retObj.index = index;
                                retObj.strValue = newChars;
                                return retObj;
                            }
                        } else if (charEx.HasLowerKana(newChars)) {
                            newChars = charEx.ToLowerKana(newChars);
                            isValid = this.IsValid(newChars);
                            if ((isValid && this._include) || (!isValid && !this._include)) {
                                index++;
                                retObj.index = index;
                                retObj.strValue = newChars;
                                return retObj;
                            }
                        }
                    } else {
                        if (index == null) {
                            r = charEx.ToFullWidth(c).text;

                            if (!charEx.IsKatakana(r)) {
                                return retObj;
                            }

                            isValid = this.IsValid(r);
                            if ((isValid && this._include) || (!isValid && !this._include)) {
                                index++;
                                retObj.index = index;
                                retObj.strValue = r;
                                return retObj;
                            }
                        } else {
                            // To process what??? kyle.wang
                            if ((index + 1) < text.GetLength()) {
                                //r = charEx.ToFullWidthEx(out processedAll, new char[] {c, text[index + 1]});
                                var convertObj = charEx.ToFullWidth(text.Substring(index, index + 2));
                                r = convertObj.text;
                                processedAll = convertObj.processedAll;
                            } else {
                                r = charEx.ToFullWidth(c).text;
                            }

                            if (!charEx.IsKatakana(r)) {
                                return retObj;
                            }

                            isValid = this.IsValid(r);
                            if ((isValid && this._include) || (!isValid && !this._include)) {
                                index++;
                                if (processedAll) {
                                    index++;
                                }

                                retObj.index = index;
                                retObj.strValue = r;
                                return retObj;
                                //return new string(r, 1);
                            }
                        }

                        if (charEx.IsLowerKana(r)) {
                            var u = charEx.ToUpperKana(r);
                            isValid = this.IsValid(u);
                            if ((isValid && this._include) || (!isValid && !this._include)) {
                                index++;
                                retObj.index = index;
                                retObj.strValue = u;
                                return retObj;
                            }
                        } else if (charEx.HasLowerKana(r)) {
                            var l = charEx.ToLowerKana(r);
                            isValid = this.IsValid(l);
                            if ((isValid && this._include) || (!isValid && !this._include)) {
                                index++;
                                retObj.index = index;
                                retObj.strValue = l;
                                return retObj;
                            }
                        }
                    }

                    r = charEx.ToHiragana(r);
                    isValid = this.IsValid(r);
                    if ((isValid && this._include) || (!isValid && !this._include)) {
                        index++;
                        if (processedAll) {
                            index++;
                        }

                        retObj.index = index;
                        retObj.strValue = r;

                        //add by sj for bug 2955
                        if (r === '\u3094') {
                            if (processedAll) {
                                retObj.strValue = '\u3046' + '\u309B';
                            } else {
                                index--;
                                retObj.index = index;
                                retObj.strValue = "";
                                retObj.success = false;
                            }
                        }

                        //end by sj
                        return retObj;
                    }

                    if (charEx.IsLowerKana(r)) {
                        var u = charEx.ToUpperKana(r);
                        isValid = this.IsValid(u);
                        if ((isValid && this._include) || (!isValid && !this._include)) {
                            index++;
                            retObj.index = index;
                            retObj.strValue = u;
                            return retObj;
                        }
                    } else if (charEx.HasLowerKana(r)) {
                        var l = charEx.ToLowerKana(r);
                        isValid = this.IsValid(l);
                        if ((isValid && this._include) || (!isValid && !this._include)) {
                            index++;
                            retObj.index = index;
                            retObj.strValue = l;
                            return retObj;
                        }
                    }
                    //return new string(r, 1);;
                }

                // Convert between DBCS and SBCS automatically.
                c = charEx.IsFullWidth(c) ? charEx.ToHalfWidth(c) : charEx.ToFullWidth(c).text;
                isValid = this.IsValid(c);
                if ((isValid && this._include) || (!isValid && !this._include)) {
                    index++;
                    retObj.index = index;
                    retObj.strValue = c;
                    return retObj;
                    //return new string(c, 1);
                }

                retObj.success = false;
                return retObj;
            };
            return CharacterFilter;
        })();
        input.CharacterFilter = CharacterFilter;

        /** @ignore */
        var HalfWidthFilter = (function (_super) {
            __extends(HalfWidthFilter, _super);
            function HalfWidthFilter(owner, include) {
                _super.call(this, "HalfWidthFilter", owner, include);
            }
            HalfWidthFilter.prototype.IsValidTwoByte = function (c) {
                if (!input.CharProcess.CharEx.IsFullWidth(c)) {
                    return true;
                }

                if (c === '\x0D' || c === '\x0A') {
                    return true;
                }

                return false;
            };
            return HalfWidthFilter;
        })(CharacterFilter);

        /** @ignore */
        var FullWidthFilter = (function (_super) {
            __extends(FullWidthFilter, _super);
            function FullWidthFilter(owner, include) {
                _super.call(this, "FullWidthFilter", owner, include);
            }
            FullWidthFilter.prototype.IsValidTwoByte = function (c) {
                if (input.CharProcess.CharEx.IsFullWidth(c)) {
                    return true;
                }

                if (c === '\x0D' || c === '\x0A') {
                    return true;
                }

                return false;
            };
            return FullWidthFilter;
        })(CharacterFilter);

        /** @ignore */
        var HiraganaFilter = (function (_super) {
            __extends(HiraganaFilter, _super);
            function HiraganaFilter(owner, include) {
                _super.call(this, "HiraganaFilter", owner, include);
            }
            HiraganaFilter.prototype.IsValidTwoByte = function (c) {
                if (input.CharProcess.CharEx.IsHiragana(c)) {
                    return true;
                }

                if (c === '\x0D' || c === '\x0A') {
                    return true;
                }

                return false;
            };
            return HiraganaFilter;
        })(CharacterFilter);

        /** @ignore */
        var ShiftJISFilter = (function (_super) {
            __extends(ShiftJISFilter, _super);
            function ShiftJISFilter(owner, include) {
                _super.call(this, "ShiftJISFilter", owner, include);
            }
            ShiftJISFilter.prototype.IsValidTwoByte = function (c) {
                return input.CharProcess.CharEx.IsShiftJIS(c);
            };
            return ShiftJISFilter;
        })(CharacterFilter);

        /** @ignore */
        var JISX0208Filter = (function (_super) {
            __extends(JISX0208Filter, _super);
            function JISX0208Filter(owner, include) {
                _super.call(this, "JISX0208Filter", owner, include);
            }
            JISX0208Filter.prototype.IsValidTwoByte = function (c) {
                return input.CharProcess.CharEx.IsJISX0208(c);
            };
            return JISX0208Filter;
        })(CharacterFilter);

        /** @ignore */
        var DBCSHiraganaFilter = (function (_super) {
            __extends(DBCSHiraganaFilter, _super);
            function DBCSHiraganaFilter(owner, include) {
                _super.call(this, "DBCSHiraganaFilter", owner, include);
            }
            DBCSHiraganaFilter.prototype.IsValidTwoByte = function (c) {
                return input.CharProcess.CharEx.IsUpperKana(c) && input.CharProcess.CharEx.IsHiragana(c);
            };
            return DBCSHiraganaFilter;
        })(CharacterFilter);

        /** @ignore */
        var DBCSKatakanaFilter = (function (_super) {
            __extends(DBCSKatakanaFilter, _super);
            function DBCSKatakanaFilter(owner, include) {
                _super.call(this, "DBCSKatakanaFilter", owner, include);
            }
            DBCSKatakanaFilter.prototype.IsValidTwoByte = function (c) {
                return input.CharProcess.CharEx.IsFullWidth(c) && input.CharProcess.CharEx.IsKatakana(c) && !input.CharProcess.CharEx.IsLowerKana(c);
            };
            return DBCSKatakanaFilter;
        })(CharacterFilter);

        /** @ignore */
        var SBCSKatakanaFilter = (function (_super) {
            __extends(SBCSKatakanaFilter, _super);
            function SBCSKatakanaFilter(owner, include) {
                _super.call(this, "SBCSKatakanaFilter", owner, include);
            }
            SBCSKatakanaFilter.prototype.IsValidTwoByte = function (c) {
                return !input.CharProcess.CharEx.IsFullWidth(c) && input.CharProcess.CharEx.IsKatakana(c) && !input.CharProcess.CharEx.IsLowerKana(c);
            };
            return SBCSKatakanaFilter;
        })(CharacterFilter);

        /** @ignore */
        var SurrogateFilter = (function (_super) {
            __extends(SurrogateFilter, _super);
            function SurrogateFilter(owner, include) {
                _super.call(this, "SurrogateFilter", owner, include);
            }
            SurrogateFilter.prototype.IsValidTwoByte = function (c) {
                if (input.CharProcess.CharEx.IsSurrogatePair(c)) {
                    return true;
                }

                if (c === '\x0D' || c === '\x0A') {
                    return true;
                }

                return false;
            };

            SurrogateFilter.prototype.IsValidMoreByte = function (c) {
                for (var i = 0; i < c.length; i++) {
                    if (input.CharProcess.CharEx.IsSurrogate(c[i])) {
                        return true;
                    }
                }
                return false;
            };
            return SurrogateFilter;
        })(CharacterFilter);

        /** @ignore */
        var HalfWidthKatakanaFilter = (function (_super) {
            __extends(HalfWidthKatakanaFilter, _super);
            function HalfWidthKatakanaFilter(owner, include) {
                _super.call(this, "HalfWidthKatakanaFilter", owner, include);
            }
            HalfWidthKatakanaFilter.prototype.IsValidTwoByte = function (c) {
                if (!input.CharProcess.CharEx.IsFullWidth(c) && input.CharProcess.CharEx.IsKatakana(c)) {
                    return true;
                }

                if (c === '\x0D' || c === '\x0A') {
                    return true;
                }

                return false;
            };
            return HalfWidthKatakanaFilter;
        })(CharacterFilter);

        /** @ignore */
        var FullWidthKatakanaFilter = (function (_super) {
            __extends(FullWidthKatakanaFilter, _super);
            function FullWidthKatakanaFilter(owner, include) {
                _super.call(this, "FullWidthKatakanaFilter", owner, include);
            }
            FullWidthKatakanaFilter.prototype.IsValidTwoByte = function (c) {
                if (input.CharProcess.CharEx.IsFullWidth(c) && input.CharProcess.CharEx.IsKatakana(c)) {
                    return true;
                }

                if (c === '\x0D' || c === '\x0A') {
                    return true;
                }

                return false;
            };
            return FullWidthKatakanaFilter;
        })(CharacterFilter);

        /** @ignore */
        var HalfWidthSymbolsFilter = (function (_super) {
            __extends(HalfWidthSymbolsFilter, _super);
            function HalfWidthSymbolsFilter(owner, include) {
                _super.call(this, "HalfWidthSymbolsFilter", owner, include);
            }
            HalfWidthSymbolsFilter.prototype.IsValidTwoByte = function (c) {
                if (!input.CharProcess.CharEx.IsFullWidth(c) && input.CharProcess.CharEx.IsSymbol(c)) {
                    return true;
                }

                if (c === '\x0D' || c === '\x0A') {
                    return true;
                }

                return false;
            };
            return HalfWidthSymbolsFilter;
        })(CharacterFilter);

        /** @ignore */
        var FullWidthSymbolsFilter = (function (_super) {
            __extends(FullWidthSymbolsFilter, _super);
            function FullWidthSymbolsFilter(owner, include) {
                _super.call(this, "FullWidthSymbolsFilter", owner, include);
            }
            FullWidthSymbolsFilter.prototype.IsValidTwoByte = function (c) {
                if (input.CharProcess.CharEx.IsFullWidth(c) && input.CharProcess.CharEx.IsSymbol(c)) {
                    return true;
                }

                if (c === '\x0D' || c === '\x0A') {
                    return true;
                }

                return false;
            };
            return FullWidthSymbolsFilter;
        })(CharacterFilter);

        /** @ignore */
        var LimitedFilter = (function (_super) {
            __extends(LimitedFilter, _super);
            function LimitedFilter(includeChars, excludeChars, owner, include) {
                _super.call(this, "LimitedFilter", owner, include);
                this._includeChars = includeChars;
                this._excludeChars = excludeChars;
            }
            LimitedFilter.prototype.IsValidTwoByte = function (c) {
                if ((this._includeChars !== "" && this._includeChars.IndexOf(c) > -1) || (this._excludeChars !== "" && this._excludeChars.IndexOf(c) === -1)) {
                    return true;
                }

                if (c === '\x0D' || c === '\x0A') {
                    return true;
                }

                return false;
            };

            LimitedFilter.prototype.IsValidMoreByte = function (c) {
                if ((this._includeChars !== "" && this._includeChars.IndexOf(c) > -1) || (this._excludeChars !== "" && this._excludeChars.IndexOf(c) === -1)) {
                    return true;
                }

                if (c === '\x0D' || c === '\x0A') {
                    return true;
                }

                return false;
            };
            return LimitedFilter;
        })(CharacterFilter);

        /** @ignore */
        var RangeFilter = (function (_super) {
            __extends(RangeFilter, _super);
            function RangeFilter(startChar, endChar, owner, include) {
                _super.call(this, "RangeFilter", owner, include);
                this._startChar = startChar;
                this._endChar = endChar;
            }
            RangeFilter.prototype.IsValidTwoByte = function (c) {
                if (c >= this._startChar && c <= this._endChar) {
                    return true;
                }

                if (c === '\x0D' || c === '\x0A') {
                    return true;
                }

                return false;
            };
            return RangeFilter;
        })(CharacterFilter);

        /** @ignore */
        var UnionFilter = (function (_super) {
            __extends(UnionFilter, _super);
            function UnionFilter(owner, include) {
                _super.call(this, "UnionFilter", owner, include);
                this.filterArray = [];
            }
            UnionFilter.prototype.Add = function (filter) {
                if (filter == null) {
                    return;
                }

                //2012/08/17, Robin Hotfix Bug#37.
                if (filter.filterLabel === "HiraganaFilter") {
                    this.hiranagaFilter = filter;
                } else if (filter.filterLabel === "FullWidthKatakanaFilter") {
                    this.katakanaFilter = filter;
                }

                //End Hotfix Bug#37
                this.filterArray.push(filter);
            };

            UnionFilter.prototype.AddRange = function (filters) {
                for (var i = 0; i < filters.length; i++) {
                    this.Add(filters[i]);
                }
            };

            UnionFilter.prototype.IsValidTwoByte = function (c) {
                if (this.filterArray.length === 0) {
                    if (c === '\x0D' || c === '\x0A') {
                        return true;
                    }

                    return false;
                }
                var includeResult = false;
                var hasInclude = false;

                for (var i = 0; i < this.filterArray.length; i++) {
                    if (this.filterArray[i]._include) {
                        hasInclude = true;
                    }
                }

                //2012/08/17, Robin Hotfix Bug#37.
                // The char '\u30FC' is hiranaga while it is katakana type. See TextFilter for details.
                var isMixedJPChar = (c === '\u30FC');
                if (isMixedJPChar) {
                    if (this.hiranagaFilter && this.katakanaFilter) {
                        if (hasInclude) {
                            return true;
                        }
                    } else if (this.hiranagaFilter) {
                        return true;
                    } else if (this.katakanaFilter) {
                        return true;
                    }
                }

                for (var i = 0; i < this.filterArray.length; i++) {
                    if (this.filterArray[i].IsValid(c)) {
                        if (!this.filterArray[i]._include) {
                            return false;
                        } else {
                            includeResult = true;
                        }
                    } else {
                        if (!hasInclude) {
                            includeResult = true;
                        }
                    }
                }
                if (includeResult) {
                    return true;
                }

                if (c === '\x0D' || c === '\x0A') {
                    return true;
                }

                return false;
            };

            UnionFilter.prototype.IsValidMoreByte = function (c) {
                return this.IsValidTwoByte(c);
            };
            return UnionFilter;
        })(CharacterFilter);

        /** @ignore */
        var Field = (function () {
            function Field(label) {
                this.minLength = -1;
                this.maxLength = -1;
                this.text = "";
                this.oldText = "";
                this.fieldLabel = label;
            }
            Field.prototype.Snap = function () {
                var retObj = {};
                retObj.text = this.text;
                retObj.oldText = this.oldText;
                return retObj;
            };

            Field.prototype.Revert = function (snapPackage) {
                this.text = snapPackage.text;
                this.oldText = snapPackage.oldText;
            };

            Field.prototype.GetFieldText = function () {
                if (this.oldText == null) {
                    return null;
                } else {
                    return this.oldText;
                }
            };

            Field.prototype.GetText = function () {
                return this.text;
            };

            Field.prototype.SetText = function (text) {
                this.text = text;
            };

            Field.prototype.GetFillingString = function (promptChar) {
                if (!promptChar) {
                    return null;
                }

                var b = "";
                for (var a = 0; a < this.minLength; a++) {
                    b = b + promptChar;
                }

                return b;
            };

            Field.prototype.GetFieldStatus = function () {
                return 0;
            };

            Field.prototype.GetTextExcludeLiterals = function (start, sellength) {
                var textLength = this.text.GetLength();

                if (textLength < sellength) {
                    sellength = textLength;
                }

                var ret = this.text.Substring(start, sellength);
                ret = ret.replace(/[^\d]/g, '');

                return ret;
            };

            Field.prototype.SaveOldState = function () {
            };

            Field.prototype.RollBack = function () {
            };

            Field.prototype.PerformSpin = function (position, increment, wrap) {
                return 0;
            };

            Field.prototype.Insert = function (start, text, isLast, isSetText) {
            };

            Field.prototype.Replace = function (start, length, text) {
            };

            Field.prototype.Delete = function (start, length) {
            };

            Field.prototype.SaveUndoState = function () {
            };

            Field.prototype.Clear = function () {
                this.text = null;
            };

            Field.prototype.Undo = function () {
            };

            Field.prototype.SetTextInternal = function (text, start, isLast, validateText) {
            };

            Field.prototype.GetLength = function () {
                return this.text.GetLength() > this.minLength ? this.text.GetLength() : this.minLength;
            };
            return Field;
        })();
        input.Field = Field;

        /** @ignore */
        var PromptField = (function (_super) {
            __extends(PromptField, _super);
            function PromptField(text) {
                _super.call(this, "PromptField");
                this.text = text;
                this.minLength = this.text.GetLength();
                this.maxLength = this.text.GetLength();
            }
            PromptField.prototype.GetFillingString = function () {
                return this.text;
            };

            PromptField.prototype.SetText = function (text) {
                var retInfo = {};

                if (text === this.promptText) {
                    retInfo.existInvalid = false;
                    text = text.Substring(this.text.GetLength());
                } else {
                    retInfo.existInvalid = true;
                }

                retInfo.text = text;

                return retInfo;
            };

            PromptField.prototype.GetLength = function () {
                return this.text.GetLength();
            };
            return PromptField;
        })(Field);

        /** @ignore */
        var FilterField = (function (_super) {
            __extends(FilterField, _super);
            function FilterField(owner) {
                _super.call(this, "FilterField");
                this._minLength = 0;
                this._maxLength = 0;
                this._filter = new CharacterFilter();
                this._bitStates = null;
                this._oldBitState = null;
                this.undoText = "";
                this.undoTempText = "";
                this._undoBitState = null;
                this._trueLength = 0;
                this._bitState = null;
                this._owner = owner;
            }
            FilterField.prototype.GetPromptChar = function () {
                return this._owner.GetPromptChar();
            };

            FilterField.prototype.GetAutoConvert = function () {
                return this._owner.GetAutoConvert();
            };

            FilterField.prototype.FilterField = function (minlength, maxlength, filter, bitState) {
                if (minlength > maxlength) {
                    return false;
                }

                if (!filter) {
                    return false;
                }

                this._minLength = minlength;
                this._maxLength = maxlength;
                this._filter = filter;
                this._bitState = bitState;
                this._oldBitState = bitState;
                this._undoBitState = bitState;
                this._trueLength = 0;

                if (this._bitState != null) {
                    var length = 0;
                    while (this._bitState[length] != null) {
                        length++;
                    }

                    for (var i = length; i >= 0; i--) {
                        if (this._bitState[i] != null) {
                            if (this._bitState[i] === false) {
                                this._trueLength--;
                            }
                        } else if (this._bitState[i] == null) {
                            this._trueLength--;
                        } else {
                            break;
                        }
                    }
                }

                // Clear will init the text value with the prompt char.
                this.Clear();
                return true;
            };

            FilterField.prototype.InitialText = function (text) {
                while (text.IndexOf("@#GCD#@") != -1) {
                    text = text.replace("@#GCD#@", "\'");
                }

                while (text.IndexOf("@#GCM#@") != -1) {
                    text = text.replace("@#GCM#@", "\"");
                }

                this.text = text;
                this.oldText = text;
                this.undoText = text;
                this.undoTempText = text;
            };

            FilterField.prototype.GetFieldStatus = function () {
                if (this._trueLength >= this._minLength && this._trueLength > 0) {
                    return 2;
                }

                if (this._trueLength > 0 && this._trueLength < this._minLength) {
                    return 1;
                }

                return 0;
            };

            FilterField.prototype.GetFieldIsFull = function () {
                if (this._trueLength >= this._minLength && this._trueLength > 0) {
                    for (var i = 0; i < this._trueLength; i++) {
                        if (this._bitState[i] === false) {
                            return false;
                        }
                    }

                    return true;
                }

                return false;
            };

            FilterField.prototype.SetTextInternal = function (text, start, isLast, validateText) {
                var retObj = {};
                retObj.offset = start;
                retObj.text = text;
                retObj.existInvalid = false;
                retObj.exception = false;

                var existInvalid = false;

                if (start > this._maxLength || text === "" || text.GetLength() === 0) {
                    return retObj;
                }

                var newText = "";
                var position = 0;

                var tempBitState = [];
                var bitStartPos = start;
                for (var temp = 0; temp < start; temp++) {
                    tempBitState[temp] = this._bitState[temp];
                }
                while (position < text.GetLength()) {
                    var checkObj = this._filter.Check(text, position);
                    var result = checkObj.strValue;
                    position = checkObj.index;

                    if (result === "" && text.Substring(position, position + 1) !== this.GetPromptChar()) {
                        if (!isLast && start + newText.GetLength() >= this._minLength && start + newText.GetLength() === this._trueLength + newText.GetLength()) {
                            break;
                        }

                        existInvalid = true;
                        position++;
                        break;
                    } else {
                        if (result !== "") {
                            if (validateText && validateText !== "" && validateText.Substring(bitStartPos, bitStartPos + 1) === input.Utility.MaskValChar) {
                                newText += this.GetPromptChar();
                                tempBitState[bitStartPos] = false;
                            } else if (result === "\r" || result === "\n") {
                                newText += this.GetPromptChar();
                                tempBitState[bitStartPos] = false;
                            } else {
                                newText += result;
                                tempBitState[bitStartPos] = true;
                            }

                            bitStartPos++;
                            if (result.GetLength() === 2) {
                                tempBitState[bitStartPos] = true;
                                bitStartPos++;
                            }
                        } else {
                            newText += this.GetPromptChar();
                            position++;
                            tempBitState[bitStartPos] = false;
                            bitStartPos++;
                        }

                        if (start + newText.GetLength() === this._maxLength) {
                            break;
                        } else if (start + newText.GetLength() > this._maxLength) {
                            newText = newText.Substring(0, newText.GetLength() - 1);
                            break;
                        }
                    }
                }

                if (start + newText.GetLength() < this._minLength) {
                    text = text.Substring(position, text.GetLength() - position);
                    retObj.existInvalid = existInvalid;
                    retObj.exception = true;
                }

                var fieldText = this.text.Substring(0, start) + newText + this.text.Substring(start, this.text.GetLength());

                if (fieldText.GetLength() > this._maxLength) {
                    fieldText = fieldText.Substring(0, this._maxLength);
                }

                if (fieldText.GetLength() > start + newText.GetLength()) {
                    for (var i = 1; i <= fieldText.GetLength() - start - newText.GetLength(); i++) {
                        if (this._bitState[start + i] != null) {
                            tempBitState[bitStartPos] = this._bitState[start + i];
                            bitStartPos++;
                        }
                    }
                }

                this._bitState = new Array(bitStartPos);
                this._bitState = tempBitState;
                this._trueLength = bitStartPos;
                for (var i = bitStartPos - 1; i >= 0; i--) {
                    if (this._bitState[i] === false) {
                        this._trueLength--;
                    } else {
                        break;
                    }
                }

                if (fieldText.GetLength() < this._minLength) {
                    for (var i = 0; i < this._minLength - fieldText.GetLength(); i--) {
                        fieldText += this.GetPromptChar();
                    }
                }

                for (var i = fieldText.GetLength(); i > this._minLength; i--) {
                    if (fieldText.Substring(i - 1, i) === this.GetPromptChar() && i > this._trueLength) {
                        fieldText = fieldText.Substring(0, i - 1);
                    } else {
                        break;
                    }
                }

                this.text = fieldText;

                if (position === text.GetLength()) {
                    text = "";
                } else {
                    text = text.Substring(position, text.GetLength());
                }

                start += newText.GetLength();
                retObj.offset = start;
                retObj.text = text;
                return retObj;
            };

            FilterField.prototype.SaveOldState = function () {
                this.oldText = this.text;
                this._oldBitState = this._bitState;
            };

            FilterField.prototype.SaveUndoState = function () {
                this.undoText = this.text;
                this.undoTempText = this.text;
                this._undoBitState = this._bitState;
            };

            FilterField.prototype.GetValue = function () {
            };

            FilterField.prototype.GetText = function () {
                return this._text;
            };

            FilterField.prototype.UpdateState = function (submit) {
            };

            FilterField.prototype.RollBack = function () {
                if (this.oldText === this.text) {
                    return;
                } else {
                    var temp = this.oldText;
                    this.text = temp;
                    this._bitState = this._oldBitState;
                    this._trueLength = temp.GetLength();
                    for (var i = temp.GetLength() - 1; i >= 0; i--) {
                        if (this._bitState[i] == false) {
                            this._trueLength--;
                        } else {
                            break;
                        }
                    }
                }
            };

            FilterField.prototype.Undo = function () {
                if (this.undoTempText === this.text) {
                    return false;
                } else {
                    var temp = this.undoTempText;
                    this.undoTempText = this.text;
                    var tempBitState = this._bitState;
                    this.text = temp;
                    this._bitState = this._undoBitState;
                    this._trueLength = temp.GetLength();
                    if (this._bitState.length === 0) {
                        this._trueLength = 0;
                    } else {
                        for (var i = temp.GetLength() - 1; i >= 0; i--) {
                            if (this._bitState[i] === false) {
                                this._trueLength--;
                            } else {
                                break;
                            }
                        }
                    }
                    this._undoBitState = tempBitState;

                    return true;
                }
            };

            FilterField.prototype.Clear = function () {
                this._trueLength = 0;
                var retText = "";
                var tempBitStates = [];

                if (this._minLength > 0) {
                    for (var i = 0; i < this._minLength; i++) {
                        tempBitStates[i] = false;
                    }

                    this._bitState = new Array(this._minLength);
                    this._bitState = tempBitStates;

                    if (this.GetPromptChar() !== "") {
                        for (var i = 0; i < this._minLength; i++) {
                            retText += this.GetPromptChar();
                        }
                    } else {
                        for (var i = 0; i < this._minLength; i++) {
                            retText += " ";
                        }
                    }

                    this.text = retText;
                } else {
                    this.text = "";
                    this._bitStates = null;
                }
            };

            FilterField.prototype.Insert = function (start, text, isLast, isSetText) {
                if (!isSetText) {
                    isSetText = true;
                }

                var retObj = {};
                retObj.offset = start;
                retObj.text = text;
                retObj.existInvalid = false;
                retObj.exception = false;

                var existInvalid = false;

                if (start > this._maxLength || text === "" || text.GetLength() === 0) {
                    return retObj;
                }

                var tempBitState = [];
                var bitStartPos = start;
                for (var temp = 0; temp < start; temp++) {
                    tempBitState[temp] = this._bitState[temp];
                }

                var newText = "";
                var position = 0;
                while (position < text.GetLength()) {
                    var checkObj = this._filter.Check(text, position);
                    var result = checkObj.strValue;
                    position = checkObj.index;

                    if (result === "" && (isSetText || text.CharAt(position) !== " ")) {
                        if (!isLast && start + newText.GetLength() >= this._minLength && start + newText.GetLength() >= this._trueLength + newText.GetLength()) {
                            break;
                        }

                        existInvalid = true;
                        position++;
                        continue;
                    } else {
                        if (result === "" && !isSetText && text.CharAt(position) === " ") {
                            newText += this.GetPromptChar();
                            tempBitState[bitStartPos] = false;
                            bitStartPos++;
                            position++;
                        } else if (result === "\r" || result === "\n") {
                            newText += this.GetPromptChar();
                            tempBitState[bitStartPos] = false;
                            bitStartPos++;
                        } else {
                            newText += result;
                            tempBitState[bitStartPos] = true;
                            bitStartPos++;

                            if (result.GetLength() === 2) {
                                tempBitState[bitStartPos] = true;
                                bitStartPos++;
                            }
                        }

                        if (start + newText.GetLength() === this._maxLength) {
                            break;
                        } else if (start + newText.GetLength() > this._maxLength) {
                            newText = newText.Substring(0, newText.GetLength() - 1);
                            break;
                        }
                    }
                }

                if (newText.GetLength() === 0) {
                    text = text.Substring(position, text.GetLength() - position);
                    retObj.existInvalid = existInvalid;
                    retObj.exception = true;

                    return retObj;
                }

                var fieldText = this.text.Substring(0, start) + newText + this.text.Substring(start, this.text.GetLength());

                if (fieldText.GetLength() > this._maxLength) {
                    fieldText = fieldText.Substring(0, this._maxLength);
                }

                if (fieldText.GetLength() > start + newText.GetLength()) {
                    for (var i = 0; i < fieldText.GetLength() - start - newText.GetLength(); i++) {
                        if (this._bitState[start + i] != null) {
                            tempBitState[bitStartPos] = this._bitState[start + i];
                        } else {
                            tempBitState[bitStartPos] = false;
                        }
                        bitStartPos++;
                    }
                }

                this._bitState = new Array(bitStartPos);

                this._bitState = tempBitState;
                this._trueLength = bitStartPos;
                for (var i = bitStartPos - 1; i >= 0; i--) {
                    if (this._bitState[i] === false) {
                        this._trueLength--;
                    } else {
                        break;
                    }
                }

                if (fieldText.GetLength() < this._minLength) {
                    for (var i = 0; i < this._minLength - fieldText.GetLength(); i--) {
                        fieldText += this.GetPromptChar();
                    }
                }

                for (var i = fieldText.GetLength(); i > this._minLength; i--) {
                    if (fieldText.Substring(i - 1, i) === this.GetPromptChar() && i > this._trueLength) {
                        fieldText = fieldText.Substring(0, i - 1);
                    } else {
                        break;
                    }
                }

                this.text = fieldText;
                if (position === text.GetLength()) {
                    text = "";
                } else {
                    text = text.Substring(position, text.GetLength());
                }
                start += newText.GetLength();
                retObj.offset = start;
                retObj.text = text;

                return retObj;
            };

            FilterField.prototype.Replace = function (start, length, text, isLast) {
                var retObj = {};
                retObj.offset = start;
                retObj.text = text;
                if (length === 0) {
                    return retObj;
                }

                // DaryLuo 2013/07/09 fix bug 1014 in IM HTML 5.0.
                var charCode = text.charCodeAt(0);
                var excludeCharList = [12364, 12460, 12366, 12462, 12376, 12472];

                if (input.Utility.ArrayIndexOf(excludeCharList, charCode) !== -1 && length === 1) {
                    var checkResult = this._filter.Check(text, 0);
                    if (checkResult.strValue && checkResult.strValue.length === 2) {
                        length = 2;
                    }
                }
                start = this.Delete(start, length);
                retObj = this.Insert(start, text, isLast);

                return retObj;
            };

            FilterField.prototype.Delete = function (start, length) {
                if (length === 0 || start >= this.text.GetLength()) {
                    return start;
                }

                if (start + length > this.text.GetLength()) {
                    length = this.text.GetLength() - start;
                }

                var tempBitState = [];
                var bitStartPos = start;
                for (var temp = 0; temp < start; temp++) {
                    tempBitState[temp] = this._bitState[temp];
                }

                var fieldText = this.text.Substring(0, start) + this.text.Substring(start + length, this.text.GetLength());

                if (start + length < this.text.GetLength()) {
                    for (var i = 0; i < this.text.Substring(start + length, this.text.GetLength()).GetLength(); i++) {
                        if (this._bitState[start + length + i] != null) {
                            tempBitState[bitStartPos] = this._bitState[start + length + i];
                        } else {
                            tempBitState[bitStartPos] = false;
                        }

                        bitStartPos++;
                    }
                }

                if (bitStartPos < this._minLength) {
                    for (var i = bitStartPos; i < this._minLength; i++) {
                        tempBitState[i] = false;
                    }
                }

                this._bitState = new Array(bitStartPos);
                this._bitState = tempBitState;
                this._trueLength = bitStartPos;
                for (var i = bitStartPos - 1; i >= 0; i--) {
                    if (this._bitState[i] === false) {
                        this._trueLength--;
                    } else {
                        break;
                    }
                }

                if (fieldText.GetLength() < this._minLength) {
                    var addTime = this._minLength - fieldText.GetLength();
                    for (var i = 0; i < addTime; i++) {
                        fieldText += this.GetPromptChar();
                    }
                }

                this.text = fieldText;

                return start;
            };
            return FilterField;
        })(Field);

        /** @ignore */
        var EnumField = (function (_super) {
            __extends(EnumField, _super);
            function EnumField(owner) {
                _super.call(this, "EnumField");
                this._activeItem = -1;
                this._trueLength = 0;
                this._lastActiveItem = -1;
                this.undoText = "";
                this.undoTempText = "";
                this._undoItem = -1;
                this._minLength = 0;
                this._maxLength = 0;
                this._itemCount = 0;
                this._owner = owner;
            }
            EnumField.prototype.GetPromptChar = function () {
                return this._owner.GetPromptChar();
            };

            EnumField.prototype.GetText = function () {
                var retText = "";

                if (this._activeItem < 0) {
                    retText = input.Utility.ToString(this.GetPromptChar(), this._minLength);
                } else {
                    retText += this._items[this._activeItem];
                }

                return retText;
            };

            EnumField.prototype.GetFieldStatus = function () {
                return this._activeItem === -1 ? 0 : 2;
            };

            EnumField.prototype.GetFieldIsFull = function () {
                return this._activeItem === -1 ? false : true;
            };

            EnumField.prototype.IsOver = function () {
                return (this._activeItem !== -1);
            };

            EnumField.prototype.Init = function (items) {
                var minLength = Number.MAX_VALUE;
                var maxLength = Number.MIN_VALUE;
                for (var i = 0; i < items.length; i++) {
                    minLength = Math.min(minLength, items[i].length);
                    maxLength = Math.max(maxLength, items[i].length);
                }

                this.EnumField(minLength, maxLength, items, items.length, -1);
            };

            EnumField.prototype.EnumField = function (minlength, maxlength, items, itemCount, activeItem) {
                this._minLength = minlength;
                this._maxLength = maxlength;

                if (!items) {
                    return false;
                }

                this._itemCount = itemCount;
                this._activeItem = activeItem;
                this._lastActiveItem = activeItem;
                this._undoItem = activeItem;
                this.InitialItems(items);

                if (activeItem !== -1) {
                    this._trueLength = items[activeItem].toString().GetLength();
                } else {
                    this._trueLength = 0;
                }
                this.text = this.GetText();
            };

            EnumField.prototype.InitialItems = function (items) {
                this._items = new Array(items.length);

                for (var i = 0; i < items.length; i++) {
                    var tempText = items[i];
                    while (tempText.IndexOf("@#GCD#@") !== -1) {
                        tempText = tempText.replace("@#GCD#@", "\'");
                    }

                    while (tempText.IndexOf("@#GCM#@") !== -1) {
                        tempText = tempText.replace("@#GCM#@", "\"");
                    }

                    if (tempText) {
                        tempText = tempText.replace(/@#GCX0D#@/g, "\r").replace(/@#GCX0A#@/g, "\n");
                    }

                    this._items[i] = tempText;
                }
            };

            EnumField.prototype.InitialText = function (text) {
                while (text.IndexOf("@#GCD#@") !== -1) {
                    text = text.replace("@#GCD#@", "\'");
                }

                while (text.IndexOf("@#GCM#@") !== -1) {
                    text = text.replace("@#GCM#@", "\"");
                }

                if (text) {
                    text = text.replace(/@#GCX0D#@/g, "\r").replace(/@#GCX0A#@/g, "\n");
                }

                this.text = text;
                this.oldText = text;
                this.undoText = text;
                this.undoTempText = text;
            };

            EnumField.prototype.Insert = function (start, text, isLast) {
                var retObj = {};
                retObj.offset = start;
                retObj.text = text;
                retObj.existInvalid = false;
                retObj.exception = false;

                var old = start;
                var prefix = "";

                if (this._activeItem === -1) {
                    old = 0;
                }
                if (old !== 0) {
                    prefix = this._items[this._activeItem].toString().Substring(0, old);
                }

                var sameCharsIndex = new Array(this._itemCount);
                var textIndex = new Array(this._itemCount);
                var firstSamePos = new Array(this._itemCount);
                var invalidInfos = new Array(this._itemCount);
                for (var i = 0; i < this._itemCount; i++) {
                    sameCharsIndex[i] = old;
                    textIndex[i] = 0;
                    firstSamePos[i] = 99999;
                    invalidInfos[i] = new Array();
                }

                for (var i = 0; i < this._itemCount; i++) {
                    var item = this._items[i].toString();

                    if (prefix.GetLength() > 0 && item.Substring(0, prefix.GetLength()) !== prefix) {
                        continue;
                    }

                    while (textIndex[i] < text.GetLength()) {
                        if (sameCharsIndex[i] >= item.length) {
                            break;
                        }

                        var judgeInfo = this.JudgeIfValid(item, sameCharsIndex[i], text, textIndex[i]);

                        sameCharsIndex[i] = judgeInfo.index1;
                        textIndex[i] = judgeInfo.index2;
                        if (!judgeInfo.isValid) {
                            textIndex[i]++;
                        } else {
                            if (firstSamePos[i] === 99999) {
                                firstSamePos[i] = textIndex[i];
                            }
                        }
                    }
                }

                var itemIndex = 0;
                var sameCount = 0;
                var findOut = false;
                var maxPos = sameCharsIndex[itemIndex];
                for (var j = 0; j < this._itemCount; j++) {
                    var item = this._items[j].toString();
                    if (sameCharsIndex[j] === text.GetLength() + old && text.GetLength() === item.length) {
                        itemIndex = j;
                        maxPos = sameCharsIndex[itemIndex];
                        findOut = true;
                        break;
                    }

                    if (firstSamePos[j] === 99999) {
                        continue;
                    }

                    if (firstSamePos[itemIndex] >= firstSamePos[j]) {
                        if (firstSamePos[itemIndex] === firstSamePos[j]) {
                            var pos = sameCharsIndex[j];
                            if (maxPos < pos) {
                                itemIndex = j;
                                maxPos = pos;
                                sameCount = 1;
                            } else if (maxPos === pos)
                                sameCount++;
                        } else {
                            itemIndex = j;
                            maxPos = sameCharsIndex[itemIndex];
                            sameCount = 1;
                        }
                    }
                }
                var existInvalid;
                if (findOut) {
                    if (textIndex[itemIndex] === 0) {
                        existInvalid = true;
                        retObj.existInvalid = true;
                        return retObj;
                    }
                    text = text.Substring(textIndex[itemIndex] + 1, text.GetLength());
                    start = this._items[itemIndex].toString().GetLength();
                    existInvalid = invalidInfos[itemIndex].Count === 0 ? false : true;

                    this._activeItem = itemIndex;
                    this.text = this._items[itemIndex].toString();
                    this._trueLength = this._items[itemIndex].toString().GetLength();

                    retObj.offset = start;
                    retObj.text = text;
                    retObj.existInvalid = existInvalid;
                    return retObj;
                } else {
                    if (maxPos === old) {
                        if (isLast === false && this._activeItem !== -1 && start === this._items[this._activeItem].toString().GetLength()) {
                            text = text.Substring(textIndex[itemIndex], text.GetLength());
                            existInvalid = false;
                            retObj.offset = start;
                            retObj.text = text;
                            return retObj;
                        } else {
                            existInvalid = true;
                            retObj.exception = true;
                            retObj.existInvalid = true;
                            return retObj;
                        }
                    }

                    var source = -1;
                    for (var i = 0; i < invalidInfos[itemIndex].Count; i++) {
                        source = 0;
                    }

                    if (sameCount === 1) {
                        start = this._items[itemIndex].toString().GetLength();
                    } else {
                        start = maxPos;
                    }

                    if (source === -1) {
                        text = text.Substring(textIndex[itemIndex], text.GetLength());
                        existInvalid = false;
                    } else {
                        text = text.Substring(textIndex[itemIndex], text.GetLength());
                        existInvalid = true;
                    }

                    this._activeItem = itemIndex;
                    this.text = this._items[itemIndex].toString();
                    this._trueLength = this._items[itemIndex].toString().GetLength();
                    retObj.offset = start;
                    retObj.text = text;
                    return retObj;
                }
            };

            EnumField.prototype.Replace = function (start, length, text, isLast) {
                return this.Insert(start, text, isLast);
            };

            EnumField.prototype.Delete = function (start, length) {
                if (length === 0 || start >= this.text.GetLength()) {
                    return start;
                }
                start = 0;
                this._activeItem = -1;
                this.text = "";
                if (this._minLength > 0) {
                    for (var i = 0; i < this._minLength; i++) {
                        this.text += this.GetPromptChar();
                    }
                }
                this._trueLength = 0;

                return start;
            };

            EnumField.prototype.SaveOldState = function () {
                this._lastActiveItem = this._activeItem;
                this.oldText = this.text;
            };

            EnumField.prototype.RollBack = function () {
                if (this.oldText === this.text) {
                    return;
                } else {
                    var tempItem = this._lastActiveItem;
                    this._activeItem = tempItem;
                    if (tempItem >= 0 && tempItem < this._itemCount) {
                        this.text = this._items[tempItem].toString();
                    } else {
                        this.text = "";
                        for (var i = 0; i < this._minLength; i++) {
                            this.text += this.GetPromptChar();
                        }
                    }

                    var plength = 0;
                    for (var i = this.text.GetLength(); i > 0; i--) {
                        if (this.text.Substring(i - 1, i) === this.GetPromptChar()) {
                            plength++;
                        } else {
                            break;
                        }
                    }
                    this._trueLength = this.text.GetLength() - plength;
                }
            };

            EnumField.prototype.SaveUndoState = function () {
                this.undoText = this.text;
                this.undoTempText = this.text;
                this._undoItem = this._activeItem;
            };

            EnumField.prototype.Undo = function () {
                if (this.undoTempText === this.text) {
                    return;
                } else {
                    this.undoTempText = this.text;
                    var tempItem = this._activeItem;
                    this._activeItem = this._undoItem;
                    this._undoItem = tempItem;
                    if (this._activeItem >= 0 && this._activeItem < this._itemCount) {
                        this.text = this._items[this._activeItem].toString();
                    } else {
                        this.text = "";
                        for (var i = 0; i < this._minLength; i++) {
                            this.text += this.GetPromptChar();
                        }
                    }

                    var plength = 0;
                    for (var i = this.text.GetLength(); i > 0; i--) {
                        if (this.text.Substring(i - 1, i) === this.GetPromptChar()) {
                            plength++;
                        } else {
                            break;
                        }
                    }
                    this._trueLength = this.text.GetLength() - plength;
                }
            };

            EnumField.prototype.SetTextInternal = function (text, start, isLast, validateText) {
                var i;
                var textIndex = new Array(this._itemCount);
                var itemPoss = new Array(this._itemCount);
                var existInvalids = new Array(this._itemCount);

                for (i = 0; i < this._itemCount; i++) {
                    textIndex[i] = 0;
                    itemPoss[i] = 0;
                    existInvalids[i] = false;
                }

                for (i = 0; i < this._itemCount; i++) {
                    var item = this._items[i].toString();
                    while (textIndex[i] < text.GetLength()) {
                        var judgeInfo = this.JudgeIfValid(item, itemPoss[i], text, textIndex[i]);

                        itemPoss[i] = judgeInfo.index1;
                        textIndex[i] = judgeInfo.index2;
                        if (!judgeInfo.isValid && isLast === true) {
                            existInvalids[i] = true;
                            break;
                        }

                        if (!judgeInfo.isValid && item.GetLength() === textIndex[i]) {
                            break;
                        }

                        if (!judgeInfo.isValid && item.GetLength() > textIndex[i]) {
                            existInvalids[i] = true;
                            break;
                        }

                        if (itemPoss[i].toString().GetLength() === item.GetLength() && textIndex[i].toString().GetLength() < text.GetLength() && isLast === true) {
                            existInvalids[i] = true;
                            break;
                        }

                        if (textIndex[i].toString().GetLength() === text.GetLength() && itemPoss[i].toString().GetLength() < item.GetLength()) {
                            existInvalids[i] = true;
                            break;
                        }
                    }
                }

                var itemIndex = this._itemCount;
                for (i = 0; i < this._itemCount; i++) {
                    if (existInvalids[i] === false) {
                        if (itemIndex === this._itemCount) {
                            itemIndex = i;
                        }
                        var item = this._items[i].toString();
                        if (item.GetLength() === this._maxLength && text.GetLength() >= this._maxLength) {
                            itemIndex = i;
                            break;
                        }
                    }
                }
                var k = itemIndex;

                var retObj = {};
                retObj.existInvalid = false;
                retObj.exception = false;

                if (k >= this._itemCount) {
                    var tempPrompt = "";
                    retObj.exception = true;
                    for (i = 0; i < this._minLength; i++) {
                        tempPrompt += this.GetPromptChar();
                    }
                    if (text.Substring(0, this._minLength) === tempPrompt) {
                        text = text.Substring(this._minLength, text.GetLength());
                        retObj.offset = this._minLength;
                        retObj.text = text;
                        retObj.existInvalid = false;
                        retObj.exception = true;
                        this.Clear();
                        return retObj;
                    } else {
                        retObj.text = text;
                        this.text = tempPrompt;
                        this._activeItem = -1;
                        retObj.existInvalid = true;
                        retObj.exception = true;
                        return retObj;
                    }
                } else {
                    this._activeItem = k;
                    this.text = this._items[k].toString();
                    this._trueLength = this._items[k].toString().GetLength();
                    retObj.offset = this._trueLength;
                    retObj.text = text.Substring(this._trueLength, text.GetLength());
                    return retObj;
                }
            };

            EnumField.prototype.PerformSpin = function (position, increment, wrap) {
                var count = this._itemCount;

                if (count < increment) {
                    if (count > 1) {
                        while (count < increment) {
                            increment -= count;
                        }
                    } else {
                        increment = 1;
                    }
                } else if (count < -increment) {
                    if (count > 1) {
                        while (count < -increment) {
                            increment += count;
                        }
                    } else {
                        increment = -1;
                    }
                }

                if (increment === 0) {
                    return position;
                }

                var currentIndex;
                if (this._activeItem === -1) {
                    currentIndex = increment > 0 ? 0 : count - 1;
                } else {
                    currentIndex = this._activeItem + increment;

                    if (currentIndex < 0 || currentIndex >= count) {
                        if (!wrap) {
                            currentIndex = increment > 0 ? count - 1 : 0;
                        } else {
                            currentIndex = increment > 0 ? currentIndex - count : currentIndex + count;
                            if (increment > 0 && currentIndex < this._activeItem) {
                                if (this._activeItem < count - 1) {
                                    currentIndex = count - 1;
                                } else {
                                    currentIndex = 0;
                                }
                            } else if (increment < 0 && currentIndex > this._activeItem) {
                                if (this._activeItem > 0) {
                                    currentIndex = 0;
                                } else {
                                    currentIndex = count - 1;
                                }
                            }
                        }
                    }
                }

                var newItemLen = this._items[currentIndex].toString().GetLength();
                position = Math.min(position, newItemLen);
                this._activeItem = currentIndex;
                this.text = this._items[currentIndex].toString();
                this._trueLength = this._activeItem === -1 ? 0 : this.text.GetLength();
                return position;
            };

            EnumField.prototype.Clear = function () {
                this._activeItem = -1;
            };

            EnumField.prototype.JudgeIfValid = function (str1, index1, str2, index2) {
                var charEx = input.CharProcess.CharEx;
                var retObj = {};
                retObj.index1 = index1;
                retObj.index2 = index2;
                retObj.isValid = false;
                if (index1 >= str1.GetLength()) {
                    return retObj;
                }

                if (str1.Substring(index1, index1 + 1) === str2.Substring(index2, index2 + 1)) {
                    index1++;
                    index2++;
                    retObj.index1 = index1;
                    retObj.index2 = index2;
                    retObj.isValid = true;
                    return retObj;
                } else {
                    if (this._owner.GetAutoConvert() === false) {
                        return retObj;
                    }

                    if (str2.Substring(index2, index2 + 1).charCodeAt(0) >= 0xFF41 && str2.Substring(index2, index2 + 1).charCodeAt(0) <= 0xFF5A) {
                        var dbcsUpper = String.fromCharCode(str2.Substring(index2, index2 + 1).charCodeAt(0) - 32);
                        if (dbcsUpper === str1.Substring(index1, index1 + 1)) {
                            index1++;
                            index2++;
                            retObj.index1 = index1;
                            retObj.index2 = index2;
                            retObj.isValid = true;
                            return retObj;
                        }

                        var sbcsLower = charEx.ToHalfWidth(str2.Substring(index2, index2 + 1));
                        if (sbcsLower === str1.Substring(index1, index1 + 1)) {
                            index1++;
                            index2++;
                            retObj.index1 = index1;
                            retObj.index2 = index2;
                            retObj.isValid = true;
                            return retObj;
                        }

                        var sbcsUpper = charEx.ToHalfWidth(dbcsUpper);
                        if (sbcsUpper === str1.Substring(index1, index1 + 1)) {
                            index1++;
                            index2++;
                            retObj.index1 = index1;
                            retObj.index2 = index2;
                            retObj.isValid = true;
                            return retObj;
                        }

                        return retObj;
                    } else if (str2.Substring(index2, index2 + 1).charCodeAt(0) >= 0xFF21 && str2.Substring(index2, index2 + 1).charCodeAt(0) <= 0xFF3A) {
                        var dbcsLower = String.fromCharCode(str2.Substring(index2, index2 + 1).charCodeAt(0) - 32);
                        if (dbcsLower === str1.Substring(index1, index1 + 1)) {
                            index1++;
                            index2++;
                            retObj.index1 = index1;
                            retObj.index2 = index2;
                            retObj.isValid = true;
                            return retObj;
                        }

                        var sbcsUpper = charEx.ToHalfWidth(str2.Substring(index2, index2 + 1));
                        if (sbcsUpper === str1.Substring(index1, index1 + 1)) {
                            index1++;
                            index2++;
                            retObj.index1 = index1;
                            retObj.index2 = index2;
                            retObj.isValid = true;
                            return retObj;
                        }

                        var sbcsLower = charEx.ToHalfWidth(dbcsLower);
                        if (sbcsLower === str1.Substring(index1, index1 + 1)) {
                            index1++;
                            index2++;
                            retObj.index1 = index1;
                            retObj.index2 = index2;
                            retObj.isValid = true;
                            return retObj;
                        }

                        return retObj;
                    } else if (charEx.IsUpper(str2.Substring(index2, index2 + 1))) {
                        var sbcsLower = str2.Substring(index2, index2 + 1).toLowerCase();
                        if (sbcsLower === str1.Substring(index1, index1 + 1)) {
                            index1++;
                            index2++;
                            retObj.index1 = index1;
                            retObj.index2 = index2;
                            retObj.isValid = true;
                            return retObj;
                        }

                        var dbcsUpper = charEx.ToFullWidth(str2.Substring(index2, index2 + 1)).text;
                        if (dbcsUpper === str1.Substring(index1, index1 + 1)) {
                            index1++;
                            index2++;
                            retObj.index1 = index1;
                            retObj.index2 = index2;
                            retObj.isValid = true;
                            return retObj;
                        }

                        var dbcsLower = charEx.ToFullWidth(sbcsLower).text;
                        if (dbcsLower === str1.Substring(index1, index1 + 1)) {
                            index1++;
                            index2++;
                            retObj.index1 = index1;
                            retObj.index2 = index2;
                            retObj.isValid = true;
                            return retObj;
                        }

                        return retObj;
                    } else if (charEx.IsLower(str2.Substring(index2, index2 + 1))) {
                        var sbcsUpper = str2.Substring(index2, index2 + 1).toUpperCase();
                        if (sbcsUpper === str1.Substring(index1, index1 + 1)) {
                            index1++;
                            index2++;
                            retObj.index1 = index1;
                            retObj.index2 = index2;
                            retObj.isValid = true;
                            return retObj;
                        }

                        var dbcsLower = charEx.ToFullWidth(str2.Substring(index2, index2 + 1)).text;
                        if (dbcsLower === str1.Substring(index1, index1 + 1)) {
                            index1++;
                            index2++;
                            retObj.index1 = index1;
                            retObj.index2 = index2;
                            retObj.isValid = true;
                            return retObj;
                        }

                        var dbcsUpper = charEx.ToFullWidth(dbcsLower).text;
                        if (dbcsUpper === str1.Substring(index1, index1 + 1)) {
                            index1++;
                            index2++;
                            retObj.index1 = index1;
                            retObj.index2 = index2;
                            retObj.isValid = true;
                            return retObj;
                        }

                        return retObj;
                    } else if (charEx.IsHiragana(str2.Substring(index2, index2 + 1))) {
                        var dbcsKatakana = charEx.ToKatakana(str2.Substring(index2, index2 + 1));
                        if (dbcsKatakana === str1.Substring(index1, index1 + 1)) {
                            index1++;
                            index2++;
                            retObj.index1 = index1;
                            retObj.index2 = index2;
                            retObj.isValid = true;
                            return retObj;
                        }

                        var c1 = charEx.ToKatakana(dbcsKatakana);
                        var sbcsKatakanas = charEx.ToHalfWidthEx(c1);
                        if (sbcsKatakanas.length === 1 && sbcsKatakanas === str1.Substring(index1, index1 + 1)) {
                            index1++;
                            index2++;
                            retObj.index1 = index1;
                            retObj.index2 = index2;
                            retObj.isValid = true;
                            return retObj;
                        } else if (sbcsKatakanas.length === 2 && sbcsKatakanas.Substring(0, 1) === str1.Substring(index1, index1 + 1) && index1 + 1 < str1.GetLength() && sbcsKatakanas.Substring(1, 2) === str1.Substring(index1 + 1, index1 + 2)) {
                            index1 += 2;
                            index2++;
                            retObj.index1 = index1;
                            retObj.index2 = index2;
                            retObj.isValid = true;
                            return retObj;
                        }

                        return retObj;
                    } else if (charEx.IsKatakana(str2.Substring(index2, index2 + 1)) && charEx.IsFullWidth(str2.Substring(index2, index2 + 1))) {
                        var c1 = charEx.ToKatakana(str2.Substring(index2, index2 + 1));
                        var sbcsKatakanas = charEx.ToHalfWidthEx(c1);
                        if (sbcsKatakanas.length === 1 && sbcsKatakanas === str1.Substring(index1, index1 + 1)) {
                            index1++;
                            index2++;
                            retObj.index1 = index1;
                            retObj.index2 = index2;
                            retObj.isValid = true;
                            return retObj;
                        } else if (sbcsKatakanas.length === 2 && sbcsKatakanas.Substring(0, 1) === str1.Substring(index1, index1 + 1) && index1 + 1 < str1.GetLength() && sbcsKatakanas.Substring(1, 2) === str1.Substring(index1 + 1, index1 + 2)) {
                            index1 += 2;
                            index2++;
                            retObj.index1 = index1;
                            retObj.index2 = index2;
                            retObj.isValid = true;
                            return retObj;
                        }

                        var hiragana = charEx.ToHiragana(str2.Substring(index2, index2 + 1));
                        if (hiragana === '\u3094') {
                            return retObj;
                        }
                        if (hiragana === str1.Substring(index1, index1 + 1)) {
                            index1++;
                            index2++;
                            retObj.index1 = index1;
                            retObj.index2 = index2;
                            retObj.isValid = true;
                            return retObj;
                        }

                        return retObj;
                    } else if (charEx.IsKatakana(str2.Substring(index2, index2 + 1)) && !charEx.IsFullWidth(str2.Substring(index2, index2 + 1))) {
                        var nextChar;
                        if (index2 + 1 < str2.GetLength() && charEx.IsKatakana(str2.Substring(index2 + 1, index2 + 2)) && !charEx.IsFullWidth(str2.Substring(index2 + 1, index2 + 2))) {
                            nextChar = str2.Substring(index2 + 1, index2 + 2);
                        } else {
                            nextChar = " ";
                        }

                        if (nextChar === " ") {
                            var dbcsKatakana = charEx.ToFullWidth(str2.Substring(index2, index2 + 1)).text;
                            if (dbcsKatakana === str1.Substring(index1, index1 + 1)) {
                                index1++;
                                index2++;
                                retObj.index1 = index1;
                                retObj.index2 = index2;
                                retObj.isValid = true;
                                return retObj;
                            }

                            var hiragana = charEx.ToHiragana(dbcsKatakana);
                            if (hiragana === '\u3094') {
                                return retObj;
                            }
                            if (hiragana === str1.Substring(index1, index1 + 1)) {
                                index1++;
                                index2++;
                                retObj.index1 = index1;
                                retObj.index2 = index2;
                                retObj.isValid = true;
                                return retObj;
                            }

                            return retObj;
                        } else {
                            var fullWidthRetObj = charEx.ToFullWidth(str2.Substring(index2, index2 + 2));
                            var dbcsKatakana = fullWidthRetObj.text;
                            var processedAll = fullWidthRetObj.processedAll;

                            if (dbcsKatakana === str1.Substring(index1, index1 + 1)) {
                                index1++;
                                if (processedAll) {
                                    index2 += 2;
                                } else {
                                    index2++;
                                }
                                retObj.index1 = index1;
                                retObj.index2 = index2;
                                retObj.isValid = true;
                                return retObj;
                            }

                            var hiragana = charEx.ToHiragana(dbcsKatakana);
                            if (hiragana === '\u3094') {
                                if (processedAll) {
                                    if (('\u3046' + '\u309B') === str1.Substring(index1, index1 + 2)) {
                                        index1 += 2;
                                        index2 += 2;
                                        retObj.index1 = index1;
                                        retObj.index2 = index2;
                                        retObj.isValid = true;
                                        return retObj;
                                    } else {
                                        return retObj;
                                    }
                                } else {
                                    return retObj;
                                }
                            }
                            if (hiragana === str1.Substring(index1, index1 + 1)) {
                                index1++;
                                if (processedAll) {
                                    index2 += 2;
                                } else {
                                    index2++;
                                }
                                retObj.index1 = index1;
                                retObj.index2 = index2;
                                retObj.isValid = true;
                                return retObj;
                            }

                            return retObj;
                        }
                    } else if (charEx.IsFullWidth(str2.Substring(index2, index2 + 1))) {
                        var half = charEx.ToHalfWidth(str2.Substring(index2, index2 + 1));
                        if (half === str1.Substring(index1, index1 + 1)) {
                            index1++;
                            index2++;
                            retObj.index1 = index1;
                            retObj.index2 = index2;
                            retObj.isValid = true;
                            return retObj;
                        }

                        return retObj;
                    } else {
                        var full = charEx.ToFullWidth(str2.Substring(index2, index2 + 1)).text;
                        if (full === str1.Substring(index1, index1 + 1)) {
                            index1++;
                            index2++;
                            retObj.index1 = index1;
                            retObj.index2 = index2;
                            retObj.isValid = true;
                            return retObj;
                        }
                        return retObj;
                    }
                }
            };
            return EnumField;
        })(Field);

        /** @ignore */
        var FieldCollection = (function () {
            function FieldCollection(count) {
                this.fieldArray = [];
                this.fieldCount = 0;
                this.fieldCount = count;
            }
            FieldCollection.prototype.GetLength = function () {
                var length = 0;

                for (var i = 0; i < this.fieldCount; i++) {
                    var field = this.GetFieldByIndex(i);
                    length += field.GetLength();
                }

                return length;
            };

            FieldCollection.prototype.Add = function (field) {
                if (field) {
                    this.fieldArray.push(field);
                }
            };

            FieldCollection.prototype.AddRange = function (fields) {
                if (!fields || fields.length === 0 || this.fieldCount !== fields.length) {
                    return;
                }

                var tempFields = new Array();

                for (var i = 0; i < fields.length; i++) {
                    tempFields[i] = fields[i];
                }

                this.fieldArray = tempFields;
            };

            FieldCollection.prototype.GetFieldByIndex = function (index) {
                return this.fieldArray[index];
            };

            FieldCollection.prototype.GetText = function () {
                var text = "";
                for (var i = 0; i < this.fieldCount; i++) {
                    text += this.GetFieldByIndex(i).GetText();
                }

                return text;
            };

            FieldCollection.prototype.GetFillingString = function (fillChar) {
                var fillString = "";
                for (var i = 0; i < this.fieldCount; i++) {
                    var field = this.fieldArray[i];
                    if (field.fieldLabel === "PromptField") {
                        fillString += field.GetText();
                    } else {
                        for (var j = 0; j < field._minLength; j++) {
                            fillString += fillChar;
                        }
                    }
                }

                return fillString;
            };

            FieldCollection.prototype.SetText = function (text, includePrompt) {
            };

            FieldCollection.prototype.Insert = function (start, text, includePrompt) {
            };

            FieldCollection.prototype.Replace = function (start, length, text, includePrompt) {
            };

            FieldCollection.prototype.Delete = function (start, length) {
            };

            FieldCollection.prototype.PerformSpin = function (position, increment, wrap) {
            };

            FieldCollection.prototype.GetFieldIndex = function (position, offset) {
                var fieldPos = {};
                var length = 0;

                for (var i = 0; i < this.fieldCount; i++) {
                    var field = this.fieldArray[i];
                    var fieldLength = field.GetLength();

                    if ((position === length && fieldLength === 0) || (position >= length && position < length + fieldLength)) {
                        fieldPos.index = i;
                        fieldPos.offset = position - length;
                        return fieldPos;
                    }

                    length += fieldLength;
                }

                if (position >= length) {
                    var field = this.fieldArray[this.fieldCount - 1];

                    fieldPos.index = this.fieldCount - 1;
                    fieldPos.offset = field.GetLength();
                    return fieldPos;
                }
            };

            FieldCollection.prototype.GetFieldRange = function (fieldIndex) {
                var fieldRange = {};
                fieldRange.start = 0;
                fieldRange.length = 0;
                var length = 0;
                for (var i = 0; i < fieldIndex; i++) {
                    var field = this.GetFieldByIndex(i);

                    length += field.GetLength();
                }

                var currentField = this.GetFieldByIndex(fieldIndex);

                if (!currentField) {
                    return fieldRange;
                }

                fieldRange.start = length;
                fieldRange.length = currentField.GetLength();

                return fieldRange;
            };
            return FieldCollection;
        })();
        input.FieldCollection = FieldCollection;

        

        /** @ignore */
        var BaseInputControl = (function () {
            function BaseInputControl() {
                this.KeyActionList = null;
                this.Text = "";
                this.Value = null;
                this.DroppedDown = false;
                this.SelectionLength = 0;
                this.SelectionStart = 0;
                this.SelectionEnd = 0;
                this.IsMouseDown = false;
                this.OldSelectionStart = 0;
                this.OldSelectionEnd = 0;
                this._acceptCrlf = 0 /* NoControl */;
                this._clipContent = 0 /* IncludeLiterals */;
                this._editMode = 0 /* Insert */;
                this.__editModeInternal = 0 /* Insert */;
                this._useClipboard = true;
                this._readOnly = false;
                this._autoPostBack = false;
                this._highlightText = 0 /* None */;
                this._exitOnLeftRightKey = 0 /* None */;
                this.FocusType = 0 /* None */;
                this.IsInUpdatePanelAndAsyncPostBack = false;
                this.NeedResetFocus = false;
                this.NeedReCalCursorPos = true;
                this.SpinBtnPressed = false;
                this.DropDownBtnPressed = false;
                this.OldValue = "";
                this.ValueBeforeUndo = "";
                this.FocusExit = false;
                this.Delay = 0;
                this.SpinOnKeys = true;
                this.Wrap = true;
                this.SpinEnabled = true;
                this.Increment = 1;
                this.Visible = false;
                this.MouseButton = -1 /* Default */;
                this.TouchDropDownScale = 1;
                this.UIUpdate = new input.InputUIUpdate(this);
                this.Format = { Fields: null };
            }
            BaseInputControl.prototype.Snap = function () {
                var retObj = {
                    Text: this.Text,
                    Value: this.Value,
                    SelectionStart: this.SelectionStart,
                    SelectionEnd: this.SelectionEnd
                };
                return retObj;
            };

            BaseInputControl.prototype.Revert = function (snapPackage) {
                this.Text = snapPackage.Text;
                this.Value = snapPackage.Value;
                this.SelectionStart = snapPackage.SelectionStart;
                this.SelectionEnd = snapPackage.SelectionEnd;
            };

            /**
            * ReLoad Data.
            */
            BaseInputControl.prototype.ReLoadData = function () {
            };

            //end by Kevin.
            /**
            * Gets the Overwrite property which indicates whether edit mode of the input control is overwritable.
            * @returns {boolean}
            */
            BaseInputControl.prototype.GetOverwrite = function () {
                if (this.GetEditMode() === 2 /* FixedInsert */ || this.GetEditMode() === 3 /* FixedOverwrite */) {
                    return this.GetEditMode() === 3 /* FixedOverwrite */;
                } else {
                    return this._getEditModeInternal() !== 0 /* Insert */ && this._getEditModeInternal() !== 2 /* FixedInsert */;
                }
            };

            BaseInputControl.prototype.GetImeMode = function () {
                return this.InputElement.style.imeMode || "auto";
            };

            BaseInputControl.prototype.SetImeMode = function (imeMode) {
                this.GetInputElement().style.imeMode = imeMode;
            };

            BaseInputControl.prototype.GetEnabled = function () {
                return this.GetInputElement().disabled;
            };

            BaseInputControl.prototype.SetEnabled = function (value) {
                if (value) {
                    $(this.GetInputElement()).removeAttr("diabled");
                } else {
                    $(this.GetInputElement()).attr("diabled", "true");
                }
            };

            BaseInputControl.prototype.SetFocus = function () {
                $(this.GetInputElement()).focus();
            };

            /**
            * Gets whether the drop-down control is dropped down.
            * @returns {boolean}
            */
            BaseInputControl.prototype.GetDroppedDown = function () {
                return this.DroppedDown;
            };

            /**
            * Gets the start position of the selection.
            * @returns {number}
            */
            BaseInputControl.prototype.GetSelectionStart = function () {
                return Math.min(this.SelectionStart, this.SelectionEnd);
            };

            /**
            * Sets the start position of the selection.
            * @param {number} start
            */
            BaseInputControl.prototype.SetSelectionStart = function (start) {
                start = input.Utility.CheckInt(start, 0, Math.pow(2, 31));

                start = Math.min(start, this.Text.GetLength());

                this.SetInnerSelectionStart(start);
                this.SetInnerSelectionEnd(start + this.SelectionLength);

                this.NeedReCalCursorPos = true;
            };

            /**
            * Gets the length of the selection.
            * @returns {number}
            */
            BaseInputControl.prototype.GetSelectionLength = function () {
                return Math.abs(this.SelectionEnd - this.SelectionStart);
            };

            /**
            * Sets the length of the selection.
            * @param {number} length
            */
            BaseInputControl.prototype.SetSelectionLength = function (length) {
                length = input.Utility.CheckInt(length, 0, Math.pow(2, 31));

                if (this.SelectionStart + length > this.Text.GetLength()) {
                    length = this.Text.GetLength() - this.SelectionStart;
                }

                this.SelectionLength = length;
                this.SetInnerSelectionEnd(this.SelectionStart + length);

                this.NeedReCalCursorPos = true;
            };

            /**
            * Sets the start position of the selection.
            */
            BaseInputControl.prototype.SetInnerSelectionStart = function (start) {
                this.SelectionStart = start;
            };

            /**
            * Sets the length of the selection.
            */
            BaseInputControl.prototype.SetInnerSelectionEnd = function (end) {
                this.SelectionEnd = end;
            };

            /**
            * Sets whether the drop-down control is dropped down.
            * @param droppedDown
            */
            BaseInputControl.prototype.SetDroppedDown = function (droppedDown) {
                if (!this.Enabled) {
                    return;
                }

                this.DroppedDown = droppedDown;
            };

            /**
            * Do SpinUp action.
            */
            BaseInputControl.prototype.DoSpinUp = function (field, increment) {
                if (increment == null) {
                    increment = this.Increment;
                }

                this.DoSpin("up", this.SelectionEnd, increment);
            };

            /**
            * Do SpinDown action.
            */
            BaseInputControl.prototype.DoSpinDown = function (field, increment) {
                if (increment == null) {
                    increment = this.Increment;
                }

                this.DoSpin("down", this.SelectionEnd, increment);
            };

            /**
            * Do SpinUp action.
            */
            BaseInputControl.prototype.DoSpin = function (type, cursorPos, increment) {
                if (type === "down") {
                    increment *= -1;
                }

                if ((typeof cursorPos === "number" && isNaN(cursorPos)) || (typeof increment === "number" && isNaN(increment))) {
                    return;
                }

                var retInfo = this.UIProcess.PerformSpin(cursorPos, increment, this.Wrap);

                if (!retInfo) {
                    return;
                }
                if (typeof retInfo.SelectionStart === "number" && !isNaN(retInfo.SelectionStart)) {
                    this.SelectionStart = retInfo.SelectionStart;
                }
                if (typeof retInfo.SelectionEnd === "number" && !isNaN(retInfo.SelectionEnd)) {
                    this.SelectionEnd = retInfo.SelectionEnd;
                }

                if (retInfo.Text != null) {
                    if (!this.UpdateText(retInfo)) {
                        return;
                    }
                }

                this.UpdateDisplayText(this.Text);

                if (type === "up") {
                    this.UIProcess.FireEvent(this, this.SpinUpEvent, null, "SpinUp");
                } else if (type === "down") {
                    this.UIProcess.FireEvent(this, this.SpinDownEvent, null, "SpinDown");
                }
            };

            /**
            * Gets whether the focus automatically moves to the next or previous
            * tab ordering control when pressing the left, right arrow keys.
            * @returns {ExitOnLeftRightKey} A {ExitOnLeftRightKey} enumeration
            * indicates whether the focus automatically moves to the next or previous tab ordering control when pressing the left, right arrow keys.
            */
            BaseInputControl.prototype.GetExitOnLeftRightKey = function () {
                return this._exitOnLeftRightKey;
            };

            /**
            * Sets whether the focus automatically moves to the next or previous
            * tab ordering control when pressing the left, right arrow keys.
            * @param {ExitOnLeftRightKey} value A {ExitOnLeftRightKey} enumeration
            * indicates whether the focus automatically moves to the next or previous tab ordering control when pressing the left, right arrow keys.
            */
            BaseInputControl.prototype.SetExitOnLeftRightKey = function (value) {
                this._exitOnLeftRightKey = value;
            };

            /**
            * Gets a value indicating how to process the CrLf chars when copy, cut or paste string.
            * @returns An enumeration indicates which mode that the CrLf chars will be used when copy, cut and paste string.<br/>
            * The default is <b>CrLfMode.NoControl</b>.
            */
            BaseInputControl.prototype.GetAcceptsCrlf = function () {
                return this._acceptCrlf;
            };

            /**
            * Sets a value indicating how to process the CrLf chars when copy, cut or paste string.
            * @param {CrLfMode} value An enumeration indicates which mode that the CrLf chars will be used when copy, cut and paste string.
            */
            BaseInputControl.prototype.SetAcceptsCrlf = function (value) {
                this._acceptCrlf = value;
            };

            /**
            * Set Control to get focus.
            */
            BaseInputControl.prototype.SetInnerFocus = function () {
                this.FocusType = 3 /* ClientEvent */;
                this.UIUpdate.SetFocus();
                this.SetSelection(this.SelectionStart, this.SelectionEnd);
            };

            /**
            * Sets the display content of the control.(has no effect on FieldCollection)
            */
            BaseInputControl.prototype.UpdateDisplayText = function (text) {
                this.UIUpdate.SetText(text);

                //Add by Ryan Wu at 13:35 Nov. 23 2006.
                //For fix bug#6759.
                this.SetHideValue();
                //end by Ryan.
            };

            /**
            * Sets the text to the hide textbox.
            */
            BaseInputControl.prototype.SetHideText = function (text) {
            };

            /**
            * Sets the selection according to the special start and end position.
            */
            BaseInputControl.prototype.SetSelection = function (start, end, setOnFocus) {
                if (start == null || end == null || isNaN(start) || isNaN(end)) {
                    return;
                }

                 {
                    if (setOnFocus && input.CoreUtility.IsIE10OrLater()) {
                        // DaryLuo 2012/11/12 fix bug 869 in IM Web 7.0.
                        var self = this;
                        setTimeout(function () {
                            input.Utility.SetSelection(self.InputElement, start, end);
                        }, 0);
                    } else {
                        input.Utility.SetSelection(this.InputElement, start, end);
                    }
                }

                this.SelectionStart = start;
                this.SelectionEnd = end;

                if (start === end) {
                    this.UIProcess.isMulSelected = false;
                }
            };

            BaseInputControl.prototype._getAutoPostBack = function () {
                return this._autoPostBack;
            };

            BaseInputControl.prototype._setAutoPostBack = function (value) {
                value = input.Utility.CheckBool(value);
                this._autoPostBack = value;
            };

            /**
            * Gets whether copy, cut or paste the data to or from the clipboard when control are selected.
            * @returns {boolean}
            */
            BaseInputControl.prototype.GetUseClipboard = function () {
                return this._useClipboard;
            };

            /**
            * Sets whether copy, cut or paste the data to or from the clipboard when control are selected.
            * @param {boolean} value
            */
            BaseInputControl.prototype.SetUseClipboard = function (value) {
                this._useClipboard = value;
            };

            /**
            * Gets whether the ClipMode include the literals.
            * @returns An enumeration indicates whether the ClipMode include the literals.
            */
            BaseInputControl.prototype.GetClipContent = function () {
                return this._clipContent;
            };

            /**
            * Sets whether the ClipMode include the literals.
            * @param {ClipContent} value An enumeration indicates whether the ClipMode include the literals.
            */
            BaseInputControl.prototype.SetClipContent = function (value) {
                this._clipContent = value;
            };

            BaseInputControl.prototype.GetTextHAlign = function () {
                return this.UIUpdate.GetTextHAlign();
            };

            BaseInputControl.prototype.SetTextHAlign = function (value) {
                this.UIUpdate.SetTextHAlign(value);
            };

            /**
            * Gets the edit mode of the input control.
            * @returns {EditMode} A {EditMode} enumeration indicates the edit mode.
            */
            BaseInputControl.prototype.GetEditMode = function () {
                return this._editMode;
            };

            /**
            * Sets the edit mode of the input control.
            * @param {EditMode} value A {EditMode} enumeration indicates the edit mode.
            */
            BaseInputControl.prototype.SetEditMode = function (value) {
                if (value !== this._editMode) {
                    var shouldFireEvent = false;
                    if (this._isinsertGroup(value) && this._isOverwriteGroup(this._editMode)) {
                        shouldFireEvent = true;
                    } else if (this._isinsertGroup(this._editMode) && this._isOverwriteGroup(value)) {
                        shouldFireEvent = true;
                    }

                    this._editMode = value;
                    this.__editModeInternal = value;
                    if (shouldFireEvent) {
                        this.UIProcess.FireEvent(this, this.EditStatusChangedEvent, null, "EditStatusChanged");
                    }
                }
            };

            BaseInputControl.prototype._getEditModeInternal = function () {
                return this.__editModeInternal;
            };
            BaseInputControl.prototype._setEditModeInternal = function (value) {
                if (value !== this.__editModeInternal) {
                    var shouldFireEvent = false;
                    if (this._isinsertGroup(value) && this._isOverwriteGroup(this.__editModeInternal)) {
                        shouldFireEvent = true;
                    } else if (this._isinsertGroup(this.__editModeInternal) && this._isOverwriteGroup(value)) {
                        shouldFireEvent = true;
                    }

                    this.__editModeInternal = value;
                    if (shouldFireEvent) {
                        this.UIProcess.FireEvent(this, this.EditStatusChangedEvent, null, "EditStatusChanged");
                    }
                }
            };

            BaseInputControl.prototype._isinsertGroup = function (editMode) {
                return editMode === 0 /* Insert */ || editMode === 2 /* FixedInsert */;
            };

            BaseInputControl.prototype._isOverwriteGroup = function (editMode) {
                return editMode === 1 /* Overwrite */ || editMode === 3 /* FixedOverwrite */;
            };

            /**
            * Gets how to select the text when the control receives the focus.
            * @returns {HighlightText}
            */
            BaseInputControl.prototype.GetHighlightText = function () {
                return this._highlightText;
            };

            /**
            * Sets how to select the text when the control receives the focus.
            * @param {HighlightText} value
            */
            BaseInputControl.prototype.SetHighlightText = function (value) {
                this._highlightText = value;
            };

            /**
            * Gets whether the text is read-only.
            * @returns {boolean}
            */
            BaseInputControl.prototype.GetReadOnly = function () {
                return this._readOnly;
            };

            /**
            * Sets whether the text is read-only.
            * @param {boolean} value
            */
            BaseInputControl.prototype.SetReadOnly = function (value) {
                this._readOnly = value;
            };

            /**
            * Gets the display content of the control.
            */
            BaseInputControl.prototype.GetTextboxValue = function () {
                return this.UIUpdate.GetText();
            };

            /**
            * Gets the old value.
            */
            BaseInputControl.prototype.GetOldValue = function () {
                return this.OldValue;
            };

            /**
            * Judge if the undo action can operate.
            */
            BaseInputControl.prototype.CanUndo = function () {
                if (this.GetValue() === this.GetOldValue()) {
                    return false;
                }

                return true;
            };

            BaseInputControl.prototype.GetValue = function () {
                return "";
            };

            /**
            * Handle the ondragstart event.
            */
            BaseInputControl.prototype.DragStart = function () {
                this.DragStartElementID = this.ID;
            };

            /**
            * Handle the ondragend event.
            */
            BaseInputControl.prototype.DragEnd = function (evt) {
                this.DragStartElementID = "";
                input.Utility.PreventDefault(evt);
                return false;
            };

            /**
            * Handle the mouseout event.
            */
            BaseInputControl.prototype.MouseOut = function () {
                if (this.IsMouseDown !== true) {
                    return;
                }

                if (this.MouseUpPointerType !== undefined && this.MouseUpPointerType !== 4 && this.MouseUpPointerType !== "mouse") {
                    // DaryLuo 2012/10/31 fix bug 817 in IM Web 7.0.
                    return;
                }

                var start = Math.min(this.OldSelectionStart, this.OldSelectionEnd);
                var end = Math.max(this.OldSelectionStart, this.OldSelectionEnd);
                var data = this.GetText().Substring(start, end);

                if (data !== "") {
                    this.SetSelection(this.OldSelectionStart, this.OldSelectionEnd);
                    input.Utility.DragDrop(this.InputElement);
                }

                this.IsMouseDown = false;
            };

            BaseInputControl.prototype.GetText = function () {
                return "";
            };

            ////////////////////////////////////////////////////////////////////////////
            //For Test
            /////////////////////////////////////////////////////////////////
            //UI Operation Methods
            /**
            * Handle the onfocus event.
            */
            BaseInputControl.prototype.Focus = function (data) {
                //Add comments by Ryan Wu at 14:38 Oct. 11 2007.
                //For fix the bug#8998.
                data.SelectionStart = this.SelectionStart;
                var retInfo = this.UIProcess.Focus(data);

                //end by Ryan Wu.
                //Add comments by Ryan Wu at 15:18 Jan. 16 2007.
                //For fix bug#6447.
                input.Utility.CurrentActiveControlId = this.ID;

                //end by Ryan Wu.
                if (!retInfo) {
                    return;
                }

                if (retInfo.Text != null) {
                    this.Text = retInfo.Text;
                }

                if (retInfo.SelectionStart != null) {
                    this.SelectionStart = retInfo.SelectionStart;
                }

                if (retInfo.SelectionEnd != null) {
                    this.SelectionEnd = retInfo.SelectionEnd;
                }

                // add by Sean Huang at 2008.11.06, for bug 10007 -->
                if (this.GetReadOnly() && this.FocusType === 0 /* None */) {
                    this.SelectionStart = 0;
                    this.SelectionEnd = this.Text.length;
                }

                // end of Sean Huang <--
                this.UpdateDisplayText(this.Text);

                // DaryLuo 2012/11/08 fix bug 869 in IM Web 7.0.
                this.SetSelection(this.SelectionStart, this.SelectionEnd, true);

                return retInfo;
            };

            /**
            * Handle the onblur event.
            */
            BaseInputControl.prototype.LoseFocus = function (data) {
                // add by Sean Huang at 2008.10.30, for bug 9908 -->
                this.FireKeyExit();

                // end of Sean Huang <--
                if ((this.SpinBtnPressed || this.DropDownBtnPressed || (this.DropDownObj && this.DropDownObj.IsMouseOver)) && this.FocusType !== 4 /* KeyExit */) {
                    return;
                }

                if (this.DroppedDown) {
                    // add by Sean Huang at 2008.12.11 -->
                    this.DropDownBtnPressed = false;

                    // end of Sean Huang <--
                    //Add comments by Ryan Wu at 12:49 Apr. 21 2007.
                    //For fix the bug that When we click the dropdown date to close the dropdown,
                    //we should reset focus to the control.
                    //this.CloseDropDown();
                    this.CloseDropDown();
                    //end by Ryan Wu.
                }

                this.SetLastClientValues();

                return this.UIProcess.LoseFocus(data);
            };

            BaseInputControl.prototype.FireKeyExit = function () {
                // TODO:
            };

            BaseInputControl.prototype.SetLastClientValues = function () {
                // TODO:
            };

            /**
            * Handle the onmousedown event.
            */
            BaseInputControl.prototype.MouseDown = function (evt) {
                var mouseButton = input.Utility.GetMouseButton(evt);

                this.MouseButton = mouseButton;
                this.FocusType = 1 /* Click */;

                this.OldSelectionStart = this.SelectionStart;
                this.OldSelectionEnd = this.SelectionEnd;
                this.IsMouseDown = true;

                // add by Sean Huang at 2008.12.05, for right-to-left selection -->
                this.MouseDownX = evt.x;

                // end of Sean Huang <--
                // End by Yang
                if (this.MouseButton === 0 /* Left */) {
                    // DaryLuo 2013/05/29 fix bug 523 in IM HTML5.0.
                    // Frank Liu fixed bug 598 at 2013/06/20.
                    if (input.CoreUtility.IsIE() || input.CoreUtility.firefox) {
                        input.Utility.ClearSelection(this.GetInputElement());
                    }
                }

                if (this.DroppedDown) {
                    this.CloseDropDown();
                }

                //When format is null or pattern is "", we use the date as a textbox.
                if (this.IsNullFormat()) {
                    return;
                }

                var retInfo = this.UIProcess.MouseDown(mouseButton);

                if (!retInfo) {
                    return;
                }

                if (retInfo.SelectionStart != null) {
                    this.SelectionStart = retInfo.SelectionStart;
                }

                if (retInfo.SelectionEnd != null) {
                    this.SelectionEnd = retInfo.SelectionEnd;
                    this.SetSelection(this.SelectionStart, this.SelectionEnd);
                }
            };

            BaseInputControl.prototype.GetInputElement = function () {
                return this.InputElement;
            };

            /**
            * Handle the onmouseup event.
            */
            BaseInputControl.prototype.MouseUp = function (evt) {
                // Frank Liu fixed bug 598 at 2013/06/08.
                //evt.preventDefault();
                this.IsMouseDown = false;

                // add by Sean Huang at 2008.12.05, for right-to-left selection -->
                this.MouseUpX = evt.x;

                // end of Sean Huang <--
                //When format is null or pattern is "", we use the date as a textbox.
                if (this.IsNullFormat()) {
                    //    return true;
                }

                var retInfo = this.UIProcess.MouseUp(this.InputElement, this.SelectionStart, this.SelectionEnd, this.MouseButton);

                if (!retInfo) {
                    return;
                }

                if (retInfo.SelectionStart != null) {
                    this.SelectionStart = retInfo.SelectionStart;
                }

                if (retInfo.SelectionEnd != null) {
                    this.SelectionEnd = retInfo.SelectionEnd;
                }

                // add by Sean Huang at 2008.12.05, for right-to-left selection -->
                if (input.Utility.GetMouseButton(evt) === 0 /* Left */ && this.MouseDownX != null && this.MouseDownX > this.MouseUpX) {
                    var temp = this.SelectionStart;
                    this.SelectionStart = this.SelectionEnd;
                    this.SelectionEnd = temp;
                }
                this.MouseDownX = null;

                // end of Sean Huang <--
                this.MouseButton = -1 /* Default */;
            };

            /**
            * Handle the onmousewheel event.
            */
            BaseInputControl.prototype.MouseWheel = function (evt) {
                if (this.ImeMode === true) {
                    return false;
                }
                if (this.GetSpinEnabled()) {
                    var increment = input.Utility.GetMouseWheelValue(0, evt);

                    if (increment > 0) {
                        this.PerformSpin("up");
                    } else if (increment < 0) {
                        this.PerformSpin("down");
                    }

                    input.Utility.PreventDefault(evt);
                    return false;
                }
            };

            /**
            * Pre process the contextmenu key before process control's keydown.
            */
            BaseInputControl.prototype.PreProcessContextMenu = function (k) {
                //Add for contextmenu shortcut
                //if (this.ContextMenu.IsShow()) {
                //    //Up, Down, Entern, U(Undo), T(Cut), C(Copy), P(Paste), D(Delete), A(SelectAll)
                //    if (k === 38 || k === 40 || k === 13 || k === 85 || k === 84 || k === 67 || k === 80 || k === 68 || k === 65) {
                //        this.ContextMenu.KeyDown(k);
                //    }
                //    if (k === 27 || k === 18) {
                //        this.ContextMenu.Close();
                //    }
                //    return true;
                //}
                return false;
            };

            /**
            * Process the reserved key before process control's keydown.
            */
            BaseInputControl.prototype.ProcessReservedKey = function (k) {
                switch (k) {
                    case 131138:
                    case 131140:
                    case 131141:
                    case 131144:
                    case 131145:
                    case 131148:
                    case 131150:
                    case 131154:
                    case 131159:
                    case 131188:
                    case 262181:
                    case 262183:

                    case 112:

                    case 114:

                    case 115:

                    case 116:

                    case 117:

                    case 121:

                    case 122:

                    case 123:

                    case 65657:
                    case 131081:
                    case 196617:

                    case 131179:
                    case 131181:
                    case 131120:
                    case 131259:
                    case 131261:
                    case 131146:
                    case 196680:
                    case 196681:
                    case 196682:
                    case 131153:
                    case 131156:
                    case 196689:
                    case 262157:
                        //end by Ryan Wu.
                        return true;
                }

                return false;
            };

            /**
            * Judge whether the current format is null or not.
            */
            BaseInputControl.prototype.IsNullFormat = function () {
                return false;
            };

            /**
            * Convert the current Value to the string.
            */
            BaseInputControl.prototype.SetHideValue = function () {
                var hiddenText = "";

                if (this.GetValue() != null) {
                    hiddenText = this.GetValue().toString();
                }

                //Add comments by Ryan Wu at 10:25 Aug. 20 2007.
                //For now we will use other way to get the info whether javascript is disabled or not.
                //So we will not post the ";true" to the server side to tell the server that javascript is enabled.
                //this.SetHideText(hiddenText + ";" + true);
                this.SetHideText(hiddenText);
                //end by Ryan Wu.
            };

            /**
            * Handle the onkeydown event.
            */
            BaseInputControl.prototype.KeyDown = function (data) {
                var retInfo = {};
                var funcKeysPressed = data.FuncKeysPressed;
                var k = data.KeyCode;

                //Pre process ContextMenu
                if (this.PreProcessContextMenu(k)) {
                    retInfo.System = false;
                    return retInfo;
                }

                if (k === 229) {
                    // DaryLuo Set IMeMode to true in the Composition start event.
                    //this.ImeMode = true;
                    retInfo.System = true;
                    return retInfo;
                }

                if (funcKeysPressed.Shift) {
                    k |= 65536;
                }

                if (funcKeysPressed.Ctrl) {
                    k |= 131072;
                }

                if (funcKeysPressed.Alt) {
                    //Press the Alt+AccessKey again.
                    if (this.AccessKey != null && this.AccessKey.toLowerCase() === String.fromCharCode(k).toLowerCase()) {
                        this.SelectionStart = 0;
                        this.SelectionEnd = this.Text.GetLength();
                        retInfo.System = true;
                        return retInfo;
                    }

                    k |= 262144;
                }

                //Process reserved key.
                if (this.ProcessReservedKey(k)) {
                    retInfo.System = true;
                    return retInfo;
                }

                // add by Sean Huang at 2008.12.03, for bug 762,786 -->
                // if the key is a shortcut, this functoin will be invoked again by the
                // shortcut extender. So just return it for the first invoking.
                var k1 = k | 524288;
                if (k !== k1) {
                    var keyAction1 = this.UIProcess.GetKeyActionName(k1, this.Shortcuts);
                    if (keyAction1 != null) {
                        // Add by Jiang at Dec. 24 2008
                        //for fix bug1371 TTP
                        var isblock = true;
                        var hasFound = false;

                        if (isblock) {
                            retInfo.System = false;
                            return retInfo;
                        }
                        //retInfo.System = false;
                        //return retInfo;
                        //End by Jiang
                    }
                }

                // end of Sean Huang <--
                var keyAction = this.UIProcess.GetKeyActionName(k, this.Shortcuts);
                switch (keyAction) {
                    case "DropDown":
                        if (this.GetDropDownEnabled()) {
                            this.PerformDropDown();
                            retInfo.System = false;
                        }
                        return retInfo;
                    case "SpinUp":
                        if (this.GetSpinEnabled() && this.SpinOnKeys) {
                            this.PerformSpin("up");
                            retInfo.System = false;
                        }
                        return retInfo;
                    case "SpinDown":
                        if (this.GetSpinEnabled() && this.SpinOnKeys) {
                            this.PerformSpin("down");
                            retInfo.System = false;
                        }
                        return retInfo;
                }

                // Add by Jiang at Oct. 28 2008
                // for fixed bug10160
                var isBlockByShortcut = false;
                if (this.KeyActionList) {
                    for (var i = 0; i < this.KeyActionList.length; i++) {
                        if (this.KeyActionList[i] === k.toString()) {
                            isBlockByShortcut = true;
                            break;
                        }
                    }
                }

                // end by Jiang
                //act as calendar's keydown event
                //The current key is not a shortcut key and the key isn't Alt+Up, Alt+Down, F9, Escape, Tab, Shift+Tab.
                if (this.DroppedDown && this.DropDownObj && k != 262182 && k != 262184 && k != 27 && k != 118 && k != 9 && k != 65545) {
                    if (keyAction != null && this.DropDownObj.IsShortcut(k)) {
                        keyAction = null;
                    }

                    if (!keyAction) {
                        //Add by Ryan Wu at 11:02 Jan. 25 2006.
                        //For fix bug#4703.
                        //Right click key.(App)
                        if (k === 93) {
                            this.CloseDropDown();

                            return true;
                        }

                        //Add for Number
                        retInfo.System = false;

                        //
                        // Add by Jiang at Nov. 11 2008
                        // Fix bug10246
                        if (!isBlockByShortcut) {
                            // Frank Liu modified at 2013/06/19.
                            var _fakeEvtParam = { keyCode: 0, shiftKey: false, ctrlKey: false, altKey: false };
                            _fakeEvtParam.keyCode = data.KeyCode;
                            _fakeEvtParam.shiftKey = funcKeysPressed.Shift;
                            _fakeEvtParam.ctrlKey = funcKeysPressed.Ctrl;
                            _fakeEvtParam.altKey = funcKeysPressed.Alt;

                            this.DropDownObj.KeyDown(_fakeEvtParam);
                            return retInfo;
                        }
                        //End by Jiang
                    }
                }

                data.KeyAction = keyAction;
                data.KeyCode = k;
                var processInfo = this.UIProcess.KeyDown(data);
                if (!processInfo) {
                    switch (k) {
                        case 27:
                            if (this.DroppedDown) {
                                this.CloseDropDown();
                                this.SetInnerFocus();
                            }

                            retInfo.System = false;
                            return retInfo;

                        case 262182:

                        case 262184:
                            //	//F7 key
                            //   case 120:
                            if (!isBlockByShortcut) {
                                this.PerformDropDown();
                                retInfo.System = true;
                            }
                            return retInfo;

                        case 262152:
                            retInfo.KeyCode = 10;
                            return retInfo;

                        case 38:
                            if (!isBlockByShortcut) {
                                if (this.GetSpinEnabled() && this.SpinOnKeys) {
                                    this.PerformSpin("up");
                                }

                                // DaryLuo 2013/05/15 fix bug 379, Eat the up and down key.
                                retInfo.System = false;
                            }
                            return retInfo;

                        case 40:
                            if (!isBlockByShortcut) {
                                if (this.GetSpinEnabled() && this.SpinOnKeys) {
                                    this.PerformSpin("down");
                                }
                                retInfo.System = false;
                            }
                            return retInfo;

                        case 13:
                            retInfo.System = true;
                            return retInfo;
                    }

                    //There isn't format or press Caps, ctrl, alt key, window key, NumLock key, ScrollLock key, Right click key, Right window key.
                    if (this.IsNullFormat() || k === 20 || funcKeysPressed && (funcKeysPressed.Ctrl || funcKeysPressed.Alt) || k === 91 || k === 144 || k === 145 || k === 93 || k === 92) {
                        retInfo.System = true;
                        return retInfo;
                    }

                    //There is format and the shiftKey is pressed. Fix the bug#3789.
                    if (funcKeysPressed && funcKeysPressed.Shift) {
                        //The current key is shift.
                        if (k === 65552) {
                            retInfo.System = true;
                            return retInfo;
                        }
                    }

                    //Judge whether the current object is a NumberControl instance, if true then return directly,
                    //otherwise fire InvalidInput event.
                    if (this.Type === "Number") {
                        //Add by Michelle Fang 2005.12.28 for Number
                        retInfo.System = true;
                        return retInfo;
                    }

                    // Add by Jiang at Dec. 29 2008
                    //for fix bug1371 TTP, F2 F7 F8
                    //Add comments by Ryan Wu at 21:54 Jan. 23 2007.
                    //For fix bug#7647.
                    //F9 F12
                    //if (k === 120 || k === 123)
                    if (k === 120 || k === 123 || k === 113 || k === 118 || k === 119) {
                        return retInfo;
                    }

                    //end by Ryan Wu.
                    //End by Jiang
                    //Add comments by Ryan Wu at 9:45 Apr. 5 2007.
                    //For support Aspnet Ajax 1.0.
                    //var focusType = this.UIProcess.FireEvent(this, this.ClientEvents.SpecialClientEvents.InvalidInput, null);
                    var focusType = this.UIProcess.FireEvent(this, this.InvalidInputEvent, null, "InvalidInput");

                    //end by Ryan Wu.
                    if (focusType != null) {
                        this.FocusType = focusType;
                    }

                    return retInfo;
                }

                if (processInfo.Overwrite != null) {
                    if (this.GetOverwrite() !== processInfo.Overwrite) {
                        if (this._getEditModeInternal() === 0 /* Insert */) {
                            this._setEditModeInternal(1 /* Overwrite */);
                        } else if (this._getEditModeInternal() === 1 /* Overwrite */) {
                            this._setEditModeInternal(0 /* Insert */);
                        }
                    }
                }

                if (processInfo.Text != null) {
                    //this.SetText(processInfo.Text);
                    //updatetext before set position, Kevin, 2006-11-30
                    //commented by Kevin, Jun 7, 2007
                    //bug#8388
                    //if (!this.UpdateText(processInfo.Text))
                    if (!this.UpdateText(processInfo)) {
                        retInfo.System = false;
                        return retInfo;
                    }
                }

                // add by Sean Huang at 2009.01.06, for bug 1454 -->
                var oldLength = this.GetSelectionLength();

                // end of Sean Huang <--
                if (processInfo.SelectionStart != null) {
                    this.SelectionStart = processInfo.SelectionStart;
                }

                if (processInfo.SelectionEnd != null) {
                    this.SelectionEnd = processInfo.SelectionEnd;
                }

                // add by Sean Huang at 2009.01.06, for bug 1454 -->
                var newLength = this.GetSelectionLength();

                // end of Sean Huang <--
                //Add comments by Ryan Wu at 11:17 Aug. 28 2007.
                //For the sequence of the onfocus, onblur, onkeydown event in firefox is not same as IE
                //when we use the focus method in keydown.
                //in IE: onkeydown --> onblur --> onfocus.
                //in Firefox: onblur --> onfocus --> onkeydown.
                //	//Add comments by Ryan Wu at 16:26 May. 18 2007.
                //	//For fix the bug#8162.
                ////	if (!processInfo.System && !processInfo.FocusExit)
                ////	{
                ////		this.UpdateDisplayText(this.Text);
                ////		this.SetSelection(this.SelectionStart, this.SelectionEnd);
                ////	}
                //    if (!processInfo.System)
                //	{
                //		this.UpdateDisplayText(this.Text);
                //
                //		if (!processInfo.FocusExit)
                //		{
                //		    this.SetSelection(this.SelectionStart, this.SelectionEnd);
                //		}
                //	}
                //	//end by Ryan Wu at 16:26 May. 18 2007.
                if (!processInfo.System) {
                    if (processInfo.FocusExit) {
                        this.SetHideValue();

                        //Add comments by Ryan Wu at 16:32 Aug. 28 2007.
                        //For in number if we don't set the processInfo.System, the return value of the KeyDown of the Number control will
                        //return true(because DecimalPoint maybe be not a '.', it can be any input char). So if the key invoke the focus exit,
                        //we should return false to prevent the onkeypress event.
                        processInfo.System = false;
                        //end by Ryan Wu.
                    } else {
                        this.UpdateDisplayText(this.Text);

                        // add by Sean Huang at 2009.01.06, for bug 1454 -->
                        if (oldLength === 0 && newLength !== 0) {
                            input.Utility.ShouldFireOnSelectStart = true;
                        } else {
                            input.Utility.ShouldFireOnSelectStart = false;
                        }

                        // end of Sean Huang <--
                        this.SetSelection(this.SelectionStart, this.SelectionEnd);

                        // add by Sean Huang at 2009.01.06, for bug 1454 -->
                        input.Utility.ShouldFireOnSelectStart = false;

                        // end of Sean Huang <--
                        //Add comments by Ryan Wu at 17:10 Sep. 24 2007.
                        //For fix the bug#8923.
                        //Only For number bug.
                        processInfo.HasSetSelection = true;
                        //end by Ryan Wu.
                    }
                }

                //end by Ryan Wu at 11:17 Aug. 28 2007.
                //del the code by wuhao 2008-8-11 for fix bug 419
                //	if (processInfo.FocusType != null)
                //	{
                //		this.FocusType = processInfo.FocusType;
                //	}
                //end by wuhao for fix bug 419
                if (processInfo.EventInfo) {
                    // change by Sean Huang at 2008.10.30, for bug 9908 -->
                    // ->
                    ////Add comments by Ryan Wu at 11:57 Apr. 5 2007.
                    ////For support Aspnet Ajax 1.0.
                    ////var focusType = this.UIProcess.FireEvent(this, processInfo.EventInfo.Name, processInfo.EventInfo.Args);
                    //var focusType = this.UIProcess.FireEvent(this, processInfo.EventInfo.Name, processInfo.EventInfo.Args, processInfo.EventInfo.Type);
                    ////end by Ryan Wu.
                    //
                    //if (focusType != null)
                    //{
                    //	this.FocusType = focusType;
                    //}
                    //<-
                    if (processInfo.EventInfo.Type === "KeyExit") {
                        this.EventInfo = processInfo.EventInfo;
                    } else {
                        //Add comments by Ryan Wu at 11:57 Apr. 5 2007.
                        //For support Aspnet Ajax 1.0.
                        //var focusType = this.UIProcess.FireEvent(this, processInfo.EventInfo.Name, processInfo.EventInfo.Args);
                        var focusType = this.UIProcess.FireEvent(this, processInfo.EventInfo.Name, processInfo.EventInfo.Args, processInfo.EventInfo.Type);

                        //end by Ryan Wu.
                        if (focusType != null) {
                            this.FocusType = focusType;
                        }
                    }
                    // end of Sean Huang <--
                }

                //del the code by wuhao 2008-8-11 for fix bug 419
                if (processInfo.FocusType != null) {
                    this.FocusType = processInfo.FocusType;
                }

                //end by wuhao for fix bug 419
                //For Number
                retInfo = processInfo;
                retInfo.KeyAction = keyAction;

                return retInfo;
            };

            BaseInputControl.prototype.GetImeInputText = function (actionType) {
                var newValue = this.GetTextboxValue();

                if (newValue === this.Text) {
                    return "";
                }
                var imeInputText;

                //Now get the input ime text;
                if (this.Text !== "") {
                    var start = Math.min(this.SelectionStart, this.SelectionEnd);
                    var end = Math.max(this.SelectionStart, this.SelectionEnd);
                    if (end < this.Text.GetLength()) {
                        var lastText = this.Text.Substring(end, this.GetText().GetLength());
                        var textIndex = newValue.IndexOf(lastText);

                        if (textIndex !== -1) {
                            //imeInputText = newValue.Substring(start, textIndex);
                            imeInputText = newValue.Substring(start, newValue.GetLength() - lastText.GetLength());
                        } else {
                            imeInputText = "";
                        }
                    } else {
                        imeInputText = newValue.Substring(start, newValue.GetLength());
                    }
                } else {
                    imeInputText = newValue;
                }

                //Discard the new input character.
                if (actionType === "ReInput") {
                    imeInputText = imeInputText.Substring(0, imeInputText.GetLength());
                }

                if (actionType === "Record") {
                    return imeInputText;
                }

                if (actionType === "LoseFocusInput") {
                    if (imeInputText === "") {
                        return "";
                    }
                }

                this.ImeMode = false;
                this.ImeSelect = false;

                //We can not control ime start and end,so if there are two times ime operation
                //in the same input case. We should check all the characters and close ime.
                if (actionType === "ReInput" || actionType === "ClickInput") {
                    this.FocusType = 8 /* ImeInput */;
                    this.InputElement.blur();
                    this.InputElement.focus();
                }

                return imeInputText;
            };

            /**
            * Handle the onkeyup event.
            */
            BaseInputControl.prototype.KeyUp = function (k) {
            };

            BaseInputControl.prototype.GetVisible = function () {
                return true;
            };

            /**
            * Handle the Dropdown action.
            */
            BaseInputControl.prototype.PerformDropDown = function () {
                // Frank Liu fixed bug 738 at 2013/06/17.
                if (!this.Enabled || !this.GetDropDownEnabled()) {
                    return;
                }

                //Add comments by Ryan Wu at 19:39 May. 28 2007.
                //For fix the bug#8147.
                if (!this.GetVisible()) {
                    return;
                }

                //end by Ryan Wu.
                // TODO:
                //// Frank Liu fixed bug 1127 at 2013/07/22.
                //if (this.GetContainer().offsetWidth === 0 && this.GetContainer().offsetHeight === 0) {
                //    return;
                //}
                if (!this.DroppedDown) {
                    if (this.DropDownObj) {
                        if (this.DropDownObj.GetDropDownContainer !== undefined) {
                            var dropDownContainer = this.DropDownObj.GetDropDownContainer();
                            if (input.Utility.IsTouchMouseDown) {
                                input.Utility.SetZoomStyle(dropDownContainer, this.TouchDropDownScale, this.DropDownObj.GetAlign());
                            } else {
                                input.Utility.SetZoomStyle(dropDownContainer, "");
                            }
                        }
                    }
                    this.ShowDropDown();
                } else {
                    this.CloseDropDown();
                }
            };

            /**
            * Handle the Dropdown button onmousedown event.
            */
            BaseInputControl.prototype.DropDownBtnMouseDown = function (mouseButton) {
                this.DropDownBtnPressed = true;

                if (mouseButton !== 0 /* Left */ && mouseButton != null) {
                    return;
                }

                this.PerformDropDown();

                //Add comments by Ryan Wu at 11:42 Jul. 28 2006.
                //For fix bug#5782.
                this.SetInnerFocus();

                //end by Ryan Wu.
                //Add comments by Ryan Wu at 10:05 Oct. 11 2007.
                //For fix the bug#8899.
                if (this.DroppedDown) {
                    //this.ResetLocationHandler = new Function("FindIMControl(\"" + this.ID + "\").ResetLocation()");
                    this.ResetLocation();
                }
                //end by Ryan Wu.
            };

            /**
            * Handle the Dropdown button onmouseup event.
            */
            BaseInputControl.prototype.DropDownBtnMouseUp = function () {
                this.DropDownBtnPressed = false;

                //Add comments by Ryan Wu at 11:42 Jul. 28 2006.
                //For fix bug#5782.
                this.SetInnerFocus();
                //end by Ryan Wu.
                //Add comments by Ryan Wu at 10:05 Oct. 11 2007.
                //For fix the bug#8899.
                //For move the following action to the document.onmouseup event.
                //	//Add by Ryan Wu at Dec 15, 2005. To fix bug#4684
                //	//Only date and number have such bug.
                //	this.ResetLocation();
                //	//end by Ryan Wu at Dec 15, 2005.
                //end by Ryan Wu at 10:05 Oct. 11 2007.
            };

            /**
            * Handle the Dropdown button onmouseup event.
            */
            BaseInputControl.prototype.ResetLocation = function () {
            };

            /**
            * Handle the Dropdown button onmouseup event.
            */
            BaseInputControl.prototype.DropDownBtnMouseOut = function () {
                if (this.DropDownBtnPressed) {
                    this.SetInnerFocus();
                    this.DropDownBtnPressed = false;
                }
            };

            /**
            * Show the dropdown calendar.
            */
            BaseInputControl.prototype.ShowDropDown = function (styles) {
                if (styles != null) {
                    this.UIUpdate.WriteCssStyle(styles);
                }
            };

            /**
            * Close the dropdown calendar.
            */
            BaseInputControl.prototype.CloseDropDown = function () {
                this.DroppedDown = false;
                this.DropDownObj.Close();
                this.UIUpdate.ClearCssStyle();

                //Fire DropDownClose event
                //Add comments by Ryan Wu at 9:46 Apr. 5 2007.
                //For support Aspnet Ajax 1.0.
                //var focusType = this.UIProcess.FireEvent(this, this.ClientEvents.SpecialClientEvents.DropDownClose, null);
                var focusType = this.UIProcess.FireEvent(this, this.DropDownCloseEvent, null, "DropDownClose");

                //end by Ryan Wu.
                if (focusType != null) {
                    this.FocusType = focusType;
                }
            };

            /**
            * Perform the spin action.
            */
            BaseInputControl.prototype.PerformSpin = function (type) {
                //    //Add by Jiang Changcheng at Feb. 10 2009
                //    //For fixed bug1705 TTP
                //    if (!Utility.LoadComplete)
                //    {
                //        return;
                //    }
                //    //End by Jiang
                var increment = this.Increment;

                //When format is null or pattern is "", we use the date as a textbox.
                if (this.IsNullFormat()) {
                    this.SetSelection(this.SelectionStart, this.SelectionEnd);
                } else if (this.GetReadOnly()) {
                    //Add by Ryan Wu at 13:07 Jan. 20 2006.
                    //For fix bug#4688.
                    //return;
                } else {
                    if (type === "down") {
                        increment *= -1;
                    }

                    var retInfo = this.UIProcess.PerformSpin(this.SelectionEnd, increment, this.Wrap);

                    if (!retInfo) {
                        return;
                    }

                    if (retInfo.Text != null) {
                        if (!this.UpdateText(retInfo)) {
                            return;
                        }
                    }

                    if (retInfo.SelectionStart != null) {
                        this.SelectionStart = retInfo.SelectionStart;
                        this.SelectionEnd = retInfo.SelectionStart;
                    }

                    this.UpdateDisplayText(this.Text);
                    this.SetInnerFocus();
                    this.SetSelection(this.SelectionStart, this.SelectionEnd);
                }

                var focusType = 3 /* ClientEvent */;

                if (type === "up") {
                    focusType = this.UIProcess.FireEvent(this, this.SpinUpEvent, null, "SpinUp");
                } else if (type === "down") {
                    focusType = this.UIProcess.FireEvent(this, this.SpinDownEvent, null, "SpinDown");
                }

                if (focusType != null) {
                    this.FocusType = focusType;
                }
            };

            /**
            * Handle the Spin button onmousedown event.
            */
            BaseInputControl.prototype.SpinBtnMouseDown = function (mouseButton, type) {
                this.SpinBtnPressed = true;

                if (this.DroppedDown) {
                    this.CloseDropDown();

                    //Add comments by Ryan Wu at 17:18 Dec. 22 2006.
                    //For fix bug#7142.
                    this.SetInnerFocus();

                    //end by Ryan Wu.
                    return;
                }

                if (mouseButton != 0 /* Left */ && mouseButton != null) {
                    return;
                }

                var stringType = type === true ? "up" : "down";

                this.PerformSpin(stringType);

                //Add comments by Ryan Wu at 10:59 Nov. 6 2006.
                //For fix bug#6190.
                this.SetInnerFocus();

                //end by Ryan Wu.
                //Add comments by Ryan Wu at 16:12 Apr. 21 2007.
                //For support Aspnet Ajax 1.0.
                //For fix the bug that Spin can not stop when release mouse after keep to click SpinDown and SpinUp a moment.
                //set timer. if we press button continuously, we must invoke the SpinBtnMouseDown.
                //	if (this.Timer == null)
                //	{
                //		this.Timer = setInterval("o" + this.ID + "IMControl.PerformSpin('" + type + "')", this.Spin.Delay);
                //	}
                if (input.Utility.SpinTimer == null) {
                    var self = this;
                    input.Utility.SpinTimer = setInterval(function () {
                        self.PerformSpin(stringType);
                    }, this._getRealSpinDelay());
                }
                //end by Ryan Wu.
            };
            BaseInputControl.prototype._getRealSpinDelay = function () {
                return this.Delay === 0 ? 150 : this.Delay;
            };

            /**
            * Handle the Spin button onmouseup event.
            */
            BaseInputControl.prototype.SpinBtnMouseUp = function () {
                if (this.SpinBtnPressed) {
                    this.SetInnerFocus();
                    this.SpinBtnPressed = false;
                }

                if (input.Utility.SpinTimer != null) {
                    clearInterval(input.Utility.SpinTimer);
                    input.Utility.SpinTimer = null;
                }
                //end by Ryan Wu.
            };

            /**
            * Handle the onselectstart event.
            */
            BaseInputControl.prototype.SelectStart = function (selText) {
                //When format is null or pattern is "", we use the date as a textbox.
                if (this.IsNullFormat()) {
                    return true;
                }

                var retInfo = this.UIProcess.SelectStart(this.InputElement, selText, this.MouseButton);

                if (retInfo.SelectionStart != null) {
                    this.SelectionStart = retInfo.SelectionStart;
                }

                if (retInfo.SetFalse != null) {
                    return retInfo.SetFalse;
                }
            };

            /**
            * Handle the ondblclick event.
            */
            BaseInputControl.prototype.DoubleClick = function () {
                //When format is null or pattern is "", we use the date as a textbox.
                if (this.IsNullFormat()) {
                    return true;
                }

                var retInfo = this.UIProcess.DoubleClick(this.SelectionStart);

                if (retInfo.SelectionStart != null) {
                    this.SelectionStart = retInfo.SelectionStart;
                }

                if (retInfo.SelectionEnd != null) {
                    this.SelectionEnd = retInfo.SelectionEnd;
                    this.SetSelection(this.SelectionStart, this.SelectionEnd);
                }
            };

            /**
            * Handle the undo event.
            */
            BaseInputControl.prototype.Undo = function () {
                if (this.GetReadOnly()) {
                    return;
                }

                var retInfo = this.UIProcess.Undo();

                if (!retInfo) {
                    return;
                }

                if (retInfo.Text != null) {
                    //this.SetText(retInfo.Text);
                    //this.Text = retInfo.Text;
                    //commented by Kevin, Jun 7, 2007
                    //bug#8388
                    //if (!this.UpdateText(retInfo.Text))
                    if (!this.UpdateText(retInfo)) {
                        return;
                    }
                    this.UpdateDisplayText(this.Text);
                    this.SetSelection(this.SelectionStart, this.SelectionEnd);
                }
            };

            /**
            * Handle the cut actions.
            */
            BaseInputControl.prototype.Cut = function () {
                if (this.GetReadOnly()) {
                    return;
                }

                var retInfo = this.UIProcess.Cut(this.GetClipContent(), this.SelectionStart, this.SelectionEnd);

                if (!retInfo) {
                    return;
                }

                if (retInfo.Text != null) {
                    //this.SetText(retInfo.Text);
                    //this.Text = retInfo.Text;
                    //commented by Kevin, Jun 7, 2007
                    //bug#8388
                    //if (!this.UpdateText(retInfo.Text))
                    if (!this.UpdateText(retInfo)) {
                        return;
                    }
                }

                if (retInfo.SelectionStart != null) {
                    this.SelectionStart = retInfo.SelectionStart;
                }

                if (retInfo.SelectionEnd != null) {
                    this.SelectionEnd = retInfo.SelectionEnd;
                }

                if (retInfo.Text != null) {
                    this.UpdateDisplayText(this.Text);
                    this.SetSelection(this.SelectionStart, this.SelectionEnd);
                }

                // Frank Liu fixed bug 646 at 2013/06/14.
                if (retInfo.Color !== null) {
                    this.UIUpdate.SetForeColor(retInfo.Color);
                }
            };

            /**
            * Handle the oncopy event.
            */
            BaseInputControl.prototype.Copy = function () {
                this.UIProcess.Copy(this.GetClipContent(), this.SelectionStart, this.SelectionEnd);
            };

            /**
            * Handle the onpaste event.
            */
            BaseInputControl.prototype.Paste = function (text) {
                if (this.GetReadOnly()) {
                    return false;
                }

                if (this.IsNullFormat()) {
                    return false;
                }

                var pasteData = input.Utility.GetPasteData(this.GetUseClipboard());

                if (text) {
                    pasteData = text;
                }

                var retInfo = this.UIProcess.Paste(this.SelectionStart, this.SelectionEnd, pasteData);

                if (!retInfo) {
                    return false;
                }

                if (retInfo.Text != null) {
                    //this.SetText(retInfo.Text);
                    //this.Text = retInfo.Text;
                    //commented by Kevin, Jun 7, 2007
                    //bug#8388
                    //if (!this.UpdateText(retInfo.Text))
                    if (!this.UpdateText(retInfo)) {
                        return false;
                    }
                }

                if (retInfo.SelectionStart != null) {
                    this.SelectionStart = retInfo.SelectionStart;
                }

                if (retInfo.SelectionEnd != null) {
                    this.SelectionEnd = retInfo.SelectionEnd;
                }

                this.UpdateDisplayText(this.Text);
                this.SetSelection(this.SelectionStart, this.SelectionEnd);

                if (retInfo.EventInfo != null) {
                    //Add comments by Ryan Wu at 13:03 Apr. 5 2007.
                    //For support Aspnet Ajax 1.0.
                    //this.UIProcess.FireEvent(this, retInfo.EventInfo.Name, retInfo.EventInfo.Args);
                    this.UIProcess.FireEvent(this, retInfo.EventInfo.Name, retInfo.EventInfo.Args, retInfo.EventInfo.Type);
                    //end by Ryan Wu.
                }

                if (retInfo.FocusExit != null) {
                    this.FocusExit = retInfo.FocusExit;
                }

                return true;
            };

            /**
            * Delete the selected content.
            */
            BaseInputControl.prototype.Delete = function () {
                if (this.GetReadOnly()) {
                    return;
                }

                var retInfo = this.UIProcess.ProcessDelete(this.SelectionStart, this.SelectionEnd);

                if (!retInfo) {
                    return;
                }

                if (retInfo.Text != null) {
                    //this.SetText(retInfo.Text);
                    //this.Text = retInfo.Text;
                    //commented by Kevin, Jun 7, 2007
                    //bug#8388
                    //if (!this.UpdateText(retInfo.Text))
                    if (!this.UpdateText(retInfo)) {
                        return;
                    }
                }

                if (retInfo.SelectionStart != null) {
                    this.SelectionStart = retInfo.SelectionStart;
                }

                if (retInfo.SelectionEnd != null) {
                    this.SelectionEnd = retInfo.SelectionEnd;
                }

                if (retInfo.Text != null) {
                    this.UpdateDisplayText(this.Text);
                    this.SetSelection(this.SelectionStart, this.SelectionEnd);
                    this.DoDeleteExtraWork();
                }
            };

            BaseInputControl.prototype.DoDeleteExtraWork = function () {
            };

            /**
            * Select all the content.
            */
            BaseInputControl.prototype.SelectAll = function () {
                var retInfo = this.UIProcess.SelectAll();

                if (retInfo.SelectionStart != null) {
                    this.SelectionStart = retInfo.SelectionStart;
                }

                if (retInfo.SelectionEnd != null) {
                    this.SelectionEnd = retInfo.SelectionEnd;
                }

                this.SetSelection(this.SelectionStart, this.SelectionEnd);

                //Add comments by Ryan Wu at 9:23 Oct. 18 2007.
                //For fix the bug#9065.
                this.FocusType = 2 /* ContextMenu */;
                //end by Ryan Wu.
            };

            /**
            * Handle the ondrop event.
            */
            BaseInputControl.prototype.DragDrop = function (text) {
                // add by Sean Huang at 2008.11.06, for bug 10298 -->
                if (!input.CoreUtility.IsIE() && this.GetReadOnly()) {
                    return false;
                }

                // end of Sean Huang <--
                if (this.DragStartElementID === this.ID) {
                    this.DragStartElementID = "";

                    // TODO:
                    //Utility.PreventDefault(evt);
                    return false;
                }

                var retInfo = this.UIProcess.Paste(0, 0, text);

                if (!retInfo) {
                    return;
                }

                if (retInfo.Text != null) {
                    //this.SetText(retInfo.Text);
                    //this.Text = retInfo.Text;
                    //commented by Kevin, Jun 7, 2007
                    //bug#8388
                    //if (!this.UpdateText(retInfo.Text))
                    if (!this.UpdateText(retInfo)) {
                        return;
                    }

                    //Add comments by Ryan Wu at 11:34 Aug. 15 2007.
                    //For firefox doesn't support drag drop action event, we must
                    //imitate it.
                    if (!input.CoreUtility.IsIE()) {
                        //this.UpdateDisplayText(this.Text);
                        this.SetInnerFocus();
                    }
                    //end by Ryan Wu.
                }

                if (retInfo.SelectionStart != null) {
                    this.SelectionStart = retInfo.SelectionStart;
                }

                if (retInfo.SelectionEnd != null) {
                    this.SelectionEnd = retInfo.SelectionEnd;
                }

                this.SetSelection(this.SelectionStart, this.SelectionEnd);

                if (retInfo.EventInfo != null) {
                    //Add comments by Ryan Wu at 13:03 Apr. 5 2007.
                    //For support Aspnet Ajax 1.0.
                    //this.UIProcess.FireEvent(this, retInfo.EventInfo.Name, retInfo.EventInfo.Args);
                    this.UIProcess.FireEvent(this, retInfo.EventInfo.Name, retInfo.EventInfo.Args, retInfo.EventInfo.Type);
                    //end by Ryan Wu.
                }
            };

            //For AutoTest
            //Add by Ryan Wu at 16:40 Nov.24 2005.
            BaseInputControl.prototype.SetInnerText = function (text) {
                this.SetText(text);
            };

            BaseInputControl.prototype.SetText = function (text) {
            };

            BaseInputControl.prototype.GetInnerText = function () {
                return this.Text;
            };

            BaseInputControl.prototype.UpdateText = function (retInfo) {
                if (retInfo != null && retInfo.Text != null) {
                    this.Text = retInfo.Text;
                }

                return true;
            };

            //end by Kevin
            /**
            * rollback inner text.
            */
            BaseInputControl.prototype.RollBack = function () {
            };

            BaseInputControl.prototype.AddAllEventsHandler = function () {
                var self = this;
                var inputElement = this.GetInputElement();
                if (inputElement != null) {
                    $(inputElement).bind("mousedown.wijinput", function (evt) {
                        input.GlobalEventHandler.OnMouseDown(self, evt);
                    });

                    $(inputElement).bind("mouseup.wijinput", function (evt) {
                        input.GlobalEventHandler.OnMouseUp(self, evt);
                    });

                    $(inputElement).bind("selectstart.wijinput", function (evt) {
                        input.GlobalEventHandler.OnSelectStart(self, evt);
                    });

                    $(inputElement).bind("keydown.wijinput", function (evt) {
                        input.GlobalEventHandler.OnKeyDown(self, evt);
                    });

                    $(inputElement).bind("keypress.wijinput", function (evt) {
                        var ev = evt;
                        input.GlobalEventHandler.OnKeyPress(self, ev);
                    });

                    $(inputElement).bind("keyup.wijinput", function (evt) {
                        input.GlobalEventHandler.OnKeyUp(self, evt);
                    });

                    $(inputElement).bind("dblclick.wijinput", function (evt) {
                        input.GlobalEventHandler.OnDblClick(self, evt);
                    });

                    $(inputElement).bind("beforecopy.wijinput", function (evt) {
                        input.GlobalEventHandler.OnHTML5BeforeCopy(self, evt);
                    });

                    $(inputElement).bind("cut.wijinput", function (evt) {
                        input.GlobalEventHandler.OnHTML5Cut(self, evt);
                    });

                    $(inputElement).bind("paste.wijinput", function (evt) {
                        input.GlobalEventHandler.OnHTML5Paste(self, evt);
                    });

                    $(inputElement).bind("focus.wijinput", function (evt) {
                        input.GlobalEventHandler.OnFocus(self, evt);
                    });
                    $(inputElement).bind("blur.wijinput", function (evt) {
                        input.GlobalEventHandler.OnLostFocus(self, evt);
                    });

                    // IE+chrome
                    $(inputElement).bind("mousewheel.wijinput", function (evt) {
                        input.GlobalEventHandler.OnMouseWheel(self, evt);
                    });

                    // FireFox.
                    $(inputElement).bind("DOMMouseScroll.wijinput", function (evt) {
                        input.GlobalEventHandler.OnMouseWheel(self, evt);
                    });

                    $(inputElement).bind("dragstart.wijinput", function (evt) {
                        input.GlobalEventHandler.OnDragStart(self, evt);
                    });

                    $(inputElement).bind("dragend.wijinput", function (evt) {
                        input.GlobalEventHandler.OnDragEnd(self, evt);
                    });

                    $(inputElement).bind("mouseout.wijinput", function (evt) {
                        input.GlobalEventHandler.OnMouseOut(self, evt);
                    });

                    $(inputElement).bind("drop.wijinput", function (evt) {
                        input.GlobalEventHandler.OnDrop(self, evt);
                    });

                    $(inputElement).bind("touchstart.wijinput", function (evt) {
                        input.GlobalEventHandler.OnTouchStart(self, evt);
                    });

                    $(inputElement).bind("touchend.wijinput", function (evt) {
                        input.GlobalEventHandler.OnTouchEnd(self, evt);
                    });

                    $(inputElement).bind("select.wijinput", function (evt) {
                        input.GlobalEventHandler.OnSelect(self, evt);
                    });

                    // Frank Liu fixed bug 662 at 2013/07/10.
                    //safari
                    if (input.CoreUtility.safari) {
                        $(inputElement).bind("dragenter.wijinput", function (evt) {
                            self._safariDropText = getSelection().toString();
                        });
                        $(inputElement).bind("dragleave.wijinput", function (evt) {
                            self._safariDropText = null;
                        });
                    }

                    $(inputElement).bind("compositionstart.wijinput", function (evt) {
                        input.GlobalEventHandler.OnCompositionStart(self, evt);
                    });

                    $(inputElement).bind("compositionupdate.wijinput", function (evt) {
                        input.GlobalEventHandler.OnCompositionUpdate(self, evt);
                    });

                    $(inputElement).bind("compositionend.wijinput", function (evt) {
                        input.GlobalEventHandler.OnCompositionEnd(self, evt);
                    });

                    if (input.CoreUtility.IsPad()) {
                        $(inputElement).bind("input.wijinput", function (evt) {
                            input.GlobalEventHandler.OnInput(self, evt);
                        });
                    }
                }
            };

            // add by Sean Huang at 2008.12.10, for bug 779 -->
            BaseInputControl.prototype.ResetData = function (data) {
                this.SetText(data.ResetData);
            };

            BaseInputControl.prototype._createElementForNoSpinAndNoDropDown = function (inputElement) {
                return inputElement;
            };

            BaseInputControl.prototype._addControlEventHandler = function () {
            };

            BaseInputControl.prototype._reCreate = function () {
            };

            BaseInputControl.prototype._onSpinPropertyChanged = function (propertyName) {
                propertyName = propertyName.toLowerCase();
                if (propertyName === "alignment" || propertyName === "position") {
                    if (this._getRealSpinVisible()) {
                        this._reCreate();
                    }
                } else if (propertyName === "visible") {
                    this._reCreate();
                } else if (propertyName === "enabled") {
                } else if (propertyName === "spinupimage" || propertyName === "spindownimage" || propertyName === "pressedspinupimage" || propertyName === "pressedspindownimage") {
                }
            };

            BaseInputControl.prototype._onDropDownPropertyChanged = function (propertyName) {
                propertyName = propertyName.toLowerCase();
                if (propertyName === "position") {
                    if (this._getRealDropDownVisible()) {
                        this._reCreate();
                    }
                } else if (propertyName === "visible") {
                    this._reCreate();
                } else if (propertyName === "enabled") {
                } else if (propertyName === "buttonimage" || propertyName === "pressedbuttonimage") {
                }
            };

            BaseInputControl.prototype._isSupportClipBoard = function () {
                if (!this.GetUseClipboard()) {
                    return true;
                }

                if (input.CoreUtility.IsIE()) {
                    return true;
                }

                //if (Utility.IsFireFox4OrLater()) {
                //    try {
                //        netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
                //        var clip = Components.classes['@mozilla.org/widget/clipboard;1'].createInstance(Components.interfaces.nsIClipboard);
                //        if (!clip) {
                //            return;
                //        }
                //        var trans = Components.classes['@mozilla.org/widget/transferable;1'].createInstance(Components.interfaces.nsITransferable);
                //        if (!trans) {
                //            return;
                //        }
                //        trans.addDataFlavor('text/unicode');
                //        clip.getData(trans, clip.kGlobalClipboard);
                //        var str = {};
                //        var len = {};
                //        try {
                //            trans.getTransferData('text/unicode', str, len);
                //        } catch (error) {
                //            return null;
                //        }
                //        if (str) {
                //            if (Components.interfaces.nsISupportsWString) {
                //                str = str.value.QueryInterface(Components.interfaces.nsISupportsWString);
                //            } else if (Components.interfaces.nsISupportsString) {
                //                str = str.value.QueryInterface(Components.interfaces.nsISupportsString);
                //            } else {
                //                str = null;
                //            }
                //        }
                //        if (str) {
                //            return (str.data.substring(0, len.value / 2));
                //        }
                //    } catch (e) {
                //        return false;
                //    }
                //}
                return false;
            };

            BaseInputControl.prototype._onpropertyChanged = function () {
            };

            /**
            * Gets the delay of spin.
            * @returns {number}
            */
            BaseInputControl.prototype.GetSpinDelay = function () {
                return this.Delay;
            };

            /**
            * Sets the delay of spin.
            * @param {number} value
            * @throws Delay value should not be less than zero or greater than the max value.
            */
            BaseInputControl.prototype.SetSpinDelay = function (value) {
                this.Delay = value;
            };

            /**
            * Gets whether the spin is enabled.
            * @returns {boolean}
            */
            BaseInputControl.prototype.GetSpinEnabled = function () {
                return this.SpinEnabled && this.Enabled;
            };

            /**
            * Sets whether the spin is enabled.
            * @param {boolean} value
            */
            BaseInputControl.prototype.SetSpinEnabled = function (value) {
                this.SpinEnabled = value;
            };

            /**
            * Gets the spin increment value.
            * @returns {number}
            */
            BaseInputControl.prototype.GetSpinIncrement = function () {
                return this.Increment;
            };

            /**
            * Sets the spin increment value.
            * @param {number} value
            */
            BaseInputControl.prototype.SetSpinIncrement = function (value) {
                this.Increment = value;
            };

            /**
            * Gets a value indicated whether user can spin by key.
            * @returns {boolean}
            */
            BaseInputControl.prototype.GetSpinOnKeys = function () {
                return this.SpinOnKeys;
            };

            /**
            * Sets a value indicated whether user can spin by key.
            * @param {boolean} value
            */
            BaseInputControl.prototype.SetSpinOnKeys = function (value) {
                this.SpinOnKeys = value;
            };

            /**
            * Gets the visibility of the spin button.
            * @returns {boolean}
            */
            BaseInputControl.prototype.GetSpinVisible = function () {
                return this.Visible;
            };

            BaseInputControl.prototype._getRealSpinVisible = function () {
                return this.GetSpinVisible();
            };

            /**
            * Sets the visibility of the spin button.
            * @returns {boolean}
            */
            BaseInputControl.prototype.SetSpinVisible = function (value) {
                this.Visible = value;
            };

            /**
            * Gets whether the value iterated when spin out the max/min value of the control.
            * @returns {boolean}
            */
            BaseInputControl.prototype.GetSpinWrap = function () {
                return this.Wrap;
            };

            /**
            * Sets whether the value iterated when spin out the max/min value of the control.
            * @param {boolean} value
            */
            BaseInputControl.prototype.SetSpinWrap = function (value) {
                this.Wrap = value;
            };

            /**
            * Gets whether the drop-down object is displayed when the control receives focus.
            * @returns {boolean}
            */
            BaseInputControl.prototype.GetAutoDropDown = function () {
                return this._dropDown.AutoDropDown;
            };

            /**
            * Sets whether the drop-down object is displayed when the control receives focus.
            * @param {boolean} value
            */
            BaseInputControl.prototype.SetAutoDropDown = function (value) {
                this._dropDown.SetAutoDropDown(value);
            };

            /**
            * Gets the background image URL of drop-down button.
            * @returns {string}
            */
            BaseInputControl.prototype.GetDropDownButtonImageUrl = function () {
                return this._dropDown.GetButtonImage();
            };

            /**
            * Sets the background image URL of drop-down button.
            * @param {string} value
            */
            BaseInputControl.prototype.SetDropDownButtonImageUrl = function (value) {
                this._dropDown.SetButtonImage(value);
            };

            /**
            * Gets the animation effect when drop-down control closing.
            * @returns {DropDownAnimation}
            */
            BaseInputControl.prototype.GetDropDownClosingAnimation = function () {
                return this._dropDown.ClosingAnimation;
            };

            /**
            * Sets the animation effect when drop-down control closing.
            * @param {DropDownAnimation} value
            */
            BaseInputControl.prototype.SetDropDownClosingAnimation = function (value) {
                this._dropDown.SetClosingAnimation(value);
            };

            /**
            * Gets whether the drop-down control has a shadow.
            * @returns {boolean}
            */
            BaseInputControl.prototype.GetDropDownShadow = function () {
                return this._dropDown.DropDownShadow;
            };

            /**
            * Sets whether the drop-down field has a shadow.
            * @param {boolean} value
            */
            BaseInputControl.prototype.SetDropDownShadow = function (value) {
                this._dropDown.SetDropDownShadow(value);
            };

            /**
            * Gets whether the drop-down control is enabled.
            * @returns {boolean}
            */
            BaseInputControl.prototype.GetDropDownEnabled = function () {
                return this._dropDown.GetEnabled() && this.Enabled;
            };

            /**
            * Sets whether the drop-down control is enabled.
            * @param {boolean} value
            */
            BaseInputControl.prototype.SetDropDownEnabled = function (value) {
                this._dropDown.SetEnabled(value);
            };

            /**
            * Gets the animation effect when drop-down control openning.
            * @returns {DropDownAnimation}
            */
            BaseInputControl.prototype.GetDropDownOpeningAnimation = function () {
                return this._dropDown.OpeningAnimation;
            };

            /**
            * Sets the animation effect when drop-down control openning.
            * @param {DropDownAnimation} value
            */
            BaseInputControl.prototype.SetDropDownOpeningAnimation = function (value) {
                this._dropDown.SetOpeningAnimation(value);
            };

            /**
            * Gets the position of the drop-down button.
            * @returns {ButtonPosition}
            */
            BaseInputControl.prototype.GetDropDownPosition = function () {
                return this._dropDown.Position;
            };

            /**
            * Sets the position of the drop-down button.
            * @param {ButtonPosition} value
            */
            BaseInputControl.prototype.SetDropDownPosition = function (value) {
                this._dropDown.SetPosition(value);
            };

            /**
            * Gets the background image URL of pressed drop-down button.
            * @returns {string}
            */
            BaseInputControl.prototype.GetPressedDropDownButtonImageUrl = function () {
                return this._dropDown.GetPressedButtonImage();
            };

            /**
            * Sets the background image URL of pressed drop-down button.
            * @param {string} value
            */
            BaseInputControl.prototype.SetPressedDropDownButtonImageUrl = function (value) {
                this._dropDown.SetPressedButtonImage(value);
            };

            /**
            * Gets the visibility of the drop-down button.
            * @returns {boolean}
            */
            BaseInputControl.prototype.GetDropDownVisible = function () {
                return this._dropDown.Visible;
            };

            BaseInputControl.prototype._getRealDropDownVisible = function () {
                return this.GetDropDownVisible();
            };

            /**
            * Sets the visibility of the drop-down button.
            * @returns {boolean}
            */
            BaseInputControl.prototype.SetDropDownVisible = function (value) {
                this._dropDown.SetVisible(value);
            };
            return BaseInputControl;
        })();
        input.BaseInputControl = BaseInputControl;

        /** @ignore */
        var KeywordType;
        (function (KeywordType) {
            KeywordType[KeywordType["OctalAscII"] = 0x00] = "OctalAscII";
            KeywordType[KeywordType["HexAscII"] = 0x01] = "HexAscII";
            KeywordType[KeywordType["HexUnicode"] = 0x02] = "HexUnicode";
            KeywordType[KeywordType["DefinedCharBase"] = 0x03] = "DefinedCharBase";
            KeywordType[KeywordType["DefinedCharAddition"] = 0x04] = "DefinedCharAddition";
            KeywordType[KeywordType["CharSubset"] = 0x05] = "CharSubset";
            KeywordType[KeywordType["EnumGroup"] = 0x06] = "EnumGroup";
            KeywordType[KeywordType["Quantifier"] = 0x07] = "Quantifier";
            KeywordType[KeywordType["PromptChar"] = 0x08] = "PromptChar";
            KeywordType[KeywordType["Unknow"] = 0x09] = "Unknow";
        })(KeywordType || (KeywordType = {}));

        /** @ignore */
        var MaskFormat = (function () {
            function MaskFormat() {
            }
            MaskFormat.ParseFormat = function (pattern, owner) {
                MaskFormat.Owner = owner;
                var fields = new MaskFieldCollection(MaskFormat.Owner, 0, false);
                if (pattern === null || pattern.length === 0) {
                    var ffield = new FilterField(MaskFormat.Owner);
                    var bitsState = new Array();
                    ffield._bitState = bitsState;
                    var uf = new UnionFilter(MaskFormat.Owner, true);
                    var ff = new FullWidthFilter(MaskFormat.Owner, true);
                    uf.Add(ff);
                    var hf = new HalfWidthFilter(MaskFormat.Owner, true);
                    uf.Add(hf);

                    // DaryLuo 2013/07/01 fix bug 544 in IM HTML 5.0.
                    var tf = new SurrogateFilter(MaskFormat.Owner, true);
                    uf.Add(tf);

                    ffield.FilterField(0, 2147483647, uf, bitsState);
                    ffield.InitialText('');
                    ffield._trueLength = 0;
                    fields.PushBack(ffield);
                    fields.formatIsNull = true;
                    return fields;
                }

                var caret = 0;
                var promptS = "";
                var lastKeyType = 8 /* PromptChar */;
                var nextKeyType = 5 /* CharSubset */;
                var keyWordResult = MaskFormat.GetKeyWord(pattern, caret);
                var keyWord = keyWordResult.KeyWord;
                var keyType = keyWordResult.KeyType;
                var keyLen = keyWordResult.KeyLen;
                var filter;
                while (pattern.length > caret) {
                    switch (keyType) {
                        case 9 /* Unknow */:
                            throw "InvalidParameter";
                        case 5 /* CharSubset */:
                            var analyseResult = MaskFormat.AnalyseCharSubset(keyWord);
                            uf = analyseResult.uf;
                            if (!analyseResult.Result) {
                                throw "Invalid parameter";
                            }
                            filter = uf;
                            lastKeyType = 5 /* CharSubset */;
                            break;
                        case 4 /* DefinedCharAddition */:
                            if (keyWord === '\\K') {
                                filter = new HalfWidthKatakanaFilter(MaskFormat.Owner, true);
                            } else if (keyWord === "\\H") {
                                filter = new HalfWidthFilter(MaskFormat.Owner, true);
                            } else if (keyWord === '\\N') {
                                filter = new SBCSKatakanaFilter(MaskFormat.Owner, true);
                            } else if (keyWord === "\\" + MaskFormat.DBCS_K) {
                                filter = new FullWidthKatakanaFilter(MaskFormat.Owner, true);
                            } else if (keyWord === "\\" + MaskFormat.DBCS_J) {
                                filter = new HiraganaFilter(MaskFormat.Owner, true);
                            } else if (keyWord === "\\" + MaskFormat.DBCS_M) {
                                filter = new ShiftJISFilter(MaskFormat.Owner, true);
                            } else if (keyWord === "\\" + MaskFormat.DBCS_I) {
                                filter = new JISX0208Filter(MaskFormat.Owner, true);
                            } else if (keyWord === "\\" + MaskFormat.DBCS_G) {
                                filter = new DBCSHiraganaFilter(MaskFormat.Owner, true);
                            } else if (keyWord === "\\" + MaskFormat.DBCS_N) {
                                filter = new DBCSKatakanaFilter(MaskFormat.Owner, true);
                            } else if (keyWord === "\\" + MaskFormat.DBCS_Z) {
                                filter = new FullWidthFilter(MaskFormat.Owner, true);
                            } else if (keyWord === "\\" + MaskFormat.DBCS_T) {
                                filter = new SurrogateFilter(MaskFormat.Owner, true);
                            } else {
                                throw "argument null";
                            }
                            lastKeyType = 5 /* CharSubset */;
                            break;
                        case 6 /* EnumGroup */:
                            var members = [];
                            if (MaskFormat.AnalyseEnumGroup(keyWord, members)) {
                                var filed = new EnumField(MaskFormat.Owner);
                                filed.Init(members);
                                fields.PushBack(filed);

                                lastKeyType = 6 /* EnumGroup */;
                                caret += keyLen;
                                var r = MaskFormat.GetKeyWord(pattern, caret);
                                keyWord = r.KeyWord;
                                keyType = r.KeyType;
                                keyLen = r.KeyLen;
                                continue;
                            } else {
                                throw "invalid parameter";
                            }
                        case 0 /* OctalAscII */:
                            try  {
                                var tempInt = keyWord.Substring(1);
                                tempInt = parseInt(tempInt, 8);
                                if (tempInt === 0) {
                                    throw "argument exception";
                                }
                                var c = String.fromCharCode(tempInt);
                                if (lastKeyType === 8 /* PromptChar */) {
                                    promptS += c;
                                } else {
                                    promptS = c;
                                    lastKeyType = 8 /* PromptChar */;
                                }
                            } catch (e) {
                                throw "invalid parameter";
                            }
                            break;
                        case 1 /* HexAscII */:
                        case 2 /* HexUnicode */:
                            try  {
                                var tempInt = keyWord.Substring(2);
                                tempInt = parseInt(tempInt, 16);
                                if (tempInt === 0) {
                                    throw "argument exception";
                                }
                                var c = String.fromCharCode(tempInt);
                                if (lastKeyType === 8 /* PromptChar */) {
                                    promptS += c;
                                } else {
                                    promptS = c;
                                    lastKeyType = 8 /* PromptChar */;
                                }
                            } catch (e) {
                                throw "invalid parameter";
                            }
                            break;
                        case 8 /* PromptChar */:
                            if (lastKeyType === 8 /* PromptChar */) {
                                promptS += keyWord;
                            } else {
                                promptS = keyWord;
                                lastKeyType = 8 /* PromptChar */;
                            }
                            break;
                        case 7 /* Quantifier */:
                            throw "invalid parameter";
                        default:
                            throw "invalid parameter";
                    }

                    caret += keyLen;

                    var max = 1, min = 1;

                    if (caret < pattern.length) {
                        keyWordResult = MaskFormat.GetKeyWord(pattern, caret);
                        keyWord = keyWordResult.KeyWord;
                        keyType = keyWordResult.KeyType;
                        keyLen = keyWordResult.KeyLen;
                        switch (keyType) {
                            case 9 /* Unknow */:
                                throw "invalid parameter";
                            case 5 /* CharSubset */:
                            case 4 /* DefinedCharAddition */:
                            case 6 /* EnumGroup */:
                                nextKeyType = 5 /* CharSubset */;
                                break;
                            case 7 /* Quantifier */:
                                var quantifierResult = MaskFormat.AnalyseQuantifier(keyWord);
                                min = quantifierResult.Min;
                                max = quantifierResult.Max;
                                if (!quantifierResult.Result) {
                                    throw "invalid parameter";
                                }

                                caret += keyLen;
                                keyWordResult = MaskFormat.GetKeyWord(pattern, caret);
                                keyWord = keyWordResult.KeyWord;
                                keyType = keyWordResult.KeyType;
                                keyLen = keyWordResult.KeyLen;
                                nextKeyType = 7 /* Quantifier */;
                                break;
                            case 0 /* OctalAscII */:
                            case 2 /* HexUnicode */:
                            case 1 /* HexAscII */:
                            case 8 /* PromptChar */:
                                nextKeyType = 8 /* PromptChar */;
                                break;
                        }
                        if (lastKeyType === 8 /* PromptChar */) {
                            if (nextKeyType !== 8 /* PromptChar */) {
                                // (Henry Jia) Quantifier is not allowed occur after PromptField
                                if (nextKeyType === 7 /* Quantifier */)
                                    throw "invalid parameter";

                                fields.PushBack(new PromptField(promptS));
                            }
                        } else {
                            var filterField = new FilterField(MaskFormat.Owner);
                            filterField.FilterField(min, max, filter, [false, false, false]);
                            filterField.InitialText(input.Utility.ToString(filterField.GetPromptChar(), min));
                            filterField._trueLength = 0;
                            fields.PushBack(filterField);
                        }
                    } else {
                        if (lastKeyType === 8 /* PromptChar */) {
                            fields.PushBack(new PromptField(promptS));
                        } else {
                            var filterField = new FilterField(MaskFormat.Owner);
                            filterField.FilterField(1, 1, filter, []);
                            fields.PushBack(filterField);
                        }
                    }
                }

                for (var l = 0; l < fields.fieldCount; l++) {
                    if (!(fields.GetFieldByIndex(l) instanceof PromptField))
                        break;
                }
                if (l === fields.fieldCount) {
                    throw "invalid parameter";
                }
                return fields;
            };

            MaskFormat.ParseFillExpression = function (expression, fileds) {
                var result = {};
                result.Expression = "";
                result.Result = true;
                if (expression === "{}") {
                    result.Expression = "{}";
                    result.Result = true;
                    return result;
                }

                if (expression !== undefined && expression !== null && expression.length > 0) {
                    try  {
                        var format = expression;
                        var fillingChar = '\0';
                        var parseResult = MaskFormat.ParseFillingString(format);

                        format = parseResult.Format;
                        fillingChar = parseResult.FillingChar;

                        if (fillingChar !== '\0') {
                            if (!MaskFormat.NullParse(format)) {
                                throw "argument exception";
                            }
                            if (fileds !== undefined && fileds !== null && fileds.fieldCount > 0) {
                                result.Expression = fileds.GetFillingString(fillingChar);
                            } else {
                                result.Expression = expression;
                            }
                        } else {
                            result.Expression = format;
                        }
                    } catch (e) {
                        throw "argument exception";
                    }
                } else {
                    result.Expression = null;
                }
                return result;
            };

            MaskFormat.ParseFillingString = function (format) {
                var result = {};
                result.Format = format;
                result.FillingChar = "\0";
                result.Result = false;
                if (format === undefined || format === null || format.length === 0) {
                    result.Result = false;
                    return result;
                }

                var nLpos = format.indexOf("{");
                var nRpos = format.indexOf("}");

                if (nLpos === -1 && nRpos === -1) {
                    format = MaskFormat.RemoveEscapeChar(format);
                    result.Format = format;
                    result.Result = false;
                    return result;
                } else {
                    while (nLpos > 0 && format.charAt(nLpos - 1) === '\\') {
                        nLpos = format.indexOf("{", nLpos + 1);
                    }
                    while (nRpos > 0 && format.charAt(nRpos - 1) === '\\') {
                        nRpos = format.indexOf("}", nRpos + 1);
                    }

                    if (nLpos < nRpos) {
                        if (nLpos === -1) {
                            format = MaskFormat.RemoveEscapeChar(format);
                            result.Format = format;
                            result.Result = false;
                            return result;
                        } else {
                            if (nRpos - nLpos === 1) {
                                result.Format = "";
                            } else {
                                if (format.charAt(nLpos + 1) === "{") {
                                    throw "argument exception";
                                } else if (format.charAt(nLpos + 1) === "\\") {
                                    if (nLpos + 2 < nRpos) {
                                        nLpos++;
                                    } else {
                                        throw "arugment exception";
                                    }
                                }

                                result.FillingChar = format.charAt(nLpos + 1);
                            }
                            result.Result = true;
                            return result;
                        }
                    } else {
                        format = MaskFormat.RemoveEscapeChar(format);
                        result.Format = format;
                        result.Result = false;
                        return result;
                    }
                }
            };

            MaskFormat.RemoveEscapeChar = function (format) {
                if (format.indexOf('\\') !== -1) {
                    var sb = "";
                    var len = format.length;

                    for (var i = 0; i < len; i++) {
                        if (format.charAt(i) === '\\') {
                            if (i + 1 < len) {
                                sb += format.charAt(++i);
                            }

                            continue;
                        }
                        sb += format.charAt(i);
                    }
                    return sb;
                }
                return format;
            };

            MaskFormat.NullParse = function (text) {
                var startIndex = MaskFormat.FindSpecialCh(text, "{", 0);
                var endIndex = MaskFormat.FindSpecialCh(text, "}", 0);

                if (startIndex > -1 && endIndex > -1) {
                    if (endIndex > startIndex) {
                        //not more '{'
                        if (MaskFormat.FindSpecialCh(text, "{", startIndex + 1) > -1) {
                            return false;
                        }

                        if (MaskFormat.FindSpecialCh(text, "}", endIndex + 1) > -1) {
                            return false;
                        }
                    }
                }

                return true;
            };

            MaskFormat.FindSpecialCh = function (text, specialCh, idx) {
                var sNum = 0;
                var startIndex = idx - 1;

                do {
                    startIndex = text.indexOf(specialCh, startIndex + 1);
                    if (startIndex === 0 || startIndex === -1) {
                        return startIndex;
                    }
                    for (var sCount = startIndex - 1; sCount > 0; sCount--) {
                        if (text.charAt(sCount) !== '\\') {
                            break;
                        }
                        sNum++;
                    }
                } while(text.charAt(startIndex - 1) === '\\' && (sNum % 2) !== 0);

                return startIndex;
            };

            MaskFormat.GetKeyWord = function (format, index) {
                var result = {};
                result.KeyLen = 0;
                result.KeyType = 9 /* Unknow */;
                result.KeyWord = null;
                if (index >= format.length) {
                    return result;
                }

                var cFirst = format.charAt(index);
                switch (cFirst) {
                    case '\\':
                        // Is Escape Char ?
                        var escapChar = MaskFormat.GetEscapeCharLength(format.Substring(index), result.KeyType, result.KeyLen);
                        if (escapChar.Result) {
                            result.KeyLen = escapChar.KeyLen;
                            result.KeyType = escapChar.KeyType;
                            result.KeyWord = format.substr(index, result.KeyLen);
                            return result;
                        }

                        //Is Defined char ?
                        var cSecond = format.charAt(index + 1);

                        if (cSecond === 'A') {
                            result.KeyLen = 2;
                            result.KeyType = 5 /* CharSubset */;
                            result.KeyWord = "[A-Z]";
                            return result;
                        } else if (cSecond === MaskFormat.DBCS_A) {
                            result.KeyLen = 2;
                            result.KeyType = 5 /* CharSubset */;
                            result.KeyWord = "[" + MaskFormat.DBCS_A + "-" + MaskFormat.DBCS_Z + "]";
                            return result;
                        } else if (cSecond === 'a') {
                            result.KeyLen = 2;
                            result.KeyType = 5 /* CharSubset */;
                            result.KeyWord = "[a-z]";
                            return result;
                        } else if (cSecond === MaskFormat.DBCS_a) {
                            result.KeyLen = 2;
                            result.KeyType = 5 /* CharSubset */;
                            result.KeyWord = "[" + MaskFormat.DBCS_a + "-" + MaskFormat.DBCS_z + "]";
                            return result;
                        } else if (cSecond === 'D') {
                            result.KeyLen = 2;
                            result.KeyType = 5 /* CharSubset */;
                            result.KeyWord = "[0-9]";
                            return result;
                        } else if (cSecond === MaskFormat.DBCS_D) {
                            result.KeyLen = 2;
                            result.KeyType = 5 /* CharSubset */;
                            result.KeyWord = "[" + MaskFormat.DBCS_0 + "-" + MaskFormat.DBCS_9 + "]";
                            return result;
                        } else if (cSecond === 'B') {
                            result.KeyLen = 2;
                            result.KeyType = 5 /* CharSubset */;
                            result.KeyWord = "[0-1]";
                            return result;
                        } else if (cSecond === MaskFormat.DBCS_B) {
                            result.KeyLen = 2;
                            result.KeyType = 5 /* CharSubset */;
                            result.KeyWord = "[" + MaskFormat.DBCS_0 + "-" + MaskFormat.DBCS_1 + "]";
                            return result;
                        } else if (cSecond === 'X') {
                            result.KeyLen = 2;
                            result.KeyType = 5 /* CharSubset */;
                            result.KeyWord = "[0-9A-Fa-f]";
                            return result;
                        } else if (cSecond === MaskFormat.DBCS_X) {
                            result.KeyLen = 2;
                            result.KeyType = 5 /* CharSubset */;
                            result.KeyWord = "[" + MaskFormat.DBCS_0 + "-" + MaskFormat.DBCS_9 + MaskFormat.DBCS_A + "-" + MaskFormat.DBCS_F + MaskFormat.DBCS_a + "-" + MaskFormat.DBCS_f + "]";
                            return result;
                        } else if (cSecond === 'W') {
                            result.KeyLen = 2;
                            result.KeyType = 5 /* CharSubset */;
                            result.KeyWord = "[a-zA-Z_0-9]";
                            return result;
                        } else if (cSecond === MaskFormat.DBCS_W) {
                            result.KeyLen = 2;
                            result.KeyType = 5 /* CharSubset */;
                            result.KeyWord = "[" + MaskFormat.DBCS_a + "-" + MaskFormat.DBCS_z + MaskFormat.DBCS_A + "-" + MaskFormat.DBCS_Z + MaskFormat.DBCS__ + MaskFormat.DBCS_0 + "-" + MaskFormat.DBCS_9 + "]";
                            return result;
                        } else if (cSecond === 'K' || cSecond === MaskFormat.DBCS_K || cSecond === MaskFormat.DBCS_J || cSecond === MaskFormat.DBCS_Z || cSecond === 'H' || cSecond === MaskFormat.DBCS_T || cSecond === MaskFormat.DBCS_M || cSecond === MaskFormat.DBCS_I || cSecond === MaskFormat.DBCS_G || cSecond === MaskFormat.DBCS_N || cSecond === 'N' || cSecond === MaskFormat.DBCS_E || cSecond === MaskFormat.DBCS_V) {
                            result.KeyLen = 2;
                            result.KeyType = 4 /* DefinedCharAddition */;
                            result.KeyWord = format.substr(index, 2);
                            return result;
                        } else if (MaskFormat.IsSpecialChar(cSecond)) {
                            result.KeyLen = 2;
                            result.KeyType = 8 /* PromptChar */;
                            result.KeyWord = format.substr(index + 1, 1); //exclude the '\' character.
                            return result;
                        } else {
                            result.KeyWord = ""; // "\\";
                            return result;
                        }

                    case '{': {
                        var idx = format.indexOf('}', index + 1);
                        if (idx === -1) {
                            result.KeyWord = ""; // "\\";
                            return result;
                        }

                        result.KeyType = 7 /* Quantifier */;
                        result.KeyLen = idx + 1 - index;
                        result.KeyWord = format.substr(index, result.KeyLen);
                        return result;
                    }
                    case '[': {
                        var idx = index;

                        //calculate '\\' number
                        var sNum = 0;
                        do {
                            idx = format.indexOf(']', idx + 1);
                            if (idx === -1)
                                return "";
                            for (var sCount = idx - 1; sCount > 0; sCount--) {
                                if (format.charAt(sCount) !== '\\') {
                                    break;
                                }
                                sNum++;
                            }
                        } while(format.charAt(idx - 1) === '\\' && (sNum % 2) !== 0);

                        result.KeyType = 5 /* CharSubset */;
                        result.KeyLen = idx + 1 - index;
                        result.KeyWord = format.substr(index, result.KeyLen);
                        return result;
                    }
                    case '(': {
                        var idx = index;
                        do {
                            idx = format.indexOf(')', idx + 1);
                            if (idx === -1)
                                return "";
                        } while(format.charAt(idx - 1) === '\\');

                        result.KeyType = 6 /* EnumGroup */;
                        result.KeyLen = idx + 1 - index;
                        result.KeyWord = format.substr(index, result.KeyLen);
                        return result;
                    }
                    case '*':
                        result.KeyLen = 1;
                        result.KeyType = 7 /* Quantifier */;
                        result.KeyWord = "{0,}";
                        return result;
                    case '+':
                        result.KeyLen = 1;
                        result.KeyType = 7 /* Quantifier */;
                        result.KeyWord = "{1,}";
                        return result;
                    case '?':
                        result.KeyLen = 1;
                        result.KeyType = 7 /* Quantifier */;
                        result.KeyWord = "{0,1}";
                        return result;
                    default: {
                        var i = index + 1;
                        for (; i < format.length; i++) {
                            if (MaskFormat.IsSpecialChar(format.charAt(i)))
                                break;
                        }

                        result.KeyType = 8 /* PromptChar */;
                        result.KeyLen = i - index;
                        result.KeyWord = format.substr(index, result.KeyLen);
                        return result;
                    }
                }
            };

            MaskFormat.IsSpecialChar = function (c) {
                return (c === '\\' || c === '{' || c === '}' || c === '[' || c === ']' || c === '(' || c === ')' || c === '.' || c === '*' || c === '+' || c === '?');
            };

            MaskFormat.GetEscapeCharLength = function (format, keyType, length) {
                var result = {};
                result.Result = false;
                result.KeyType = keyType;
                result.Length = length;
                if (format.charAt(0) !== '\\') {
                    return result;
                }

                var caret = 1;

                //int oldCaret = caret;
                var c = format.charAt(1);
                if (c === 'x') {
                    if (format.length < caret + 3)
                        return result;

                    result.Length = 4;
                    result.KeyType = 1 /* HexAscII */;
                    result.Result = true;
                    return result;
                } else if (c === 'u') {
                    if (format.length < caret + 5)
                        return result;

                    result.Length = 6;
                    result.KeyType = 2 /* HexUnicode */;
                    result.Result = true;
                    return result;
                } else if (MaskFormat.IsOctalChar(c)) {
                    if (format.length < caret + 3)
                        return result;

                    result.Length = 4;
                    result.KeyType = 0 /* OctalAscII */;
                    result.Result = true;
                    return result;
                }

                return result;
            };

            MaskFormat.IsOctalChar = function (c) {
                return (c >= '0' && c <= '7');
            };

            MaskFormat.AnalyseQuantifier = function (quantifierStr) {
                var result = {};
                result.Min = -1;
                result.Max = -1;
                result.Result = false;
                var index = quantifierStr.indexOf(',', 1);

                if (index === -1) {
                    try  {
                        result.Min = parseInt(quantifierStr.substr(1, quantifierStr.length - 2));
                        result.Max = result.Min;
                        result.Result = result.Max > 0;
                        return result;
                    } catch (e) {
                        result.Result = false;
                        return result;
                    }
                }
                try  {
                    result.Min = parseInt(quantifierStr.substr(1, index - 1));
                    if (index === quantifierStr.length - 2) {
                        result.Max = Math.pow(2, 31);
                    } else {
                        result.Max = parseInt(quantifierStr.substr(index + 1, quantifierStr.length - index - 2));
                    }
                    if (result.Min < 0 || result.Min > result.Max || result.Max === 0) {
                        result.Result = false;
                        return result;
                    } else {
                        result.Result = true;
                        return result;
                    }
                } catch (e) {
                    result.Result = false;
                    return result;
                }
            };

            MaskFormat.AnalyseCharSubset = function (subset, uf) {
                var result = {};
                result.uf = uf;
                result.Result = false;
                var filters = [];
                var caret = 1;

                //char lastChar = subset[1];
                var isInclude = true;

                //			string exclude = string.Empty;
                var include = "";

                if (subset === "[]") {
                    //uf = new UnionFilter(new FilterField.CharacterFilter[]{new FullWidthFilter(),new HalfWidthFilter()});
                    //return true;
                    filters.push(new FullWidthFilter(MaskFormat.Owner, true));
                    filters.push(new HalfWidthFilter(MaskFormat.Owner, true));
                    filters.push(new SurrogateFilter(MaskFormat.Owner, true));
                    if (result.uf && result.uf.filterArray.length > 0) {
                        for (var i = 0; i < uf.filterArray.length; i++) {
                            filters.push(uf.filterArray[i]);
                        }
                    }

                    result.uf = new UnionFilter(MaskFormat.Owner, true);
                    result.uf.AddRange(filters);
                    result.Result = true;
                    return result;
                }
                if (subset === "[^]") {
                    //uf = new UnionFilter(new FilterField.CharacterFilter[]{new FullWidthFilter(),new HalfWidthFilter()});
                    //uf.Include = false;
                    //return true;
                    filters.push(new FullWidthFilter(MaskFormat.Owner, false));
                    filters.push(new HalfWidthFilter(MaskFormat.Owner, false));
                    filters.push(new SurrogateFilter(MaskFormat.Owner, false));
                    if (result.uf && result.uf.filterArray.length > 0) {
                        for (var i = 0; i < uf.filterArray.length; i++) {
                            filters.push(uf.filterArray[i]);
                        }
                    }

                    result.uf = new UnionFilter(MaskFormat.Owner, true);
                    result.uf.AddRange(filters);
                    result.uf.filterArray[0]._include = false;
                    result.uf.filterArray[1]._include = false;
                    result.uf.filterArray[2]._include = false;
                    result.Result = true;
                    return result;
                }
                if (subset.charAt(caret) === '^') {
                    isInclude = false;
                    caret++;
                }
                while (caret < subset.length - 1) {
                    var cc = subset.charAt(caret);
                    var keyType = 1 /* HexAscII */;
                    var length = 0;

                    switch (cc) {
                        case '-':
                            result.Result = false;
                            return result;
                        case '^':
                            if (isInclude === false) {
                                throw "invalid fromat";
                            }

                            //return false;
                            //characters
                            if (include.length > 0) {
                                var lf = new LimitedFilter(include, "");
                                lf._include = isInclude;
                                filters.push(lf);
                            }

                            //add filter before "^"
                            if (filters.length > 0) {
                                result.uf = new UnionFilter(MaskFormat.Owner, true);
                                result.uf.AddRange(filters);

                                for (var i = 0; i < result.uf.filterArray.length; i++) {
                                    if (!result.uf.filterArray[i]._include) {
                                        result.Result = false;
                                        return result;
                                    }
                                }
                                var charSubSetResult = MaskFormat.AnalyseCharSubset("[" + subset.substr(caret, subset.length - caret), result.uf);
                                result.uf = charSubSetResult.uf;
                                result.Result = charSubSetResult.Result;
                                return result;
                            } else {
                                result.Result = false;
                                return result;
                            }
                        case '\\':
                             {
                                // Change the "\u****" to a char.
                                var escapeCharResult = MaskFormat.GetEscapeCharLength(subset.substr(caret), keyType, length);
                                keyType = escapeCharResult.KeyType;
                                length = escapeCharResult.Length;
                                if (escapeCharResult.Result) {
                                    var baseValue = 16;
                                    var s = null;
                                    if (keyType === 0 /* OctalAscII */) {
                                        baseValue = 8;
                                        s = subset.substr(caret + 1, length - 1);
                                    } else {
                                        s = subset.substr(caret + 2, length - 2);
                                    }
                                    subset = subset.substring(0, caret) + subset.substr(caret + length);
                                    var newStr = String.fromCharCode(parseInt(s, baseValue));
                                    subset = subset.substring(0, caret) + newStr + subset.substr(caret);

                                    continue;
                                }

                                var c = subset.charAt(caret + 1);
                                if (c === 'A') {
                                    filters.push(new RangeFilter('A', 'Z', MaskFormat.Owner, true));
                                    caret++;
                                } else if (c === MaskFormat.DBCS_A) {
                                    filters.push(new RangeFilter(MaskFormat.DBCS_A, MaskFormat.DBCS_Z, MaskFormat.Owner, true));
                                    caret++;
                                } else if (c === 'a') {
                                    filters.push(new RangeFilter('a', 'z', MaskFormat.Owner, true));
                                    caret++;
                                } else if (c === MaskFormat.DBCS_a) {
                                    filters.push(new RangeFilter(MaskFormat.DBCS_a, MaskFormat.DBCS_z, MaskFormat.Owner, true));
                                    caret++;
                                } else if (c === 'D') {
                                    filters.push(new RangeFilter('0', '9', MaskFormat.Owner, true));
                                    caret++;
                                } else if (c === MaskFormat.DBCS_D) {
                                    filters.push(new RangeFilter(MaskFormat.DBCS_0, MaskFormat.DBCS_9, MaskFormat.Owner, true));
                                    caret++;
                                } else if (c === 'B') {
                                    filters.push(new RangeFilter('0', '1', MaskFormat.Owner, true));
                                    caret++;
                                } else if (c === MaskFormat.DBCS_B) {
                                    filters.push(new RangeFilter(MaskFormat.DBCS_0, MaskFormat.DBCS_1, MaskFormat.Owner, true));
                                    caret++;
                                } else if (c === 'X') {
                                    filters.push(new RangeFilter('0', '9', MaskFormat.Owner, true));
                                    filters.push(new RangeFilter('A', 'F', MaskFormat.Owner, true));
                                    filters.push(new RangeFilter('a', 'f', MaskFormat.Owner, true));
                                    caret++;
                                } else if (c === MaskFormat.DBCS_X) {
                                    filters.push(new RangeFilter(MaskFormat.DBCS_0, MaskFormat.DBCS_9, MaskFormat.Owner, true));
                                    filters.push(new RangeFilter(MaskFormat.DBCS_A, MaskFormat.DBCS_F, MaskFormat.Owner, true));
                                    filters.push(new RangeFilter(MaskFormat.DBCS_a, MaskFormat.DBCS_f, MaskFormat.Owner, true));
                                    caret++;
                                } else if (c === 'W') {
                                    filters.push(new RangeFilter('0', '9', MaskFormat.Owner, true));
                                    filters.push(new RangeFilter('A', 'Z', MaskFormat.Owner, true));
                                    filters.push(new RangeFilter('a', 'z'));

                                    //							if (include.IndexOf('_') != -1)
                                    //								return false;
                                    include += '_';
                                    caret++;
                                } else if (c === MaskFormat.DBCS_W) {
                                    filters.push(new RangeFilter(MaskFormat.DBCS_0, MaskFormat.DBCS_9, MaskFormat.Owner, true));
                                    filters.push(new RangeFilter(MaskFormat.DBCS_A, MaskFormat.DBCS_Z, MaskFormat.Owner, true));
                                    filters.push(new RangeFilter(MaskFormat.DBCS_a, MaskFormat.DBCS_z, MaskFormat.Owner, true));

                                    //							if (include.IndexOf(DBCS__) != -1)
                                    //								return false;
                                    include += MaskFormat.DBCS__;
                                    caret++;
                                } else if (c === 'K') {
                                    filters.push(new HalfWidthKatakanaFilter(MaskFormat.Owner, true));
                                    caret++;
                                } else if (c === 'H') {
                                    filters.push(new HalfWidthFilter(MaskFormat.Owner, isInclude));
                                    caret++;
                                } else if (c === MaskFormat.DBCS_K) {
                                    filters.push(new FullWidthKatakanaFilter(MaskFormat.Owner, true));
                                    caret++;
                                } else if (c === MaskFormat.DBCS_J) {
                                    filters.push(new HiraganaFilter(MaskFormat.Owner, true));
                                    caret++;
                                } else if (c === MaskFormat.DBCS_M) {
                                    filters.push(new ShiftJISFilter(MaskFormat.Owner, true));
                                    caret++;
                                } else if (c === MaskFormat.DBCS_I) {
                                    filters.push(new JISX0208Filter(MaskFormat.Owner, true));
                                    caret++;
                                } else if (c === 'N') {
                                    filters.push(new SBCSKatakanaFilter(MaskFormat.Owner, true));
                                    caret++;
                                } else if (c === MaskFormat.DBCS_N) {
                                    filters.push(new DBCSKatakanaFilter(MaskFormat.Owner, true));
                                    caret++;
                                } else if (c === MaskFormat.DBCS_G) {
                                    filters.push(new DBCSHiraganaFilter(MaskFormat.Owner, true));
                                    caret++;
                                } else if (c === MaskFormat.DBCS_Z) {
                                    filters.push(new FullWidthFilter(MaskFormat.Owner, true));
                                    caret++;
                                } else if (c === MaskFormat.DBCS_T) {
                                    filters.push(new SurrogateFilter(MaskFormat.Owner, true));
                                    caret++;
                                } else if (c === '\\' || c === ']' || c === '[' || c === '-' || c === '^') {
                                    //							if (isInclude)
                                    //								include += c;
                                    //							else
                                    //								exclude += c;
                                    //bug#5280
                                    if (include.indexOf(c) !== -1) {
                                        //return false;
                                        caret++;
                                        continue;
                                    }

                                    include += c;
                                    caret++;
                                } else
                                    return false;
                            }
                            break;
                        default: {
                            if (subset.length > caret + 2) {
                                if (subset.charAt(caret + 1) === '-') {
                                    // Change the "\u****" or "\***" or "\x**" to a char.
                                    var escapteCharResult = MaskFormat.GetEscapeCharLength(subset.substr(caret + 2), keyType, length);
                                    keyType = escapteCharResult.KeyType;
                                    length = escapteCharResult.Length;
                                    if (escapteCharResult.Result) {
                                        var s = null;
                                        var baseValue = 16;
                                        if (keyType === 0 /* OctalAscII */) {
                                            baseValue = 8;
                                            s = subset.substr(caret + 2 + 1, length - 1);
                                        } else
                                            s = subset.substr(caret + 2 + 2, length - 2);

                                        var newCaret = caret + 2;

                                        subset = subset.substring(0, newCaret) + subset.substr(newCaret + length);
                                        var newStr = String.fromCharCode(parseInt(s, baseValue));
                                        subset = subset.substring(0, newCaret) + newStr + subset.substr(newCaret);
                                    }

                                    // Get range start and range end.
                                    var rangeStart;
                                    var rangeEnd;
                                    if (subset.charAt(caret) > subset.charAt(caret + 2)) {
                                        rangeStart = subset.charAt(caret + 2);
                                        rangeEnd = subset.charAt(caret);
                                    } else {
                                        rangeStart = subset.charAt(caret);
                                        rangeEnd = subset.charAt(caret + 2);
                                    }

                                    // Create the range filter.
                                    var rf = new RangeFilter(rangeStart, rangeEnd, MaskFormat.Owner, true);
                                    filters.push(rf);

                                    caret += 2;
                                    break;
                                }
                            }

                            // Record the excluding or including string.
                            //						if (isInclude)
                            //							include += cc;
                            //						else
                            //							exclude += cc;
                            if (include.indexOf(cc) !== -1) {
                                //return false;
                                //bug#5280, Kevin Huang, Feb-19-2006
                                caret++;
                                continue;
                            }

                            include += cc;

                            break;
                        }
                    }

                    caret++;
                }

                if (include.length > 0)
                    filters.push(new LimitedFilter(include, "", MaskFormat.Owner, true));
                var icount = filters.length;

                if (result.uf && result.uf.filterArray.length > 0) {
                    for (var i = 0; i < result.uf.filterArray.length; i++) {
                        filters.push(uf.filterArray[i]);
                    }
                }

                result.uf = new UnionFilter(MaskFormat.Owner, true);
                result.uf.AddRange(filters);

                for (var i = 0; i < icount; i++) {
                    result.uf.filterArray[i]._include = isInclude;
                }

                result.Result = true;
                return result;
            };

            MaskFormat.AnalyseEnumGroup = function (groupStr, members) {
                groupStr = groupStr.Substring(1, 1 + groupStr.length - 2);

                var caret = 0, last = 0;
                while (caret < groupStr.length) {
                    var index = input.Utility.IndexOfAny(groupStr, ['|', ')', '\\', '('], caret);
                    if (index === -1) {
                        var member = groupStr.Substring(last);
                        if (member.length === 0)
                            return false;
                        members.push(member);
                        caret = groupStr.length;
                        continue;
                    }
                    if (groupStr.charAt(index) === '\\') {
                        var c = groupStr.charAt(index + 1);
                        if (c === '\\' || c === ')' || c === '|' || c === '(') {
                            groupStr = groupStr.Substring(0, index) + groupStr.Substring(index + 1, groupStr.length);
                            caret = index + 1;

                            //add judgement, KevinHuang,2006-4
                            if (caret === groupStr.length) {
                                var member = groupStr.Substring(last);
                                if (member.length === 0)
                                    return false;
                                members.push(member);
                            }
                            continue;
                        } else {
                            return false;
                        }
                    }
                    if (groupStr.charAt(index) === '|') {
                        var member = groupStr.Substring(last, index);
                        if (member.length === 0)
                            return false;
                        members.push(member);
                        caret = index + 1;
                        last = caret;
                        continue;
                    } else {
                        return false;
                    }
                }

                return true;
            };
            MaskFormat.DBCS_A = input.CharProcess.CharEx.ToFullWidth('A').text;
            MaskFormat.DBCS_a = input.CharProcess.CharEx.ToFullWidth('a').text;
            MaskFormat.DBCS_B = input.CharProcess.CharEx.ToFullWidth('B').text;
            MaskFormat.DBCS_D = input.CharProcess.CharEx.ToFullWidth('D').text;
            MaskFormat.DBCS_J = input.CharProcess.CharEx.ToFullWidth('J').text;
            MaskFormat.DBCS_K = input.CharProcess.CharEx.ToFullWidth('K').text;
            MaskFormat.DBCS_W = input.CharProcess.CharEx.ToFullWidth('W').text;
            MaskFormat.DBCS_X = input.CharProcess.CharEx.ToFullWidth('X').text;
            MaskFormat.DBCS_Z = input.CharProcess.CharEx.ToFullWidth('Z').text;
            MaskFormat.DBCS_T = input.CharProcess.CharEx.ToFullWidth('T').text;
            MaskFormat.DBCS_M = input.CharProcess.CharEx.ToFullWidth('M').text;
            MaskFormat.DBCS_I = input.CharProcess.CharEx.ToFullWidth('I').text;
            MaskFormat.DBCS_N = input.CharProcess.CharEx.ToFullWidth('N').text;
            MaskFormat.DBCS_G = input.CharProcess.CharEx.ToFullWidth('G').text;
            MaskFormat.DBCS_E = input.CharProcess.CharEx.ToFullWidth("E").text;
            MaskFormat.DBCS_V = input.CharProcess.CharEx.ToFullWidth("V").text;
            MaskFormat.DBCS_z = input.CharProcess.CharEx.ToFullWidth('z').text;
            MaskFormat.DBCS_0 = input.CharProcess.CharEx.ToFullWidth('0').text;
            MaskFormat.DBCS_1 = input.CharProcess.CharEx.ToFullWidth('1').text;
            MaskFormat.DBCS_9 = input.CharProcess.CharEx.ToFullWidth('9').text;
            MaskFormat.DBCS_F = input.CharProcess.CharEx.ToFullWidth('F').text;
            MaskFormat.DBCS_f = input.CharProcess.CharEx.ToFullWidth('f').text;
            MaskFormat.DBCS__ = input.CharProcess.CharEx.ToFullWidth('_').text;
            return MaskFormat;
        })();

        /** @ignore */
        var MaskFieldCollection = (function (_super) {
            __extends(MaskFieldCollection, _super);
            function MaskFieldCollection(owner, count, formatNull) {
                _super.call(this, count);
                this._focusNull = "";
                this.oldStart = -1;
                this.oldLength = 0;
                this.newStart = -1;
                this.newLength = 0;
                this._owner = owner;
                this.formatIsNull = formatNull;
            }
            MaskFieldCollection.prototype.GetShowLiterals = function () {
                return this._owner.GetShowLiterals();
            };

            MaskFieldCollection.prototype.GetFieldByIndex = function (index) {
                return this.fieldArray[index];
            };

            MaskFieldCollection.prototype.GetLength = function () {
                var isNull = this.ValueIsNull();

                if (isNull && this._focusNull !== "" && !this.formatIsNull) {
                    return this._focusNull.GetLength();
                } else if (isNull === true && this._focusNull !== "") {
                    return 0;
                }

                var lastField = this.GetLastVisibleFieldIndex(this.GetShowLiterals());

                var length = 0;
                for (var i = 0; i <= lastField; i++) {
                    var field = this.GetFieldByIndex(i);
                    length += field.GetLength();
                }

                return length;
            };

            MaskFieldCollection.prototype.GetInputFieldIndexByPos = function (pos) {
                var currentField = null;

                var startOffset = 0;
                var startFieldIndex;
                var posObj = this.GetFieldIndex(pos, startOffset);
                startFieldIndex = posObj.index;
                startOffset = posObj.offset;

                if (startFieldIndex !== 0 && startOffset === 0 && this.fieldArray[startFieldIndex - 1].fieldLabel !== "PromptField") {
                    startFieldIndex--;
                    startOffset = this.fieldArray[startFieldIndex].text.GetLength();
                }

                var field = this.fieldArray[startFieldIndex];
                if (startOffset === field.text.GetLength()) {
                    var k;
                    if (startOffset < field._maxLength) {
                        currentField = startFieldIndex;
                        if (currentField !== this.fieldCount - 1) {
                            for (k = startFieldIndex + 1; k < this.fieldCount; k++) {
                                if (this.fieldArray[k].fieldLabel !== "PromptField") {
                                    break;
                                }
                            }
                        }
                    } else {
                        for (k = startFieldIndex + 1; k < this.fieldCount; k++) {
                            if (this.fieldArray[k].fieldLabel !== "PromptField") {
                                currentField = k;
                                break;
                            }
                        }
                    }
                } else {
                    currentField = startFieldIndex;
                }

                var retObj = {};
                var cField = {};
                if (currentField) {
                    var findOut = false;
                    while (findOut === false) {
                        field = this.fieldArray[currentField];
                        if (field.fieldLabel === "FilterField") {
                            cField.fieldMark = field._filter.filterLabel;
                            findOut = true;
                        } else if (field.fieldLabel === "EnumField") {
                            cField.fieldMark = "Enum";
                            findOut = true;
                        } else {
                            if (currentField !== this.fieldCount - 1)
                                currentField++;
                            else {
                                cField = null;
                                break;
                            }
                        }
                        cField.fieldIndex = currentField;
                    }
                } else {
                    cField = null;
                }

                if (cField != null) {
                    retObj.currentField = cField;
                    return retObj;
                }
                return null;
            };

            MaskFieldCollection.prototype.GetCurrentField = function (position) {
                var fieldPos = {};
                var length = 0;
                var fCount = 0;
                for (var i = 0; i < this.fieldCount; i++) {
                    var field = this.fieldArray[i];
                    if (field.fieldLabel === "PromptField")
                        fCount++;
                    var fieldLength = field.GetLength();

                    length += fieldLength;

                    if (position <= length) {
                        if (field.fieldLabel === "PromptField") {
                            if (position === length - fieldLength) {
                                fieldPos.index = i - fCount;
                            } else if (position === length) {
                                fieldPos.index = i - fCount + 1;
                            } else {
                                fieldPos.index = -1;
                            }
                        } else {
                            fieldPos.index = i - fCount;
                        }
                        return fieldPos;
                    }
                }
            };

            MaskFieldCollection.prototype.GetText = function () {
                var text = "";
                for (var i = 0; i < this.fieldCount; i++) {
                    var field = this.fieldArray[i];
                    text += field.text;
                }
                return text;
            };

            MaskFieldCollection.prototype.GetTextSimpleMode = function (includeLiterals) {
                var text = "";
                for (var i = 0; i < this.fieldCount; i++) {
                    var field = this.fieldArray[i];
                    if (field.fieldLabel === "PromptField" && !includeLiterals)
                        continue;
                    text += field.text;
                }
                return text;
            };

            MaskFieldCollection.prototype.GetExistLength = function () {
                var lastInputField = this.fieldCount;
                var i;
                var field;
                for (i = this.fieldCount - 1; i >= 0; i--) {
                    field = this.fieldArray[i];
                    if (field.fieldLabel === "PromptField")
                        continue;
                    else {
                        lastInputField = i;
                        break;
                    }
                }

                var length = 0;
                for (i = 0; i <= lastInputField; i++) {
                    field = this.fieldArray[i];
                    if (i === lastInputField) {
                        if (length >= 21474000)
                            length = field._maxLength;
                        else
                            length += field._maxLength;
                    } else {
                        length += field.text.GetLength();
                    }
                }
                return length;
            };

            MaskFieldCollection.prototype.GetNonLiteralsText = function (start, length) {
                var retText = "";
                var startOffset = 0;
                var startFieldIndex;
                var posObj = this.GetFieldIndex(start, startOffset);
                startFieldIndex = posObj.index;
                startOffset = posObj.offset;

                var endOffset = 0;
                var endFieldIndex;
                posObj = this.GetFieldIndex(start + length, endOffset);
                endFieldIndex = posObj.index;
                endOffset = posObj.offset;

                if (endFieldIndex !== 0 && endOffset === 0) {
                    endFieldIndex--;
                    endOffset = this.fieldArray[endFieldIndex].text.GetLength();
                }

                for (var i = startFieldIndex; i <= endFieldIndex; i++) {
                    var field = this.fieldArray[i];
                    if (field.fieldLabel !== "PromptField") {
                        if (startFieldIndex === endFieldIndex) {
                            retText = field.text.Substring(startOffset, endOffset);
                            if (retText.GetLength() > field._trueLength)
                                retText = retText.Substring(0, field._trueLength);
                        } else if (i === startFieldIndex) {
                            retText += field.text.Substring(startOffset, field.text.GetLength());
                        } else if (i === endFieldIndex) {
                            retText += field.text.Substring(0, endOffset);
                        } else {
                            retText += field.text.Substring(0, field.text.GetLength());
                        }
                    }
                }

                return retText;
            };

            MaskFieldCollection.prototype.GetNonPromptText = function (start, length) {
                var retText = "";
                var startOffset = 0;
                var startFieldIndex;
                var posObj = this.GetFieldIndex(start, startOffset);
                startFieldIndex = posObj.index;
                startOffset = posObj.offset;

                var endOffset = 0;
                var endFieldIndex;
                posObj = this.GetFieldIndex(start + length, endOffset);
                endFieldIndex = posObj.index;
                endOffset = posObj.offset;

                if (endFieldIndex !== 0 && endOffset === 0) {
                    endFieldIndex--;
                    endOffset = this.fieldArray[endFieldIndex].text.GetLength();
                }

                for (var i = startFieldIndex; i <= endFieldIndex; i++) {
                    var field = this.fieldArray[i];
                    if (field.fieldLabel !== "PromptField") {
                        if (startFieldIndex === endFieldIndex) {
                            retText = field.text.Substring(startOffset, endOffset);
                        } else if (i === startFieldIndex) {
                            retText += field.text.Substring(startOffset, field.text.GetLength());
                        } else if (i === endFieldIndex) {
                            retText += field.text.Substring(0, endOffset);
                        } else {
                            retText += field.text;
                        }
                    }
                }

                return retText;
            };

            MaskFieldCollection.prototype.ValueIsNull = function () {
                for (var i = 0; i < this.fieldCount; i++) {
                    var field = this.fieldArray[i];
                    if (field.fieldLabel === "PromptField")
                        continue;
                    else {
                        if (field.GetFieldStatus() !== 0) {
                            return false;
                        }
                    }
                }
                return true;
            };

            MaskFieldCollection.prototype.ValueIsFull = function (mode) {
                mode = (!mode) ? 0 : mode;
                var i;
                var field;
                if (mode != null && mode === 1) {
                    for (i = 0; i < this.fieldCount; i++) {
                        field = this.fieldArray[i]; //modified by sj 2008.8.13 for bug 115.
                        if (this.fieldCount === 1 && field._minLength === 0) {
                            return true;
                        }

                        if (field.fieldLabel === "PromptField")
                            continue;
                        else {
                            if (!field.GetFieldIsFull()) {
                                return false;
                            }
                        }
                    }
                } else {
                    for (i = 0; i < this.fieldCount; i++) {
                        field = this.fieldArray[i];
                        if (field.fieldLabel === "PromptField")
                            continue;
                        else {
                            if (field.GetFieldStatus() !== 2) {
                                return false;
                            }
                        }
                    }
                }
                return true;
            };

            MaskFieldCollection.prototype.GetShowText = function (showliterals, type, notNull) {
                if (!notNull) {
                    var isNull = this.ValueIsNull();

                    if (isNull === true && this._focusNull !== "" && type == "") {
                        return this._focusNull;
                    } else if (isNull === true && this._focusNull !== "" && type == null) {
                        return "";
                    }

                    if (isNull === true && type === "LoseFocus") {
                        if (this._owner._getDisplayNullExpression() !== null)
                            return this._owner._getDisplayNullExpression();
                        else
                            return this.GetText();
                    }
                }

                var lastField = this.GetLastVisibleFieldIndex(showliterals);

                if (lastField < 0)
                    return "";

                var text = "";
                for (var i = 0; i < lastField; i++)
                    text += this.fieldArray[i].text;

                if (lastField < this.fieldCount) {
                    var field = this.fieldArray[lastField];
                    if (field.fieldLabel === "PromptField" || showliterals === 1 /* Always */) {
                        text += this.fieldArray[lastField].text;
                    } else {
                        text += field.text.Substring(0, field._trueLength);
                    }
                }
                return text;
            };

            MaskFieldCollection.prototype.GetLastVisibleFieldIndex = function (showliterals) {
                var lastField = this.fieldCount - 1;

                if (showliterals !== 1 /* Always */) {
                    var end = this.fieldCount - 1;
                    var full = true;
                    for (lastField = end; lastField >= 0; lastField--) {
                        var field = this.fieldArray[lastField];
                        if (field.fieldLabel === "PromptField")
                            continue;
                        else if (field._trueLength === 0) {
                            full = false;
                            continue;
                        } else if (field._trueLength > 0 && field._trueLength < field._minLength)
                            break;
                        else if (showliterals === 2 /* PostDisplay */) {
                            if (full)
                                lastField = end;
                            break;
                        } else {
                            while (lastField < end && this.fieldArray[lastField + 1].fieldLabel === "PromptField")
                                lastField++;
                            break;
                        }
                    }
                }

                return lastField;
            };

            MaskFieldCollection.prototype.GetValue = function () {
                var endFieldIndex = this.fieldCount - 1;
                var field;
                for (; endFieldIndex >= 0; endFieldIndex--) {
                    field = this.fieldArray[endFieldIndex]; //modified by sj 2008.8.14 for bug 404
                    if (!(field.fieldLabel === "PromptField") && (field._trueLength !== 0)) {
                        break;
                    }
                }

                if (endFieldIndex < 0)
                    return "";

                var text = "";
                for (var j = 0; j <= endFieldIndex; j++) {
                    field = this.fieldArray[j];
                    if (field.fieldLabel === "PromptField")
                        continue;
                    var length = field._trueLength;
                    var fieldText = field.text;
                    var retValue = fieldText;
                    if (field.fieldLabel === 'FilterField') {
                        retValue = retValue.Substring(0, length);
                        for (var k = 0; k < length; k++) {
                            if (field._bitState[k] === false) {
                                retValue = retValue.Substring(0, k) + " " + retValue.Substring(k + 1, retValue.GetLength());
                            }
                        }
                        var fieldTextLength = fieldText.GetLength();
                        var retValueLength = retValue.GetLength();
                        if (length === 0 && fieldTextLength !== 0) {
                            if (j !== endFieldIndex) {
                                var temp = "";
                                for (var len = 0; len < fieldTextLength; len++)
                                    temp += " ";
                                retValue = temp;
                            }
                        } else if (fieldTextLength > retValueLength) {
                            if (j !== endFieldIndex) {
                                var temp = "";
                                for (var len = 0; len < fieldTextLength - retValueLength; len++) {
                                    temp += " ";
                                }
                                retValue += temp;
                            }
                        }
                    } else {
                        if (field._activeItem === -1)
                            retValue = " ";
                    }
                    text += retValue;
                }

                return text;
            };

            MaskFieldCollection.prototype.GetOldValue = function () {
                var text = "";
                var field;
                for (var j = 0; j < this.fieldCount; j++) {
                    field = this.fieldArray[j];
                    if (field.fieldLabel === "PromptField")
                        continue;
                    var tempText;
                    if (field.fieldLabel === 'FilterField') {
                        tempText = field.undoText;
                        if (field._undoBitState && field._undoBitState.length > 0) {
                            var isCut = true;
                            for (var i = field._undoBitState.length - 1; i >= 0; i--) {
                                if (field._undoBitState[i] === false) {
                                    if (isCut) {
                                        tempText = tempText.Substring(0, tempText.GetLength() - 1);
                                    } else {
                                        tempText = tempText.Substring(0, i) + " " + tempText.Substring(i + 1, tempText.GetLength());
                                    }
                                } else {
                                    isCut = false;
                                }
                            }
                        } else {
                            tempText = "";
                        }
                    } else {
                        if (field._undoItem !== -1) {
                            tempText = field.undoText;
                        } else {
                            tempText = "";
                        }
                    }
                    text += tempText;
                }
                return text;
            };

            MaskFieldCollection.prototype.SetValue = function (text, includeprompt) {
                if (!text) {
                    this.ClearContent();
                    return true;
                }

                var include = false;
                if (includeprompt != null)
                    include = includeprompt;

                if (this.SetFieldCollectionValue(text, include)) {
                    return true;
                } else {
                    this.RollBack();
                    return false;
                }
            };

            MaskFieldCollection.prototype.SetFieldCollectionValue = function (text, includeprompt) {
                this.ClearContent();
                var include = false;
                if (includeprompt != null)
                    include = includeprompt;
                if (text.GetLength() !== 0) {
                    this.Insert(0, text, include, false);
                }
                return true;
            };

            MaskFieldCollection.prototype.ClearContent = function () {
                this.oldStart = -1;
                this.oldLength = 0;
                this.newStart = -1;
                this.newLength = 0;
                if (this.formatIsNull) {
                    this.SaveUndoState();
                }
                if (this.fieldCount > 0) {
                    for (var i = 0; i < this.fieldCount; i++) {
                        var field = this.fieldArray[i];
                        field.oldText = field.text;
                        field.Delete(0, field.text.GetLength());
                    }
                }
            };

            MaskFieldCollection.prototype.RollBack = function () {
                if (this.fieldCount > 0) {
                    for (var i = 0; i < this.fieldCount; i++) {
                        var field = this.fieldArray[i];
                        field.RollBack();
                    }
                }
            };

            MaskFieldCollection.prototype.SaveOldState = function () {
                if (this.fieldCount > 0) {
                    for (var i = 0; i < this.fieldCount; i++) {
                        var field = this.fieldArray[i];
                        if (field.fieldLabel !== "PromptField")
                            field.SaveOldState();
                    }
                }
            };

            MaskFieldCollection.prototype.SaveUndoState = function () {
                if (this.formatIsNull) {
                    var field = this.fieldArray[0];
                    var index = -1;
                    if (this.oldStart === -1) {
                        field.SaveUndoState();
                        index = this.newStart;
                    } else {
                        var newtext = field.text.substr(this.newStart, this.newLength);
                        index = field.undoText.IndexOf(newtext, this.oldStart);
                        if (index !== this.oldStart + this.oldLength) {
                            index = this.newStart;
                            if (index + this.newLength !== this.oldStart) {
                                field.SaveUndoState();
                            }
                        }
                    }
                    if (this.oldStart > 0) {
                        this.oldStart = Math.min(this.oldStart, index);
                    } else {
                        this.oldStart = index;
                    }
                    this.oldLength += this.newLength;
                } else {
                    if (this.fieldCount > 0) {
                        for (var i = 0; i < this.fieldCount; i++) {
                            var field = this.fieldArray[i];
                            if (field.fieldLabel !== "PromptField") {
                                field.SaveUndoState();
                            }
                        }
                    }
                }
            };

            MaskFieldCollection.prototype.Undo = function () {
                this.oldStart = -1;
                this.oldLength = 0;
                this.newStart = -1;
                this.newLength = 0;
                if (this.fieldCount > 0) {
                    for (var i = 0; i < this.fieldCount; i++) {
                        var field = this.fieldArray[i];
                        if (field.fieldLabel !== "PromptField")
                            field.Undo();
                    }
                }
            };

            MaskFieldCollection.prototype.PerformSpin = function (position, increment, wrap) {
                var offset;
                var posObj = this.GetFieldIndex(position, offset);
                var fieldIndex = posObj.index;
                offset = posObj.offset;

                this.SaveOldState();
                if (offset > 0 || this.fieldArray[fieldIndex].fieldLabel === "EnumField") {
                    offset = this.fieldArray[fieldIndex].PerformSpin(offset, increment, wrap);
                    var prelength = 0;
                    for (var j = 0; j < fieldIndex; j++) {
                        prelength += this.fieldArray[j].text.GetLength();
                    }
                    position = prelength + offset;
                } else {
                    var i = fieldIndex;
                    var field;
                    for (; i < this.fieldCount; i++) {
                        field = this.fieldArray[i];
                        if (field._minLength === 0) {
                            if (field.text.GetLength() === 0)
                                continue;
                            else
                                break;
                        } else if (field.fieldLabel === "EnumField") {
                            offset = field.PerformSpin(offset, increment, wrap);
                            var prelength = 0;
                            for (var j = 0; j < fieldIndex; j++) {
                                prelength += this.fieldArray[j].text.GetLength();
                            }
                            position = prelength + offset;

                            return position;
                        } else {
                            break;
                        }
                    }

                    if (fieldIndex > 0) {
                        field = this.fieldArray[fieldIndex - 1];
                        offset = field.text.GetLength();
                        if (offset < field._minLength)
                            offset = field._minLength;
                        offset = field.PerformSpin(offset, increment, wrap);
                        if (field.fieldLabel === "EnumField") {
                            var prelength = 0;
                            for (var j = 0; j < fieldIndex - 1; j++) {
                                prelength += this.fieldArray[j].text.GetLength();
                            }
                            position = prelength + offset;
                        }
                    }
                }
                return position;
            };

            MaskFieldCollection.prototype.Delete = function (start, length) {
                if (this.fieldCount === 0)
                    return start;

                var offset = 0;

                this.SaveOldState();

                var retObj = this.GetFieldIndex(start, offset);
                var startIndex = retObj.index;
                offset = retObj.offset;
                if (this.fieldArray[startIndex].fieldLabel === "PromptField" && length > this.fieldArray[startIndex].text.GetLength() - offset) {
                    start += this.fieldArray[startIndex].text.GetLength() - offset;
                    length -= this.fieldArray[startIndex].text.GetLength() - offset;
                    startIndex++;
                    offset = 0;
                }

                this.newStart = start;
                this.newLength = length;
                if (this.formatIsNull) {
                    this.SaveUndoState();
                }
                var endOffset = 0;
                retObj = this.GetFieldIndex(start + length, endOffset);
                var endIndex = retObj.index;
                endOffset = retObj.offset;
                while (endIndex !== 0 && endOffset === 0) {
                    var field = this.fieldArray[endIndex - 1];
                    if (!(field.fieldLabel === "PromptField")) {
                        endIndex--;
                        endOffset = (this.fieldArray[endIndex].text.GetLength() > this.fieldArray[endIndex]._minLength ? this.fieldArray[endIndex].text.GetLength() : this.fieldArray[endIndex]._minLength);
                    } else
                        break;
                }

                for (var i = startIndex; i <= endIndex; i++) {
                    var field = this.fieldArray[i];

                    var startOffset = offset;
                    if (startIndex === endIndex) {
                        if (endOffset > offset) {
                            offset = field.Delete(offset, endOffset - offset);
                        } else
                            offset -= (offset - endOffset);
                    } else if (i === startIndex) {
                        var len = field.text.GetLength() - offset;
                        if (len > 0) {
                            offset = field.Delete(offset, field.text.GetLength() - offset);
                        }
                    } else if (i === endIndex) {
                        offset = field.Delete(offset, endOffset);
                    } else {
                        offset = field.Delete(offset, field.text.GetLength());
                    }

                    if (offset != null) {
                        start += offset - startOffset;
                    }
                    offset = 0;
                }
                return start;
            };

            MaskFieldCollection.prototype.Replace = function (start, length, text, includePrompt) {
                var retObj = {};
                retObj.cursorPos = start;
                retObj.text = text;

                var startIndex = this.GetFieldIndex(start, offset);
                var offset = 0;
                var startIndex = 0;
                var posObj = {};
                posObj = this.GetFieldIndex(start, offset);
                startIndex = posObj.index;
                offset = posObj.offset;

                this.SaveOldState();

                var field;
                for (; startIndex < this.fieldCount; startIndex++) {
                    field = this.fieldArray[startIndex];
                    if (field._minLength > 0 || field.text.GetLength() > 0)
                        break;
                }

                while (startIndex !== 0 && offset === 0) {
                    if (this.fieldArray[startIndex].fieldLabel === 'PromptField') {
                        startIndex--;
                        field = this.fieldArray[startIndex];
                        offset = field.text.GetLength();
                        if (offset < field._minLength)
                            offset = field._minLength;
                    } else
                        break;
                }

                this.newStart = start;
                this.newLength = length;

                var endOffset = 0;
                var endIndex;
                posObj = this.GetFieldIndex(start + length, endOffset);
                endIndex = posObj.index;
                endOffset = posObj.offset;

                var orientLength = 0;
                for (var j = startIndex; j < endIndex; j++) {
                    field = this.fieldArray[endIndex - 1];
                    orientLength += field.text.GetLength();
                }
                orientLength = orientLength + endOffset;
                -startOffset;

                while (endIndex !== 0 && endOffset === 0) {
                    field = this.fieldArray[endIndex - 1];
                    if (!(field.fieldLabel === 'PromptField') && field.text.GetLength() < field._maxLength) {
                        endIndex--;
                        endOffset = this.fieldArray[endIndex].text.GetLength();
                    } else
                        break;
                }

                var oldText = text;

                var existInvalid = false;
                var fieldStart = start - offset;
                for (var i = startIndex; i <= this.fieldCount - 1; i++) {
                    existInvalid = false;
                    field = this.fieldArray[i];
                    var fieldLength = field.text.GetLength() > field._minLength ? field.text.GetLength() : field._minLength;
                    if (field.fieldLabel === 'PromptField') {
                        fieldLength = field.GetLength();
                        if (includePrompt) {
                            var fieldText = field.text.Substring(offset, field.text.GetLength());

                            var oldlength = text.GetLength();
                            if (text.GetLength() >= fieldText.GetLength()) {
                                if (text.Substring(0, fieldText.GetLength()) !== fieldText)
                                    existInvalid = true;

                                text = text.Substring(fieldText.GetLength(), text.GetLength());
                                start += fieldText.GetLength();
                            } else {
                                if (text.Substring(0, fieldText.GetLength()) !== fieldText)
                                    existInvalid = true;

                                text = "";
                                start += text.GetLength();
                            }

                            if (existInvalid) {
                                if (exception) {
                                }
                                if (oldlength === text.GetLength())
                                    break;
                            }
                        } else if ((fieldStart + offset) === start)
                            start += (fieldLength - offset);

                        fieldStart += (field.text.GetLength() - offset);
                    } else {
                        var startOffset = offset;
                        var isLast = (i === this.fieldCount - 1);
                        if (i > endIndex) {
                            var insObj = {};
                            var isLast = (i === this.fieldCount - 1);
                            insObj = field.Insert(offset, text, isLast);
                            offset = insObj.offset;
                            text = insObj.text;
                            existInvalid = insObj.existInvalid;
                        } else if (startIndex === endIndex) {
                            var repRet = {};
                            repRet = field.Replace(offset, endOffset - offset, text, isLast);
                            offset = repRet.offset;
                            text = repRet.text;
                            existInvalid = repRet.existInvalid;
                        } else if (i === startIndex) {
                            var repRet = {};
                            repRet = field.Replace(offset, fieldLength - offset, text, isLast);
                            offset = repRet.offset;
                            text = repRet.text;
                            existInvalid = repRet.existInvalid;
                        } else if (i === endIndex) {
                            var repRet = {};
                            if (endOffset - offset > 0) {
                                repRet = field.Replace(offset, endOffset - offset, text, isLast);
                            } else if (length > 0) {
                                repRet = field.Replace(offset, length, text, isLast);
                            }
                            offset = repRet.offset;
                            text = repRet.text;
                            existInvalid = repRet.existInvalid;
                        } else {
                            var repRet = {};
                            repRet = field.Replace(offset, fieldLength, text);
                            offset = repRet.offset;
                            text = repRet.text;
                            existInvalid = repRet.existInvalid;
                        }

                        var exception = (field.GetFieldStatus() !== 2);
                        if (exception && existInvalid) {
                            break;
                        }

                        start += offset - startOffset;
                        fieldStart += (field._minLength > field.text.GetLength() ? field._minLength : field.text.GetLength());
                    }
                    offset = 0;

                    if (text === "") {
                        if (i < endIndex) {
                            i++;
                            var j = i;
                            var endlength = 0;
                            ;

                            for (; i < endIndex; i++) {
                                if (this.fieldArray[i].fieldLabel !== "PromptField") {
                                    this.fieldArray[i].Delete(offset, this.fieldArray[i].text.GetLength());
                                }
                            }

                            for (var k = 0; k < j; k++) {
                                var field = this.fieldArray[k];
                                var fieldLength = field.GetLength();

                                endlength += fieldLength;
                            }
                            if (start === endlength && field._trueLength === field._maxLength)
                                for (; j <= endIndex; j++) {
                                    if ((this.fieldArray[j].fieldLabel === "PromptField") && (j !== this.fieldCount - 1)) {
                                        start += this.fieldArray[j].text.GetLength();
                                    } else {
                                        break;
                                    }
                                }
                            if (endOffset === 0)
                                break;
                            if (this.fieldArray[endIndex].fieldLabel !== "PromptField") {
                                this.fieldArray[endIndex].Delete(offset, endOffset);
                            }
                        }
                        break;
                    }
                }

                if (oldText === text) {
                    this.RollBack();
                    retObj.success = false;
                } else {
                    retObj.success = true;
                }
                retObj.cursorPos = start;
                retObj.text = text;
                return retObj;
            };

            MaskFieldCollection.prototype.SetText = function (text, includePrompt) {
                var start = 0;
                var returnInfo = {};

                returnInfo.cursorPos = start;
                returnInfo.text = text;

                if (this.fieldCount === 0 || !text || start < 0) {
                    return returnInfo;
                }

                var offset = 0;
                var startIndex = 0;
                var retObj = {};
                retObj = this.GetFieldIndex(start, offset);
                startIndex = retObj.index;
                offset = retObj.offset;
                if (offset === this.fieldArray[startIndex]._maxLength) {
                    return returnInfo;
                }
                while (startIndex !== 0 && offset === 0) {
                    var field = this.fieldArray[startIndex - 1];

                    if (!(field.fieldLabel === 'PromptField') && field.text.GetLength() < field._maxLength) {
                        startIndex--;
                        offset = this.fieldArray[startIndex]._trueLength;
                        if (offset < this.fieldArray[startIndex]._minLength)
                            offset = this.fieldArray[startIndex]._minLength;
                    } else
                        break;
                }

                var existInvalid = false;
                var i = startIndex;
                var fieldStart = start - offset;
                for (; i < this.fieldCount; i++) {
                    existInvalid = false;
                    var field = this.fieldArray[i];

                    if (field.fieldLabel === 'PromptField') {
                        if (includePrompt) {
                            var fieldText = field.text.Substring(offset, field.text.GetLength());

                            var oldlength = text.GetLength();
                            if (text.GetLength() >= fieldText.GetLength()) {
                                if (text.Substring(0, fieldText.GetLength()) !== fieldText)
                                    existInvalid = true;
                                else {
                                    text = text.Substring(fieldText.GetLength(), text.GetLength()); //text.Remove(0, fieldText.GetLength());
                                    start += fieldText.GetLength();
                                }
                            } else {
                                if (fieldText.Substring(0, text.GetLength()) !== text)
                                    existInvalid = true;

                                text = "";
                                start += text.GetLength();
                            }

                            if (existInvalid) {
                                if (exception) {
                                }
                                if (text.GetLength() === oldlength) {
                                    returnInfo.isValid = false;
                                    return returnInfo;
                                }
                            }
                        } else if ((fieldStart + offset) === start)
                            start += (field.maxLength - offset);

                        fieldStart += (field.maxLength - offset);
                    } else {
                        var startOffset = offset;
                        var insObj = {};
                        var isLast = (i === this.fieldCount - 1);

                        insObj = field.SetTextInternal(text, offset, isLast);
                        this.oldStart = -1;
                        this.oldLength = 0;
                        this.newStart = -1;
                        this.newLength = 0;
                        if (this.formatIsNull) {
                            this.SaveUndoState();
                        }

                        offset = insObj.offset;
                        text = insObj.text;
                        existInvalid = insObj.existInvalid;
                        var exception = insObj.exception;

                        if (existInvalid && exception) {
                            returnInfo.isValid = false;
                            return returnInfo;
                        }

                        start += offset - startOffset;
                        fieldStart += field._minLength < field._trueLength ? field._trueLength : field._minLength;
                    }
                    offset = 0;

                    if ((text.GetLength() === 0) && (existInvalid || exception)) {
                        if (!includePrompt)
                            break;
                        else if (existInvalid) {
                            returnInfo.isValid = false;
                            return returnInfo;
                        }
                    }
                }

                if (i >= this.fieldCount && text !== "" && text.GetLength() > 0) {
                    returnInfo.isValid = false;
                    return returnInfo;
                } else {
                    var truePosObj = this.GetFieldIndex(start, offset);
                    var newIndex = truePosObj.index;
                    var newoffset = truePosObj.offset;
                    if (i < this.fieldCount) {
                        if (newIndex === i + 1 && newoffset === 0 && this.fieldArray[i].text.GetLength() === this.fieldArray[i]._maxLength) {
                            if (this.fieldArray[i + 1].fieldLabel === 'PromptField')
                                start += this.fieldArray[i + 1].GetLength();
                        }
                    }

                    returnInfo.isValid = true;

                    returnInfo.cursorPos = start;
                    returnInfo.text = text;
                    return returnInfo;
                }
            };

            MaskFieldCollection.prototype.Insert = function (start, text, includePrompt, isSetText) {
                var returnInfo = {};

                returnInfo.cursorPos = start;
                returnInfo.text = text;

                if (this.fieldCount === 0 || !text || start < 0) {
                    return returnInfo;
                }

                var offset = 0;
                var retObj = this.GetFieldIndex(start, offset);
                var startIndex = retObj.index;
                offset = retObj.offset;
                if (offset === this.fieldArray[startIndex]._maxLength) {
                    return returnInfo;
                }
                while (startIndex !== 0 && offset === 0) {
                    var field = this.fieldArray[startIndex - 1];

                    if (!(field.fieldLabel === 'PromptField') && field.text.GetLength() < field._maxLength) {
                        startIndex--;
                        offset = this.fieldArray[startIndex]._trueLength;
                        if (offset < this.fieldArray[startIndex]._minLength) {
                            offset = this.fieldArray[startIndex]._minLength;
                            returnInfo = this.InsertProcess(startIndex, offset, start, text, includePrompt);
                            if (returnInfo.text !== "") {
                                if (start === offset) {
                                    startIndex++;
                                    offset = 0;
                                    break;
                                }
                            } else {
                                return returnInfo;
                            }
                        }
                    } else
                        break;
                }
                return this.InsertProcess(startIndex, offset, start, text, includePrompt, isSetText);
            };

            MaskFieldCollection.prototype.InsertProcess = function (startIndex, offset, start, text, includePrompt, isSetText) {
                var returnInfo = {};
                var existInvalid = false;
                var i = startIndex;
                var fieldStart = start - offset;

                this.SaveOldState();

                for (; i < this.fieldCount; i++) {
                    existInvalid = false;
                    var field = this.fieldArray[i];

                    if (field.fieldLabel === 'PromptField') {
                        if (includePrompt) {
                            var fieldText = field.text.Substring(offset, field.text.GetLength());

                            var oldlength = text.GetLength();
                            if (text.GetLength() >= fieldText.GetLength()) {
                                if (text.Substring(0, fieldText.GetLength()) !== fieldText)
                                    existInvalid = true;

                                text = text.Substring(fieldText.GetLength(), text.GetLength()); //text.Remove(0, fieldText.GetLength());
                                start += fieldText.GetLength();
                            } else {
                                if (fieldText.Substring(0, text.GetLength()) !== text)
                                    existInvalid = true;

                                text = "";
                                start += text.GetLength();
                            }

                            if (existInvalid) {
                                if (exception) {
                                }
                                if (text.GetLength() === oldlength)
                                    break;
                            }
                        } else
                            start += (field.maxLength - offset);

                        fieldStart += (field.maxLength - offset);
                    } else {
                        var startOffset = offset;
                        var isLast = (i === this.fieldCount - 1);
                        var insObj = field.Insert(offset, text, isLast, isSetText);

                        offset = insObj.offset;
                        text = insObj.text;
                        existInvalid = insObj.existInvalid;
                        var exception = insObj.exception;

                        if (existInvalid && exception) {
                            if (text === returnInfo.text) {
                                return returnInfo;
                            } else {
                                break;
                            }
                        }

                        start += offset - startOffset;
                        fieldStart += field._minLength < field._trueLength ? field._trueLength : field._minLength;
                    }
                    offset = 0;

                    if (text.GetLength() === 0)
                        break;
                }

                if (i >= this.fieldCount && text !== "" && text.GetLength() > 0 && text === returnInfo.text) {
                    return returnInfo;
                } else {
                    var truePosObj = this.GetFieldIndex(start, offset);
                    var newIndex = truePosObj.index;
                    var newoffset = truePosObj.offset;
                    if (i < this.fieldCount) {
                        if (newIndex === i + 1 && newoffset === 0 && this.fieldArray[i].text.GetLength() === this.fieldArray[i]._maxLength && this.GetShowLiterals() !== 2 /* PostDisplay */) {
                            if (this.fieldArray[i + 1].fieldLabel === 'PromptField' && i + 1 !== this.fieldCount - 1)
                                start += this.fieldArray[i + 1].GetLength();
                        }
                    }

                    returnInfo.cursorPos = start;
                    returnInfo.text = text;

                    return returnInfo;
                }
            };

            MaskFieldCollection.prototype.MoveField = function (pos, isForward) {
                var posInfo = this.GetFieldIndex(pos);
                var fieldIndex = posInfo.index;
                var fieldOffset = posInfo.offset;

                if (fieldIndex === -1) {
                    return -1;
                }

                if (isForward) {
                    if (fieldIndex === this.fieldCount - 1) {
                        return -1;
                    }

                    while (this.GetFieldByIndex(fieldIndex).text.GetLength() === 0 && fieldIndex < this.fieldCount)
                        fieldIndex++;

                    if (fieldIndex === this.fieldCount - 1) {
                        return -1;
                    }

                    fieldIndex++;

                    if (this.GetFieldByIndex(fieldIndex).fieldLabel === "PromptField") {
                        if (fieldIndex === this.fieldCount - 1) {
                            return -1;
                        } else {
                            fieldIndex++;
                        }
                    }

                    var length = 0;
                    for (var i = 0; i < fieldIndex; i++) {
                        length += this.GetFieldByIndex(i).GetLength();
                    }

                    return length;
                } else {
                    if (fieldIndex === 0 || (fieldIndex === 1 && fieldOffset === 0)) {
                        return -1;
                    }

                    while (this.GetFieldByIndex(fieldIndex).text.GetLength() === 0 && fieldIndex > 0)
                        fieldIndex--;

                    if (fieldIndex === 0) {
                        return -1;
                    }

                    fieldIndex--;

                    if (this.GetFieldByIndex(fieldIndex).fieldLabel === "PromptField") {
                        if (fieldIndex === 0) {
                            return -1;
                        } else {
                            fieldIndex--;
                        }
                    }

                    var length = 0;
                    for (var i = 0; i < fieldIndex; i++) {
                        length += this.GetFieldByIndex(i).GetLength();
                    }

                    return length;
                }
            };

            MaskFieldCollection.prototype.GetPosByCurrentField = function (curField) {
                if (curField == null)
                    return null;
                var startIndex = 0;
                var insertIndex = -1;
                var findable = false;
                for (; startIndex < this.fieldCount; startIndex++) {
                    var field = this.fieldArray[startIndex];
                    if (field.fieldLabel !== "PromptField") {
                        insertIndex++;
                    }
                    if (insertIndex === curField) {
                        findable = true;
                        break;
                    }
                }

                if (findable) {
                    return this.GetFieldRange(startIndex);
                } else {
                    if (insertIndex === -1)
                        return null;
                    else {
                        if (startIndex >= this.fieldCount)
                            startIndex = this.fieldCount - 1;
                        while (this.fieldArray[startIndex].fieldLabel === "PromptField")
                            startIndex--;
                        return this.GetFieldRange(startIndex);
                    }
                }
            };

            MaskFieldCollection.prototype.GetFirstInputPosition = function () {
                var isNull = this.ValueIsNull();

                if (isNull && this._focusNull !== "" && !this.formatIsNull) {
                    return 0;
                }
                if (this.fieldArray[0].fieldLabel === "PromptField") {
                    return this.GetFieldRange(1).start;
                }
                return 0;
            };

            MaskFieldCollection.prototype.GetTotalInputFieldCount = function () {
                var result = 0;
                if (this.fieldCount > 0) {
                    for (var i = 0; i < this.fieldCount; i++) {
                        var field = this.fieldArray[i];
                        if (field.fieldLabel !== "PromptField") {
                            result++;
                        }
                    }
                }
                return result;
            };

            MaskFieldCollection.prototype.GetFieldIndexByPos = function (position) {
                return this.GetFieldIndex(position);
            };

            MaskFieldCollection.prototype.CanUndo = function () {
                if (this.fieldCount > 0) {
                    for (var i = 0; i < this.fieldCount; i++) {
                        var field = this.fieldArray[i];
                        if (field.fieldLabel !== "PromptField") {
                            if (field.undoTempText !== field.text) {
                                return true;
                            }
                        }
                    }
                }

                return false;
            };

            MaskFieldCollection.prototype.GetRealFieldRange = function (fieldIndex) {
                var fieldRange = {};
                fieldRange.start = 0;
                fieldRange.length = 0;
                var length = 0;
                var realfield = -1;
                var fieldpos = -1;

                for (var i = 0; i < this.fieldCount; i++) {
                    if (this.fieldArray[i].fieldLabel !== "PromptField") {
                        realfield++;
                    }
                    if (realfield === fieldIndex) {
                        fieldpos = i;
                        break;
                    }
                }

                for (var i = 0; i < fieldpos; i++) {
                    var field = this.GetFieldByIndex(i);

                    length += field.GetLength();
                }

                var currentField = this.GetFieldByIndex(fieldpos);

                if (!currentField) {
                    return fieldRange;
                }

                fieldRange.start = length;
                fieldRange.length = currentField.GetLength();

                return fieldRange;
            };
            MaskFieldCollection.prototype.PushBack = function (field) {
                this.Add(field);
                this.fieldCount++;
            };
            return MaskFieldCollection;
        })(FieldCollection);
        input.MaskFieldCollection = MaskFieldCollection;

        

        /** @ignore */
        var MaskUIProcess = (function (_super) {
            __extends(MaskUIProcess, _super);
            function MaskUIProcess(data) {
                _super.call(this);
                this.OldPosition = 0;
                this.IsFocus = false;
                this.isSelectionDeterminedByHighlightText = false;
                this.Format = null;
                if (data.HelpID != null) {
                    this.HelpID = data.HelpID;
                }

                if (data.Owner) {
                    this.Owner = data.Owner;
                }
            }
            MaskUIProcess.prototype.GetCurrentField = function (pos) {
                var text = this.GetShowText(this.GetShowLiterals());

                //fix bug#5476
                if (this.Format.Fields.ValueIsNull() && text != null && ((this.Format.Fields._focusNull !== "" && text === this.Format.Fields._focusNull) || (text != null && text == ""))) {
                    var fieldPos = {};
                    fieldPos.index = -1;
                    return fieldPos;
                }
                return this.Format.Fields.GetCurrentField(pos);
            };

            MaskUIProcess.prototype.FocusInternal = function (focusType, oText, highlightText, cursorField, selectionStart) {
                var retInfo = {};
                var text = this.GetShowText(this.GetShowLiterals());
                this.OldValue = this.Format.Fields.GetText();
                this.isMulSelected = false;
                this.isDblClick = false;
                this.isTriClick = false;

                // Add comments by Yang at 15:04 October 11th 2007
                // For fix bug 8998
                retInfo.SelectionStart = selectionStart;

                // End by Yang
                //commented by Kevin, Jun 8, 2007
                //bug#7769
                //		//the focusType is used to distribute the get focus type by Left key
                //		// or Right key or something else.
                //		//if ( focusType === FocusType.Click )
                //		//For bug 3917
                //		if ((focusType === FocusType.Click || this.IsFocus === false) && focusType != FocusType.ClientEvent)
                //		{
                //			retInfo.SelectionStart = Utility.GetCursorPosition(oText);
                //			retInfo.SelectionEnd   = retInfo.SelectionStart;
                //		}
                if (focusType === 1 /* Click */) {
                    retInfo.SelectionStart = input.Utility.GetCursorPosition(oText);
                    retInfo.SelectionEnd = retInfo.SelectionStart;
                }

                //end by Kevin
                //when get the focus, display the format.
                retInfo.Text = text;

                if (this.Format.Fields.ValueIsNull() && (retInfo.Text != null && this.Format.Fields._focusNull !== "" && retInfo.Text === this.Format.Fields._focusNull)) {
                    retInfo.SelectionStart = 0;
                    retInfo.SelectionEnd = 0;
                }

                //modified by sj 2008.8.14 for bug 514
                if (this.Format.Fields.ValueIsNull() && this.Format.Fields._owner._getDisplayNullExpression() !== null) {
                    retInfo.SelectionStart = 0;
                    retInfo.SelectionEnd = 0;
                }

                //end by sj
                //Press tab key will set cursor start position to less than zero
                if (retInfo.SelectionStart === -1 || retInfo.SelectionStart > retInfo.Text.GetLength()) {
                    retInfo.SelectionStart = 0;
                    retInfo.SelectionEnd = 0;
                }

                //Add comments by Ryan Wu at 15:04 Apr. 27 2007.
                //For fix the bug#7769.
                //		if (focusType === FocusType.Left)
                //		{
                //			retInfo.SelectionStart = retInfo.Text.GetLength();
                //			retInfo.SelectionEnd   = retInfo.Text.GetLength();
                //		}
                //		else if (focusType === FocusType.Right)
                //		{
                //			retInfo.SelectionStart = 0;
                //			retInfo.SelectionEnd   = 0;
                //		}
                if (focusType === 9 /* Left */) {
                    retInfo.SelectionStart = 0;
                    retInfo.SelectionEnd = 0;
                } else if (focusType === 10 /* Right */) {
                    retInfo.SelectionStart = retInfo.Text.GetLength();
                    retInfo.SelectionEnd = retInfo.Text.GetLength();
                }

                //end by Ryan Wu.
                //According to the HighlightText property and CursorPosition property to set the
                //selection.
                var curPos = retInfo.SelectionStart;

                if (focusType !== 6 /* SpinButton */ && focusType !== 2 /* ContextMenu */ && focusType !== 3 /* ClientEvent */ && focusType !== 8 /* ImeInput */ && !(highlightText === 0 /* None */ && cursorField === -1)) {
                    //bug#6930
                    if (this.Format.Fields.ValueIsNull() && (retInfo.Text != null && this.Format.Fields._focusNull != "" && retInfo.Text === this.Format.Fields._focusNull)) {
                        retInfo.SelectionEnd = retInfo.Text.GetLength();
                    } else {
                        var ret = this.SetCursorPositionAndSelection(highlightText, "", cursorField, curPos);
                        if (ret != null) {
                            retInfo.SelectionStart = ret.SelectionStart;
                            retInfo.SelectionEnd = ret.SelectionEnd;
                            //this.isSelectionDeterminedByHighlightText = true;
                        }
                    }
                }

                //Record the position now for undo.
                if (retInfo.SelectionStart != null)
                    this.OldPosition = retInfo.SelectionStart;

                this.IsFocus = true;
                return retInfo;
            };

            MaskUIProcess.prototype.SetCursorPositionAndSelection = function (highlightText, text, cursorField, startPos) {
                var retInfo;

                if (highlightText === 2 /* All */) {
                    this.isSelectionDeterminedByHighlightText = true;
                    retInfo = this.SelectAll();
                } else if (highlightText === 1 /* Field */) {
                    this.isSelectionDeterminedByHighlightText = true;
                    if (cursorField <= -1) {
                        if (startPos > 0) {
                            var fieldIndex = this.Format.Fields.GetFieldIndex(startPos).index;
                            var field = this.Format.Fields.fieldArray[fieldIndex];
                            if (field.fieldLabel === "PromptField") {
                                if (fieldIndex === this.Format.Fields.fieldCount - 1)
                                    fieldIndex--;
                                else
                                    fieldIndex++;
                            }
                            var fieldPos = this.Format.Fields.GetFieldRange(fieldIndex);
                            retInfo = {};
                            retInfo.SelectionStart = fieldPos.start;
                            retInfo.SelectionEnd = fieldPos.length + fieldPos.start;
                        } else {
                            retInfo = this.GetPosByCurrentField(startPos);
                        }
                        //return retInfo;
                    } else {
                        retInfo = this.GetPosByCurrentField(cursorField);
                    }
                } else {
                    retInfo = this.GetPosByCurrentField(cursorField);

                    if (retInfo != null) {
                        retInfo.SelectionStart = retInfo.SelectionStart;
                        retInfo.SelectionEnd = retInfo.SelectionStart;
                    }
                }

                return retInfo;
            };

            MaskUIProcess.prototype.GetPosByCurrentField = function (curField) {
                var retInfo = {};
                var rangeInfo = this.Format.Fields.GetPosByCurrentField(curField);

                // rangeInfo = this.Format.Fields.GetFieldRange(curField);
                if (rangeInfo != null && rangeInfo != -1) {
                    retInfo.SelectionStart = rangeInfo.start;
                    retInfo.SelectionEnd = rangeInfo.start + rangeInfo.length;

                    return retInfo;
                }

                return null;
            };
            MaskUIProcess.prototype.LoseFocus = function () {
                var retInfo = {};

                if (this.Owner._getFormatIsNull() != true) {
                    this.Format.Fields.SaveUndoState();
                }

                retInfo.Text = this.GetShowText(this.GetShowLiterals(), "LoseFocus");
                retInfo.Value = this.Format.Fields.GetValue();
                this.IsFocus = false;

                return retInfo;
            };

            MaskUIProcess.prototype.GetSepText = function () {
                //Commented by Kevin, Feb 17, 2009
                //bug#1891
                if (this.Owner._getFormatIsNull()) {
                    return this.Format.Fields.GetText();
                }

                //end by Kevin
                var sepText = "";
                var i = this.Format.Fields.fieldCount - 1;

                for (var j = 0; j <= i; j++) {
                    var field = this.Format.Fields.fieldArray[j];
                    if (field.fieldLabel === "PromptField") {
                        continue;
                    }
                    var length = field._trueLength;
                    var retValue = field.text;

                    //Filter field.
                    if (field.fieldLabel === 'FilterField') {
                        for (var k = 0; k < length; k++) {
                            if (field._bitState[k] === false) {
                                retValue = retValue.Substring(0, k) + " " + retValue.Substring(k + 1, retValue.GetLength());
                            }
                        }
                    } else {
                        if (field._activeItem === -1) {
                            retValue = "";
                        }
                    }
                    if (j != i) {
                        var tempValue = retValue.Substring(0, length);
                        tempValue = tempValue.replace(/'/g, "@#GCD#@").replace(/"/g, "@#GCM#@").replace(/,/g, "@#GCC#@").replace(/@#GCF#@/g, "\\");

                        //Commented by Kevin, Jan 4, 2009
                        //bug#1418 tcp
                        if (field.fieldLabel === 'FilterField') {
                            if (!this.Owner._getFormatIsNull()) {
                                var validateText = retValue.Substring(0, length);
                                for (var k = 0; k < length; k++) {
                                    if (field._bitState[k] === false) {
                                        validateText = validateText.Substring(0, k) + input.Utility.MaskValChar + validateText.Substring(k + 1, validateText.GetLength());
                                    }
                                }
                                tempValue += input.Utility.Hold + "," + validateText.replace(/'/g, "@#GCD#@").replace(/"/g, "@#GCM#@").replace(/,/g, "@#GCC#@").replace(/@#GCF#@/g, "\\");
                            }
                        }

                        sepText += tempValue + input.Utility.Hold + ";";
                    } else {
                        var tempValue = retValue.Substring(0, length);
                        tempValue = tempValue.replace(/'/g, "@#GCD#@").replace(/"/g, "@#GCM#@").replace(/,/g, "@#GCC#@").replace(/@#GCF#@/g, "\\");

                        //Commented by Kevin, Jan 4, 2009
                        //bug#1418 tcp
                        if (field.fieldLabel === 'FilterField') {
                            if (!this.Owner._getFormatIsNull()) {
                                var validateText = retValue.Substring(0, length);
                                for (var k = 0; k < length; k++) {
                                    if (field._bitState[k] === false) {
                                        validateText = validateText.Substring(0, k) + input.Utility.MaskValChar + validateText.Substring(k + 1, validateText.GetLength());
                                    }
                                }
                                tempValue += input.Utility.Hold + "," + validateText.replace(/'/g, "@#GCD#@").replace(/"/g, "@#GCM#@").replace(/,/g, "@#GCC#@").replace(/@#GCF#@/g, "\\");
                            }
                        }

                        sepText += tempValue;
                    }
                }
                return sepText;
            };

            MaskUIProcess.prototype.SetSepText = function (text) {
                if (!text) {
                    for (var fieldIndex = 0; fieldIndex < this.Format.Fields.fieldCount; fieldIndex++) {
                        var field = this.Format.Fields.fieldArray[fieldIndex];
                        if (field.fieldLabel === "PromptField") {
                            continue;
                        }
                        field.Clear();
                    }
                    return true;
                }

                //Commented by Kevin, Jan 4, 2009
                //bug#1418 tcp
                //var sp = ',';
                var sp = input.Utility.Hold + ";";
                var sepText = text.split(sp);

                for (var i = 0; i < sepText.length; i++) {
                    sepText[i] = sepText[i].replace(/@#GCC#@/g, ",").replace(/@#GCD#@/g, "'").replace(/@#GCM#@/g, "\"");
                }

                var isLast = false;
                var j = 0;
                for (var fieldIndex = 0; fieldIndex < this.Format.Fields.fieldCount; fieldIndex++) {
                    var field = this.Format.Fields.fieldArray[fieldIndex];
                    if (field.fieldLabel === "PromptField") {
                        continue;
                    }

                    if (j < sepText.length) {
                        //Commented by Kevin, Jan 4, 2009
                        //bug#1418 tcp
                        //text = sepText[j];
                        var inputText = sepText[j].split(input.Utility.Hold + ",");

                        //var newText = inputText[0].replace(/ /g, this.PromptChar);
                        var newText = inputText[0];
                        var validateText = "";
                        if (inputText.length > 1) {
                            validateText = inputText[1];
                            if (validateText && validateText != "" && newText != validateText) {
                                var startIndex = 0;
                                var findIndex = newText.IndexOf(" ", startIndex);
                                while (findIndex != -1) {
                                    if (validateText.Substring(findIndex, findIndex + 1) === input.Utility.MaskValChar) {
                                        newText = newText.Substring(0, findIndex) + this.Owner.GetPromptChar() + newText.Substring(findIndex + 1, newText.GetLength());
                                    }
                                    startIndex = findIndex;
                                    findIndex = newText.IndexOf(" ", startIndex);
                                }
                            }
                        }

                        //end by Kevin
                        //not same as server side
                        isLast = (j === this.Format.Fields.fieldCount - 1);
                        var textLength = newText.GetLength();
                        if (textLength < field._minLength) {
                            for (var i = 0; i < field._minLength - textLength; i++) {
                                newText += this.Owner.GetPromptChar();
                                validateText += input.Utility.MaskValChar;
                            }
                        }

                        //Commented by Kevin, Jan 4, 2009
                        //bug#1418 tcp
                        //var insObj = field.SetText(0, newText, isLast);
                        var insObj;
                        if (field.fieldLabel === 'FilterField') {
                            insObj = field.SetTextInternal(newText, 0, isLast, validateText);
                        } else {
                            insObj = field.SetTextInternal(newText, 0, isLast);
                        }

                        //end by Kevin
                        if (insObj.existInvalid && insObj.exception) {
                            return false;
                        }

                        //
                        j++;
                    } else {
                        field.Clear();
                    }
                }
                return true;
            };

            MaskUIProcess.prototype.ProcessShortcutKey = function (keyAction, readOnly, end) {
                var retInfo = {};
                switch (keyAction) {
                    case "Clear":
                        if (!readOnly) {
                            this.Format.Fields.ClearContent();
                        }
                        retInfo.SelectionStart = this.Format.Fields.GetFirstInputPosition();
                        retInfo.SelectionEnd = retInfo.SelectionStart;
                        retInfo.Text = this.GetShowText(this.GetShowLiterals());
                        return retInfo;
                    case "NextField":
                        if (this.IsLastInputField(end, true)) {
                            return true;
                        }

                        break;
                    case "PreviousField":
                        if (this.IsLastInputField(end, false)) {
                            return true;
                        }
                }
                retInfo = _super.prototype.ProcessShortcutKey.call(this, keyAction, readOnly, end);

                return retInfo;
            };

            MaskUIProcess.prototype.KeyDown = function (Data) {
                var k = Data.KeyCode;

                //var start = Data.SelectionStart;
                //var end = Data.SelectionStart;
                //var isExitOnLastChar = Data.ExitOnLastChar;
                var retInfo = _super.prototype.KeyDown.call(this, Data);

                //Escape key.
                if (k === 27) {
                    this.Owner.Clear();
                }
                if (Data.KeyAction != null) {
                    return retInfo;
                }

                if (Data.ReadOnly === true) {
                    return retInfo;
                }

                //if (k === 131158)
                //{
                //    //if null now,set position 0,0;
                //    if (this.Format.Fields.ValueIsNull() && this.Format.Fields._focusNull != "")
                //    {
                //        start = 0;
                //        end = 0;
                //    }
                //}
                if (k != undefined && k != null) {
                    if ((k >= 48 && k <= 57) || (k >= 65 && k <= 90) || (k >= 96 && k <= 105) || k === 0 || k === 229 || k === 231) {
                        //input status.Response by keyup event.
                        if (!retInfo) {
                            retInfo = {};
                        }
                        MaskControl.Mask_ImeResponse = true;
                        retInfo.inputChar = true;

                        return retInfo;
                    }

                    // for symbol charactors
                    //Add comments by Ryan Wu at 15:03 Mar. 2 2006.
                    //For fix bug that 226 keycode can't be input into the edit reported by Japan.
                    /*if(  k===32 || k === 106 || k === 107 || k === 109 || k === 110 || k === 111 || k === 219
                    || k === 220 || k === 221 || k === 222 || (k >= 186 && k <= 192) )*/
                    if (k === 32 || k === 106 || k === 107 || k === 109 || k === 110 || k === 111 || k === 219 || k === 220 || k === 221 || k === 222 || (k >= 186 && k <= 192) || k === 226) {
                        //input status.Response by keyup event.
                        if (!retInfo) {
                            retInfo = {};
                        }
                        MaskControl.Mask_ImeResponse = true;
                        retInfo.inputChar = true;

                        return retInfo;
                    }

                    // Add comments by Yang at 14:13 Sep. 12th 2007
                    // For fix the bug 8754
                    if (!input.CoreUtility.IsIE() && (k === 61 || k === 59)) {
                        if (!retInfo) {
                            retInfo = {};
                        }
                        MaskControl.Mask_ImeResponse = true;
                        retInfo.inputChar = true;

                        return retInfo;
                    }

                    // End by Yang
                    var tempk = k;

                    //Shift + key
                    if (Data.FuncKeysPressed.Shift && k != 65552) {
                        tempk = k - 65536;
                    }

                    if (k > 65600 && k < 65627) {
                        tempk = k - 65536;
                    }

                    if ((tempk >= 48 && tempk <= 57) || (tempk >= 65 && tempk <= 90) || (tempk >= 96 && tempk <= 105) || tempk === 229 || tempk === 0 || tempk === 231) {
                        //input status.Response by keyup event.
                        if (!retInfo) {
                            retInfo = {};
                        }
                        MaskControl.Mask_ImeResponse = true;
                        retInfo.inputChar = true;

                        return retInfo;
                    }

                    // for symbol charactors
                    //Add comments by Ryan Wu at 15:03 Mar. 2 2006.
                    //For fix bug that 226 keycode can't be input into the edit reported by Japan.
                    /*if (tempk === 32 || tempk === 106 || tempk === 107 || tempk === 109 || tempk === 110
                    || tempk === 111 || tempk === 219 || tempk === 220 || tempk === 221
                    || tempk === 222 || (tempk >= 186 && tempk <= 192))*/
                    var fireFoxSpecial = (k == 173 || k == 64 || k == 160 || k == 65594 || k == 58 || k == 65709 || k == 65600 || k == 65696) && input.CoreUtility.IsFireFox4OrLater();

                    if (fireFoxSpecial || tempk === 32 || tempk === 106 || tempk === 107 || tempk === 109 || tempk === 110 || tempk === 111 || tempk === 219 || tempk === 220 || tempk === 221 || tempk === 222 || (tempk >= 186 && tempk <= 192) || tempk === 226 || tempk == 231) {
                        //input status.Response by keyup event.
                        if (!retInfo) {
                            retInfo = {};
                        }
                        MaskControl.Mask_ImeResponse = true;
                        retInfo.inputChar = true;

                        return retInfo;
                    }

                    // Add comments by Yang at 14:00 Sep. 12th 2007
                    // For fix the bug 8754
                    if (!input.CoreUtility.IsIE() && (tempk === 61 || tempk === 59)) {
                        if (!retInfo) {
                            retInfo = {};
                        }
                        MaskControl.Mask_ImeResponse = true;
                        retInfo.inputChar = true;

                        return retInfo;
                    }
                    // End by Yang
                }

                return retInfo;
            };

            MaskUIProcess.prototype.KeyPressInternal = function (inputElement, start, end, isExitOnLastChar, inputChar) {
                if (MaskControl.Mask_ImeResponse === true) {
                    MaskControl.Mask_ImeResponse = false;

                    var retInfo = {};

                    //if null now,set position 0,0;
                    if (this.Format.Fields.ValueIsNull() && this.Format.Fields._focusNull != "") {
                        start = 0;
                        end = 0;
                    }

                    var processInfo = this.ProcessCharKey(start, end, inputChar, isExitOnLastChar);

                    if (processInfo.success) {
                        retInfo.SelectionStart = processInfo.start;
                        retInfo.SelectionEnd = retInfo.SelectionStart;
                        retInfo.Text = this.GetShowText(this.GetShowLiterals());
                        this.isMulSelected = false;

                        //if ExitOnLastChar is true and the caret is move to the right-most of the edit field
                        //then the focus will move to the next control.
                        if (this.moveFocusExitOnLastChar) {
                            var ret = this.MoveControl(this.GetElementId(), true, false, "CharInput");

                            if (ret != null) {
                                retInfo.EventInfo = ret.EventInfo;
                                retInfo.FocusType = ret.FocusType;
                                retInfo.FocusExit = true;
                            }
                            this.moveFocusExitOnLastChar = false;
                        }
                    } else {
                        retInfo.SelectionStart = processInfo.start;
                        retInfo.SelectionEnd = Math.max(start, end);
                        retInfo.Text = this.GetShowText(this.GetShowLiterals());
                        retInfo.EventInfo = processInfo.EventInfo;
                        retInfo.exception = true;

                        //modified by sj 2008.8.13 for bug 370
                        if (this.moveFocusExitOnLastChar) {
                            retInfo.FocusExit = true;
                            this.moveFocusExitOnLastChar = false;
                        }
                        //end by sj
                    }

                    return retInfo;
                } else {
                    return false;
                }
            };

            MaskUIProcess.prototype.ProcessCharKey = function (start, end, charInput, isExitOnLastChar) {
                var processInfo = _super.prototype.ProcessCharKey.call(this, start, end, charInput, isExitOnLastChar);

                var selectionStart = Math.min(start, end);

                //judge if the focus should exit on last char.
                if (processInfo.success) {
                    selectionStart = processInfo.start;
                }

                if (isExitOnLastChar) {
                    this.moveFocusExitOnLastChar = false;
                    if (selectionStart === this.Format.Fields.GetExistLength()) {
                        this.moveFocusExitOnLastChar = true;
                    }
                }

                return processInfo;
            };

            MaskUIProcess.prototype.ContextMenu = function () {
            };

            MaskUIProcess.prototype.Click = function () {
            };

            MaskUIProcess.prototype.Undo = function (pos) {
                var retInfo = {};
                this.Format.Fields.Undo();

                //Return true position last operation.
                retInfo.SelectionStart = this.OldPosition;
                retInfo.SelectionEnd = this.OldPosition;

                //Record
                this.OldPosition = pos;
                retInfo.Value = this.Format.Fields.GetText();

                //commented by Kevin, May 31, 2007
                //modify GetShowText method
                //retInfo.Text  = this.GetShowText(retInfo.Value);
                retInfo.Text = this.GetShowText(this.GetShowLiterals());

                //end by Kevin
                return retInfo;
            };

            MaskUIProcess.prototype.Paste = function (start, end, text, isExitOnLastChar, isSetSelectedText) {
                var retInfo = {};
                retInfo.SelectionStart = start;
                retInfo.SelectionEnd = end;

                //modified by sj for bug 1994
                //if isSetSelectedText is true, there is no need calling Utility.GetPasteData()
                var pasteData;
                if (isSetSelectedText != null && isSetSelectedText === true) {
                    pasteData = text;
                } else if (this.Owner) {
                    pasteData = input.Utility.GetPasteData(this.Owner.GetUseClipboard());

                    // Frank Liu fixed bug 569 at 2013/06/05.
                    pasteData = this.UpdateCrLfString(pasteData, this.Owner.GetAcceptsCrlf());
                } else {
                    pasteData = input.Utility.GetPasteData(true);
                }
                var processInfo = null;

                if (pasteData != null) {
                    if (pasteData.IndexOf("\r") != -1) {
                        pasteData = pasteData.Substring(0, pasteData.IndexOf("\r"));
                    }
                    if (pasteData.IndexOf("\n") != -1) {
                        pasteData = pasteData.Substring(0, pasteData.IndexOf("\n"));
                    }
                }

                if (!pasteData) {
                    return retInfo;
                }

                //End for SetSelectedText function.
                this.FireClientEvent("OnBeforePaste");

                var selectionStart = Math.min(start, end);
                var selectionEnd = Math.max(start, end);
                var selectionLength = selectionEnd - selectionStart;
                if (selectionStart === selectionEnd) {
                    retInfo.SelectionStart = this.Format.Fields.Insert(selectionStart, pasteData, false).cursorPos;
                    retInfo.Text = this.GetShowText(this.GetShowLiterals());
                    retInfo.SelectionEnd = retInfo.SelectionStart;
                } else {
                    var orientText = this.GetShowText(this.GetShowLiterals());

                    //5409
                    if (orientText != null && this.Format.Fields._focusNull != "" && orientText === this.Format.Fields._focusNull && this.Format.Fields.fieldArray[0].text != orientText) {
                        processInfo = this.Format.Fields.Insert(0, pasteData, false);
                    } else {
                        processInfo = this.Format.Fields.Replace(selectionStart, selectionLength, pasteData, false);
                    }
                    retInfo.SelectionStart = processInfo.cursorPos;

                    retInfo.Text = this.GetShowText(this.GetShowLiterals());
                    if (orientText === retInfo.Text && processInfo.success === false) {
                        retInfo.SelectionStart = selectionStart;
                        retInfo.SelectionEnd = selectionEnd;
                    } else {
                        retInfo.SelectionEnd = retInfo.SelectionStart;
                    }
                }

                //if exist invalid charactor, fire event.
                if (retInfo.Text.Substring(selectionStart, selectionStart + pasteData.GetLength()) != pasteData) {
                    //add judgement on selectionStart for bug#4335,6841, KevinHuang, 2006-04-25
                    if (retInfo.SelectionStart - selectionStart < pasteData.GetLength() && this.InvalidInput != "") {
                        var eventInfo = {};
                        eventInfo.Name = this.InvalidInput;
                        eventInfo.Args = null;

                        //Add comments by Ryan Wu at 10:56 Apr. 5 2007.
                        //For support Aspnet Ajax 1.0.
                        eventInfo.Type = "InvalidInput";

                        //end by Ryan Wu.
                        retInfo.EventInfo = eventInfo;
                    }
                }

                //judge if the focus should exit on last char.
                if (isExitOnLastChar) {
                    if (retInfo.SelectionStart === this.Format.Fields.GetExistLength()) {
                        this.moveFocusExitOnLastChar = true;
                    } else {
                        var posInfo = this.Format.Fields.GetFieldIndex(retInfo.SelectionStart);
                        var fieldIndex = posInfo.index;
                        var fieldOffset = posInfo.offset;

                        if (fieldIndex === this.Format.Fields.fieldCount - 1 && fieldOffset === 0 && this.Format.Fields.GetFieldByIndex(fieldIndex).fieldLabel === "PromptField") {
                            this.moveFocusExitOnLastChar = true;
                        }
                    }
                }

                //if ExitOnLastChar is true and the caret is move to the right-most of the edit field
                //then the focus will move to the next control.
                if (this.moveFocusExitOnLastChar) {
                    //Commetned by Kevin, Dec 22, 2008
                    //bug#1316
                    //var ret = this.MoveControl(this.ElementID, true, false, "NextControl");
                    var ret = this.MoveControl(this.GetElementId(), true, false, "CharInput");

                    //end by Kevin
                    if (ret != null) {
                        retInfo.EventInfo = ret.EventInfo;
                        retInfo.FocusType = ret.FocusType;
                        retInfo.FocusExit = true;
                    }

                    this.moveFocusExitOnLastChar = false;
                }

                if (retInfo.SelectionStart != selectionStart) {
                    this.FireClientEvent("OnPaste");
                }

                return retInfo;
            };

            MaskUIProcess.prototype.UpdateCrLfString = function (text, crlfMode) {
                if (crlfMode !== 0 /* NoControl */) {
                    return input.BaseUIProcess.UpdateCrLfString(text, crlfMode);
                } else {
                    return input.BaseUIProcess.UpdateCrLfString(text, 2 /* Cut */);
                }
            };

            MaskUIProcess.prototype.DragStart = function () {
            };

            MaskUIProcess.prototype.DragEnd = function () {
            };
            MaskUIProcess.prototype.DragOver = function () {
            };
            MaskUIProcess.prototype.DragInit = function () {
            };

            MaskUIProcess.prototype.SetValue = function (value) {
                this.Format.Fields.SetValue(value);
            };
            MaskUIProcess.prototype.GetShowText = function (showliterals, type, notNull) {
                var text = "";
                if (!type) {
                    text = this.Format.Fields.GetShowText(showliterals, "", notNull);
                } else if (type === "LoseFocus") {
                    text = this.Format.Fields.GetShowText(showliterals, "LoseFocus", notNull);
                }

                return text;
            };
            MaskUIProcess.prototype.ProcessBackSpaceKey = function (start, end) {
                //get the selection information.
                var selectionStart = Math.min(start, end);
                var selectionLength = Math.abs(start - end);
                var retInfo = {};
                retInfo.SelectionStart = selectionStart;
                retInfo.SelectionEnd = selectionStart + selectionLength;

                //none action.
                if (selectionStart === 0 && selectionLength === 0) {
                    return retInfo;
                }

                //get the start field, end field's index and offset of the selection range.
                var startFieldIndex;
                var startFieldOffset;

                var fieldPosInfo = this.Format.Fields.GetFieldIndex(selectionStart);
                startFieldIndex = fieldPosInfo.index;
                startFieldOffset = fieldPosInfo.offset;

                //none action.
                if (startFieldIndex === -1) {
                    return retInfo;
                }

                //if the selectionlength = 0, do the delete action for previous char.
                if (selectionLength === 0) {
                    var pfield = this.Format.Fields.GetFieldByIndex(startFieldIndex);
                    if (startFieldIndex === 0 && startFieldOffset === 0) {
                        return retInfo;
                    }

                    while ((startFieldOffset === 0 || pfield.fieldLabel === "PromptField") && startFieldIndex > 0) {
                        startFieldIndex--;
                        selectionLength += startFieldOffset;
                        pfield = this.Format.Fields.GetFieldByIndex(startFieldIndex);
                        startFieldOffset = pfield.GetLength();
                        if (pfield.fieldLabel === "PromptField") {
                            selectionLength += startFieldOffset;
                            startFieldOffset = 0;
                        }
                    }

                    if (startFieldIndex === 0) {
                        if (this.Format.Fields.GetFieldByIndex(startFieldIndex).fieldLabel === "PromptField") {
                            return retInfo;
                        }

                        if (this.Format.Fields.GetFieldByIndex(startFieldIndex).GetLength() === 0) {
                            return retInfo;
                        }
                    }

                    //FilterFiled
                    if (this.Format.Fields.GetFieldByIndex(startFieldIndex).fieldLabel === "FilterField") {
                        selectionLength = selectionLength + 1;

                        //startFieldOffset = this.Format.Fields.GetFieldByIndex(startFieldIndex).GetLength();
                        selectionStart = selectionStart - selectionLength;
                        selectionLength = 1;
                    } else if (this.Format.Fields.GetFieldByIndex(startFieldIndex).fieldLabel === "EnumField") {
                        //startFieldOffset = 0;
                        selectionLength = selectionLength + this.Format.Fields.GetFieldByIndex(startFieldIndex).GetLength();
                        selectionStart = selectionStart - selectionLength;
                        selectionStart = selectionStart > 0 ? selectionStart : 0;
                    } else {
                        return retInfo;
                    }

                    //invoke this.Format.Fields.Delete action to process backspace action.
                    selectionStart = this.Format.Fields.Delete(selectionStart, selectionLength);

                    retInfo.SelectionStart = selectionStart;
                    retInfo.SelectionEnd = retInfo.SelectionStart;
                } else {
                    var endFieldIndex;

                    // var endFieldOffset;
                    fieldPosInfo = this.Format.Fields.GetFieldIndex(selectionStart + selectionLength);
                    endFieldIndex = fieldPosInfo.index;

                    //endFieldOffset = fieldPosInfo.offset;
                    //none action.
                    if (endFieldIndex === -1) {
                        return retInfo;
                    }

                    if (startFieldOffset === 0 && startFieldIndex != 0) {
                        startFieldIndex--;
                        //startFieldOffset = this.Format.Fields.GetFieldByIndex(startFieldIndex).GetLength();
                    }

                    if ((startFieldIndex === endFieldIndex && this.Format.Fields.GetFieldByIndex(endFieldIndex).fieldLabel === "PromptField")) {
                        return retInfo;
                    }

                    //invoke DateFieldCollection.Delete action to process backspace action.
                    retInfo.SelectionStart = this.Format.Fields.Delete(selectionStart, selectionLength);
                    retInfo.SelectionEnd = retInfo.SelectionStart;
                }

                return retInfo;
            };

            MaskUIProcess.prototype.PerformSpinInternal = function (start, end, increment, wrap, isUp) {
                //if no field return position;
                if (this.Format.Fields.fieldCount <= 0) {
                    return null;
                }

                var retInfo = {};
                retInfo.SelectionStart = start;
                retInfo.SelectionEnd = end;
                retInfo.Text = this.GetShowText(this.GetShowLiterals());

                //judge the startfield
                //var posInfo = this.Format.Fields.GetFieldIndex(start);
                var posInfo = this.Format.Fields.GetFieldIndex(end);
                var fieldIndex = posInfo.index;
                var offset = posInfo.offset;
                if (fieldIndex != 0 && offset === 0) {
                    if (start === end) {
                        if (this.Format.Fields.fieldArray[fieldIndex].fieldLabel != "EnumField") {
                            fieldIndex--;
                        }
                    } else {
                        if (start < end) {
                            fieldIndex--;
                        }
                    }
                }

                if (this.Format.Fields.fieldArray[fieldIndex].fieldLabel != "EnumField" && this.Format.Fields.fieldArray[fieldIndex].text.GetLength() != 0) {
                    //if( this.Format.Fields.fieldArray[fieldIndex].text.GetLength() != 0)
                    //	return retInfo;
                } else {
                    if (isUp) {
                        retInfo.SelectionStart = this.Format.Fields.PerformSpin(end, increment, wrap);
                    } else {
                        //bug#8097
                        retInfo.SelectionStart = this.Format.Fields.PerformSpin(end, -increment, wrap);
                    }
                    retInfo.SelectionEnd = retInfo.SelectionStart;
                    retInfo.Text = this.GetShowText(this.GetShowLiterals());
                }

                if (isUp) {
                    if (this.SpinUp != "") {
                        var eventInfo = {};
                        eventInfo.Name = this.SpinUp;
                        eventInfo.Args = null;

                        //Add comments by Ryan Wu at 10:56 Apr. 5 2007.
                        //For support Aspnet Ajax 1.0.
                        eventInfo.Type = "SpinUp";

                        //end by Ryan Wu.
                        retInfo.EventInfo = eventInfo;
                    }
                } else {
                    if (this.SpinDown != "") {
                        var eventInfo = {};
                        eventInfo.Name = this.SpinDown;
                        eventInfo.Args = null;

                        //Add comments by Ryan Wu at 10:57 Apr. 5 2007.
                        //For support Aspnet Ajax 1.0.
                        eventInfo.Type = "SpinDown";

                        //end by Ryan Wu.
                        retInfo.EventInfo = eventInfo;
                    }
                }

                return retInfo;
            };

            MaskUIProcess.prototype.ProcessBackSpace = function (start, end) {
                var retInfo = this.ProcessBackSpaceKey(start, end);
                retInfo.Text = this.GetShowText(this.GetShowLiterals());

                this.isMulSelected = false;
                return retInfo;
            };

            MaskUIProcess.prototype.ProcessDeleteKey = function (start, end) {
                //get the selection information.
                var selectionStart = Math.min(start, end);
                var selectionLength = Math.abs(start - end);
                var retInfo = {};
                retInfo.SelectionStart = selectionStart;
                retInfo.SelectionEnd = selectionStart + selectionLength;

                if (selectionStart === this.Format.Fields.GetLength() && selectionLength === 0) {
                    return retInfo;
                }

                var startFieldIndex;
                var fieldPosInfo = this.Format.Fields.GetFieldIndex(selectionStart);
                startFieldIndex = fieldPosInfo.index;

                //none action.
                if (startFieldIndex === -1) {
                    return retInfo;
                }

                //if the selectionlength = 0, do the delete action for one post char.
                if (selectionLength === 0) {
                    //none action.
                    if (this.Format.Fields.GetFieldByIndex(startFieldIndex).fieldLabel === "PromptField") {
                        return retInfo;
                    }

                    selectionStart = this.Format.Fields.Delete(selectionStart, 1);

                    retInfo.SelectionStart = selectionStart;
                    retInfo.SelectionEnd = retInfo.SelectionStart;
                } else {
                    var endFieldOffset;
                    var endFieldIndex;
                    fieldPosInfo = this.Format.Fields.GetFieldIndex(selectionStart + selectionLength);
                    endFieldOffset = fieldPosInfo.offset;
                    endFieldIndex = fieldPosInfo.index;

                    //none action.
                    if (endFieldIndex === -1) {
                        return retInfo;
                    }

                    if (endFieldOffset === 0) {
                        endFieldIndex--;
                    }

                    //none action
                    if (startFieldIndex === endFieldIndex && this.Format.Fields.GetFieldByIndex(startFieldIndex).fieldLabel === "PromptField") {
                        return retInfo;
                    }

                    retInfo.SelectionStart = this.Format.Fields.Delete(selectionStart, selectionLength);
                    retInfo.SelectionEnd = retInfo.SelectionStart;
                }

                return retInfo;
            };

            MaskUIProcess.prototype.ProcessDelete = function (start, end) {
                var retInfo = this.ProcessDeleteKey(start, end);
                retInfo.Text = this.GetShowText(this.GetShowLiterals());
                this.isMulSelected = false;

                return retInfo;
            };

            MaskUIProcess.prototype.GetNullCasePosition = function (cursorPos, keyCode) {
                var fields = this.Format.Fields;
                switch (keyCode) {
                    case 36:

                    case 65572:

                    case 131109:

                    case 196645:

                    case 196644:

                    case 131108:
                        cursorPos = 0;
                        break;

                    case 35:

                    case 65571:
                        cursorPos = fields.GetLength();
                        break;

                    case 65573:

                    case 37:
                        if (cursorPos != 0) {
                            cursorPos--;
                        }
                        break;

                    case 39:

                    case 65575:
                        if (cursorPos != fields.GetLength()) {
                            cursorPos++;
                        }
                        break;

                    case 131111:

                    case 196647:

                    case 196643:

                    case 131107:
                        cursorPos = fields.GetLength();
                        break;

                    case 131118:

                    case 131080:
                    case 196616:
                        return cursorPos;
                }
                return cursorPos;
            };

            MaskUIProcess.prototype.GetCaretPosition = function (cursorPos, keyCode) {
                // For null case, get normal position.for bug 3852.
                if (this.Format.Fields.ValueIsNull() && this.Format.Fields._focusNull != "") {
                    return this.GetNullCasePosition(cursorPos, keyCode);
                }

                var fields = this.Format.Fields;
                var fieldPosInfo = fields.GetFieldIndex(cursorPos);
                var fieldIndex = fieldPosInfo.index;

                // var fieldOffset = fieldPosInfo.offset;
                var fieldRange;
                var startPos;
                var endPos = 0;
                ;
                var i = 0;

                for (i = 0; i < fields.fieldCount; i++) {
                    if (fields.GetFieldByIndex(i).fieldLabel != "PromptField") {
                        startPos = fields.GetFieldRange(i).start;
                        break;
                    }
                }

                //Find the end position by this.ShowLiterals.
                var lastFieldIndex = fields.GetLastVisibleFieldIndex(this.GetShowLiterals());

                //bug#4976
                if (this.ShowLiterals === 3 /* PreDisplay */) {
                    for (i = lastFieldIndex; i >= 0; i--) {
                        if (fields.GetFieldByIndex(i).fieldLabel != "PromptField") {
                            endPos += fields.GetFieldByIndex(i)._trueLength;
                            //break;
                        }
                    }
                } else {
                    for (i = lastFieldIndex; i >= 0; i--) {
                        if (fields.GetFieldByIndex(i).fieldLabel != "PromptField") {
                            fieldRange = fields.GetFieldRange(i);

                            endPos = fieldRange.start + fieldRange.length;
                            break;
                        }
                    }
                }

                var oldcursorPos = cursorPos;

                cursorPos = _super.prototype.GetCaretPosition.call(this, cursorPos, keyCode, startPos, endPos, "PromptField");

                //bug#4642
                var fieldPosInfo = fields.GetFieldIndexByPos(oldcursorPos);
                var fieldIndex = fieldPosInfo.index;
                var fieldRange;
                if (keyCode === 196647 && cursorPos === oldcursorPos) {
                    for (; fieldIndex < lastFieldIndex; fieldIndex++) {
                        fieldRange = fields.GetFieldRange(fieldIndex + 1);
                        cursorPos = fieldRange.start;
                        if (cursorPos > startPos) {
                            break;
                        }
                    }
                    if (fieldIndex === lastFieldIndex) {
                        cursorPos = cursorPos + fieldRange.length;
                    }
                }

                if (keyCode === 131111) {
                    if (fields.GetFieldByIndex(fieldIndex).fieldLabel != "PromptField" && fields.GetFieldRange(fieldIndex).length === 0) {
                        while (fields.GetFieldRange(fieldIndex).length === 0 && fieldIndex < fields.fieldCount - 1) {
                            fieldIndex++;
                        }
                        for (i = fieldIndex + 1; i < fields.fieldCount; i++) {
                            //find the edit field after the current field
                            if (fields.GetFieldByIndex(i).fieldLabel != "PromptField") {
                                fieldRange = fields.GetFieldRange(i);

                                return fieldRange.start;
                            }
                        }
                    }
                }

                return cursorPos;
            };

            MaskUIProcess.prototype.ProcessTabKey = function (pos, isForward, tabAction) {
                var retInfo;

                if (tabAction === 1 /* Field */ && !(this.Format.Fields.ValueIsNull() && this.Format.Fields._focusNull != "" && this.GetShowText(this.GetShowLiterals()) === this.Format.Fields._focusNull)) {
                    retInfo = this.MoveFieldAndControl(pos, isForward);
                } else {
                    //invoke the KeyExit Event if it exit
                    retInfo = _super.prototype.ProcessTabKey.call(this, pos, isForward, tabAction);
                }

                return retInfo;
            };

            MaskUIProcess.prototype.ProcessLeftDirection = function (start, end, k) {
                var retInfo = {};

                //Here exists bugs, when delete all, then input , it will start at the first position, but it is wrong.
                //we should judge if it is express or full of prompt char.
                if (!this.isMulSelected || k === 36 || k === 131108) {
                    retInfo.SelectionStart = this.GetCaretPosition(end, k);
                    retInfo.SelectionEnd = retInfo.SelectionStart;
                } else {
                    retInfo.SelectionStart = Math.min(start, end);
                    retInfo.SelectionEnd = retInfo.SelectionStart;
                }

                if (k === 37 || k === 131109) {
                    // For null.for bug 3852.
                    if (this.Format.Fields.ValueIsNull() && this.Format.Fields._focusNull != "") {
                    } else {
                        if (retInfo.SelectionStart > 0) {
                            //retInfo.SelectionStart = start - 1;
                            var fieldPosInfo = this.Format.Fields.GetFieldIndex(retInfo.SelectionStart);
                            var startFieldIndex = fieldPosInfo.index;
                            var startFieldOffset = fieldPosInfo.offset;

                            //Calculate the correct start and length information for DateFieldCollection.Delete method.
                            if (this.Format.Fields.GetFieldByIndex(startFieldIndex).fieldLabel === "PromptField" && this.isMulSelected === false) {
                                retInfo.SelectionStart -= startFieldOffset;
                            }
                            retInfo.SelectionEnd = retInfo.SelectionStart;
                        }
                    }
                    this.isMulSelected = false;

                    return retInfo;
                }

                this.isMulSelected = false;

                if (!this.isMulSelected || k === 36 || k === 131108) {
                    retInfo.SelectionStart = this.GetCaretPosition(end, k);
                    retInfo.SelectionEnd = retInfo.SelectionStart;
                } else {
                    retInfo.SelectionStart = Math.min(start, end);

                    var fieldPosInfo = this.Format.Fields.GetFieldIndex(retInfo.SelectionStart);
                    var startFieldIndex = fieldPosInfo.index;
                    var startFieldOffset = fieldPosInfo.offset;

                    //Calculate the correct start and length information for DateFieldCollection.Delete method.
                    if (this.Format.Fields.GetFieldByIndex(startFieldIndex).fieldLabel === "PromptField") {
                        retInfo.SelectionStart -= startFieldOffset;
                    }
                    retInfo.SelectionEnd = retInfo.SelectionStart;
                }

                return retInfo;
            };

            MaskUIProcess.prototype.ProcessRightDirection = function (start, end, k) {
                var retInfo = {};

                //Ritht arrow
                if (!this.isMulSelected || k === 35 || k === 131107) {
                    retInfo.SelectionStart = this.GetCaretPosition(end, k);
                    retInfo.SelectionEnd = retInfo.SelectionStart;

                    //Added for bug 3852.
                    this.isMulSelected = false;
                    return retInfo;
                } else {
                    retInfo.SelectionStart = Math.max(start, end);

                    //if value is null, return;
                    if (this.Format.Fields.ValueIsNull() === true && this.Format.Fields._focusNull != "") {
                        retInfo.SelectionEnd = retInfo.SelectionStart;
                        this.isMulSelected = false;
                        return retInfo;
                    }

                    //get the start field, end field's index and offset of the selection range.
                    var startFieldIndex;
                    var startFieldOffset;

                    var fieldPosInfo = this.Format.Fields.GetFieldIndex(retInfo.SelectionStart);
                    startFieldIndex = fieldPosInfo.index;
                    startFieldOffset = fieldPosInfo.offset;

                    //Calculate the correct start and length information for DateFieldCollection.Delete method.
                    if (this.Format.Fields.GetFieldByIndex(startFieldIndex).fieldLabel === "PromptField" && this.isMulSelected === false) {
                        var field = this.Format.Fields.fieldArray[startFieldIndex];
                        retInfo.SelectionStart += field.text.GetLength() - startFieldOffset;
                    }
                    retInfo.SelectionEnd = retInfo.SelectionStart;

                    this.isMulSelected = false;

                    return retInfo;
                }
            };

            MaskUIProcess.prototype.IsLastInputField = function (pos, isForward) {
                var posObj = this.Format.Fields.GetFieldIndex(pos, 0);
                var fieldIndex = posObj.index;

                if (isForward) {
                    while (fieldIndex < this.Format.Fields.fieldCount - 1 && this.Format.Fields.fieldArray[fieldIndex + 1].fieldLabel != "PromptField" && this.Format.Fields.fieldArray[fieldIndex + 1].text.GetLength() === 0) {
                        fieldIndex++;
                    }

                    var i = this.Format.Fields.fieldCount - 1;
                    for (; i > fieldIndex; i--) {
                        if (this.Format.Fields.fieldArray[i].fieldLabel != "PromptField") {
                            break;
                        }
                    }
                    if (i === fieldIndex) {
                        return true;
                    }

                    return false;
                } else {
                    while (fieldIndex > 0 && this.Format.Fields.fieldArray[fieldIndex - 1].fieldLabel != "PromptField" && this.Format.Fields.fieldArray[fieldIndex - 1].text.GetLength() === 0) {
                        fieldIndex--;
                    }

                    var i = 0;
                    for (; i < fieldIndex; i++) {
                        if (this.Format.Fields.fieldArray[i].fieldLabel != "PromptField") {
                            break;
                        }
                    }
                    if (i === fieldIndex) {
                        return true;
                    }

                    return false;
                }
            };

            MaskUIProcess.prototype.DoubleClick = function (pos) {
                var retInfo = {};

                //Commented by Kevin, Feb 25, 2008
                //fix bug#4724comment#4
                //		if (this.Format.Fields.ValueIsNull())
                var text = this.GetShowText(this.GetShowLiterals());
                if (this.Format.Fields.ValueIsNull() && text != null && ((this.Format.Fields._focusNull != "" && text === this.Format.Fields._focusNull) || (text != null && text == ""))) {
                    var text = this.GetShowText(this.GetShowLiterals());
                    retInfo.SelectionStart = 0;
                    retInfo.SelectionEnd = text.GetLength();
                } else {
                    retInfo = _super.prototype.DoubleClick.call(this, pos);
                }

                return retInfo;
            };
            return MaskUIProcess;
        })(input.BaseUIProcess);
        input.MaskUIProcess = MaskUIProcess;

        /** @ignore */
        var MaskControl = (function (_super) {
            __extends(MaskControl, _super);
            function MaskControl() {
                _super.call(this);
                this.IMControlType = "Mask";
                this._promptChar = "_";
                this._autoConvert = true;
                this._displayNull = null;
                this._null = "";
                this._formatPattern = "";
                this._exitOnLastChar = false;
                this._displayNullExpresson = null;
                this._showLiterals = 1 /* Always */;
                this._tabAction = 0 /* Control */;
                this._hideEnter = false;
                this._hidePromptOnLeave = false;
                this._textWithPromptChar = null;
                this.Init();
            }
            MaskControl.prototype.AttachInput = function (inputElement) {
                this.InputElement = inputElement;
                this.AddAllEventsHandler();
            };

            MaskControl.prototype.DetachInput = function () {
                $(this.InputElement).unbind(".wijinput");
                this.InputElement = null;
            };

            MaskControl.prototype.GetAutoConvert = function () {
                return this._autoConvert;
            };

            MaskControl.prototype.SetAutoConvert = function (value) {
                this._autoConvert = value;
            };

            MaskControl.prototype.GetExitOnLastChar = function () {
                return this._exitOnLastChar;
            };

            MaskControl.prototype.SetExitOnLastChar = function (value) {
                value = input.Utility.CheckBool(value);
                this._exitOnLastChar = value;
            };

            MaskControl.prototype.GetNull = function () {
                return this._null;
            };

            MaskControl.prototype.SetNull = function (value) {
                if (value !== this._null) {
                    var result = MaskFormat.ParseFillExpression(value, this.Format.Fields);
                    if (result.Expression === null) {
                        this.Format.Fields._focusNull = value;
                    } else {
                        this.Format.Fields._focusNull = result.Expression;
                    }

                    this._null = value;
                }
            };

            MaskControl.prototype._getDisplayNullExpression = function () {
                if (this._displayNullExpresson !== null) {
                    return this._displayNullExpresson;
                }
                return this._displayNull;
            };

            MaskControl.prototype.GetDisplayNull = function () {
                return this._displayNull;
            };

            MaskControl.prototype.SetDisplayNull = function (value) {
                if (value === undefined) {
                    value = null;
                }
                if (value !== null) {
                    value = input.Utility.CheckString(value);
                }
                if (value !== this._displayNull) {
                    var result = MaskFormat.ParseFillExpression(value, this.Format.Fields);

                    this._displayNullExpresson = result.Expression;

                    this._displayNull = value;
                    var maskValue = this.GetValue();
                    this.SetValue(maskValue);
                }
            };

            MaskControl.prototype.GetFormatPattern = function () {
                return this._formatPattern;
            };

            MaskControl.prototype.SetFormatPattern = function (pattern) {
                pattern = input.BaseUIProcess.UpdateCrLfString(pattern, 1 /* Filter */);
                if (pattern !== this._formatPattern) {
                    try  {
                        var filedCollection = MaskFormat.ParseFormat(pattern, this);
                        this.Clear();
                        this.Format.Fields = filedCollection;

                        this.ResetNullAndDispalyNull();
                        this.FormatIsNull = this.Format.Fields.formatIsNull;
                        this.Clear();
                        this.SetSelectionStart(0);

                        this._formatPattern = pattern;
                        var text = this.GetDisplayText();

                        // DaryLuo 2013/05/23 fix bug 459 in IM HTML5.0.
                        this.UpdateDisplayText(text);
                    } catch (e) {
                        throw "Format pattern is invalid";
                    }
                }
            };

            MaskControl.prototype.ResetNullAndDispalyNull = function () {
                var result = MaskFormat.ParseFillExpression(this.GetNull(), this.Format.Fields);
                if (result.Expression === null) {
                    this.Format.Fields._focusNull = this.GetNull();
                } else {
                    this.Format.Fields._focusNull = result.Expression;
                }

                result = MaskFormat.ParseFillExpression(this.GetDisplayNull(), this.Format.Fields);
                this._displayNullExpresson = result.Expression;
            };

            MaskControl.prototype.GetPromptChar = function () {
                return this._promptChar;
            };

            MaskControl.prototype.SetPromptChar = function (value) {
                if (!value) {
                    value = "_";
                }
                if (value.length > 1) {
                    value = value.charAt(0);
                }

                //value = Utility.CheckChar(value);
                if (value !== this._promptChar) {
                    this._promptChar = value;
                    var maskValue = this.GetValue();
                    this.SetValue(maskValue);
                }
            };

            MaskControl.prototype.GetShowLiterals = function () {
                return this._showLiterals;
            };

            MaskControl.prototype.SetShowLiterals = function (value) {
                if (value != this._showLiterals) {
                    this._showLiterals = value;
                    var maskValue = this.GetValue();
                    this.SetValue(maskValue);
                }
            };

            MaskControl.prototype.GetTabAction = function () {
                return this._tabAction;
            };

            MaskControl.prototype.SetTabAction = function (value) {
                this._tabAction = value;
            };

            MaskControl.prototype.GetCursorPosition = function () {
                return this.CursorPosition;
            };

            MaskControl.prototype.SetCursorPosition = function (value) {
                value = input.Utility.CheckInt(value, -1, Math.pow(2, 31));
                value = Math.min(value, this.Format.Fields.GetTotalInputFieldCount() - 1);
                if (value !== this.CursorPosition) {
                    this.CursorPosition = value;
                }
            };

            MaskControl.prototype.Init = function () {
                this._autoConvert = true;
                this.FormatIsNull = true;
                this.CursorPosition = -1;
                this.truePosition = -1;
                this.japInput = false;
                this.ImeMode = false;
                this.IsImplementImeInput = false;
                this.IsJapanConvertKeyPress = false;

                this.HelpID = '__' + this.ID + '_State';
                this.IsDragDrop = false;

                var data1 = {};
                data1.ID = this.ID;
                data1.HelpID = this.HelpID;

                data1.Owner = this;
                this.UIProcess = this._createUIProcess(data1);

                this.Format.Fields = MaskFormat.ParseFormat("", this);
                this.FormatIsNull = this.Format.Fields.formatIsNull;
                this.UIProcess.Format = this.Format;

                this.NewSelectionStart = 0;
                this.NewSelectionEnd = 0;

                if (this.IsInUpdatePanelAndAsyncPostBack) {
                } else {
                    if (this.UIUpdate) {
                        this.UIProcess.Format.Fields.ClearContent();
                        this.UIProcess.Format.Fields.SetText(this.UIUpdate.GetText(), true);
                    }
                }

                this.Text = this.UIProcess.Format.Fields.GetText();
                this.Value = this.UIProcess.Format.Fields.GetValue();
                this.OldText = this.UIProcess.Format.Fields.GetText();
                this.OldFocusText = this.UIProcess.Format.Fields.GetText();

                this.MouseButton = -1 /* Default */;

                this.FocusType = 0 /* None */;

                if (this.IsInUpdatePanelAndAsyncPostBack) {
                    var text = this.UIUpdate.GetText();

                    if (text != this.UIProcess.GetShowText(this.GetShowLiterals(), null, true) && text != this.UIProcess.GetShowText(this.GetShowLiterals(), "LoseFocus", false)) {
                        if (this.ShowLiterals === 1 /* Always */) {
                            this.UIProcess.Format.Fields.ClearContent();
                            this.UIProcess.Format.Fields.SetText(text, true);
                            this.SetHideValue();
                        } else {
                            this.UIProcess.Format.Fields.ClearContent();
                            var literalText = this.UIProcess.GetShowText("Always", null, true);
                            if (text.GetLength() < literalText.GetLength()) {
                                text = text + literalText.Substring(text.GetLength(), literalText.GetLength());
                            }
                            this.UIProcess.Format.Fields.SetText(text, true);
                            this.SetHideValue();
                        }
                    }

                    this.Text = this.UIProcess.Format.Fields.GetText();

                    this.Value = this.UIProcess.Format.Fields.GetValue();

                    this.OldText = this.UIProcess.Format.Fields.GetText();
                    this.OldFocusText = this.UIProcess.Format.Fields.GetText();
                }

                if (this.UIUpdate) {
                    this.DisplayText = this.GetTextboxValue();
                }

                this.LastStart = 0;
                this.LastEnd = 0;

                this.OrientText = "";
                this.ImeSelect = false;
                this.ImeSelectTimes = 0;

                this.Type = "Mask";

                if (this.UIUpdate) {
                    this.ReLoadData();
                }
            };

            MaskControl.prototype._createUIProcess = function (data) {
                return new MaskUIProcess(data);
            };

            MaskControl.prototype.Clear = function () {
                this.SetValue("");

                // DaryLuo 2013/05/23 fix bug 434 in IM HTMl5.0.
                this.SelectionStart = this.SelectionEnd = this.Format.Fields.GetFirstInputPosition();
            };

            MaskControl.prototype.SetValue = function (value) {
                if (value) {
                    if (typeof (value) != "string") {
                        value = value.toString();
                    }
                    if (this.FormatIsNull) {
                        value = value.replace(/[\r\n]/g, "");
                    }
                    value = input.BaseUIProcess.UpdateCrLfString(value, 1 /* Filter */);
                }

                if (this.UIProcess.Format.Fields.SetValue(value, false)) {
                    this.AfterSetTextValue();
                }
            };

            MaskControl.prototype.GetValue = function () {
                //return this.UIProcess.Format.Fields.GetValue();
                return this.Value;
            };

            MaskControl.prototype.GetSelectedText = function () {
                var start = Math.min(this.SelectionStart, this.SelectionEnd);
                var end = Math.max(this.SelectionStart, this.SelectionEnd);
                var text = this.Text.Substring(start, end);
                if (this.GetClipContent() === 1 /* ExcludeLiterals */) {
                    var startPos = Math.min(this.SelectionStart, this.SelectionEnd);
                    var length = this.GetSelectionLength();
                    text = this.UIProcess.Format.Fields.GetNonPromptText(startPos, length);
                }
                return text;
            };

            MaskControl.prototype.SetSelectedText = function (text) {
                if (!text) {
                    return;
                }

                var tempoldValue = this.Value;
                var tempoldText = this.Text;
                this.UIProcess.Paste(this.SelectionStart, this.SelectionEnd, text, false, true);

                var retInfo = {};
                retInfo.Text = this.GetDisplayText("Focus");

                if (!this.UpdateText(retInfo)) {
                    return;
                }
                this.UpdateDisplayText(this.Text);

                this.Value = this.UIProcess.Format.Fields.GetValue();
                if (this.Text != tempoldText) {
                    this.FireClientEvent("TextChanged", null);
                }
                if (this.Value != tempoldValue) {
                    this.FireClientEvent("ValueChanged", null);
                }
            };

            MaskControl.prototype.SetText = function (text) {
                try  {
                    this.ShowPromptChar();
                    this.Value = this.UIProcess.Format.Fields.GetValue();

                    if (!text) {
                        this.SetValue("");
                        return;
                    }
                    if (text === this.UIProcess.Format.Fields._focusNull && !this.UIProcess.Format.Fields.formatIsNull) {
                        this.SetValue("");
                        return;
                    }
                    this.UIProcess.Format.Fields.ClearContent();
                    if (this.FormatIsNull) {
                        text = text.replace(/[\r\n]/g, "");
                    }
                    text = input.BaseUIProcess.UpdateCrLfString(text, 1 /* Filter */);
                    if (this.UIProcess.Format.Fields.SetText(text, true).isValid === false) {
                        this.UIProcess.Format.Fields.RollBack();
                    } else {
                        this.AfterSetTextValue();
                    }
                } finally {
                    this.HidePromptChar();
                }
            };

            MaskControl.prototype.AfterSetTextValue = function () {
                var tempoldValue = this.Value;
                var tempoldText = this.Text;

                var retInfo = {};

                retInfo.Text = this.GetDisplayText("Focus");

                if (!this.UpdateText(retInfo)) {
                    return;
                }
                this.Value = this.UIProcess.Format.Fields.GetValue();
                this.UpdateDisplayText(this.GetDisplayText());
                if (this.Text != tempoldText) {
                    this.OldText = this.UIProcess.Format.Fields.GetText();
                    this.OldFocusText = this.UIProcess.Format.Fields.GetText();
                    this.FireClientEvent("TextChanged", null);
                }
                if (this.Value != tempoldValue) {
                    this.FireClientEvent("ValueChanged", null);
                }
            };
            MaskControl.prototype.GetText = function () {
                return this.GetDisplayText("Focus");
            };

            MaskControl.prototype.GetDisplayText = function (type) {
                if (!type) {
                    return this.UIProcess.GetShowText(this.GetShowLiterals(), "LoseFocus");
                } else if (type === "Focus") {
                    return this.UIProcess.GetShowText(this.GetShowLiterals());
                }
                return "";
            };

            MaskControl.prototype.GetCurrentField = function () {
                if (this.UIProcess.GetCurrentField(this.SelectionEnd) != null) {
                    return this.UIProcess.GetCurrentField(this.SelectionEnd).index;
                } else {
                    return 0;
                }
            };

            MaskControl.prototype.GetValueIsFull = function () {
                return this.UIProcess.Format.Fields.ValueIsFull(1);
            };

            MaskControl.prototype._getFormatIsNull = function () {
                return this.FormatIsNull;
            };

            MaskControl.prototype.FireClientEvent = function (eventType, args) {
                var name = "";

                switch (eventType) {
                    case "TextChanged":
                        if (this.TextChanged != "") {
                            name = this.TextChanged;
                        }
                        break;
                    case "ValueChanged":
                        if (this.ValueChanged != "") {
                            name = this.ValueChanged;
                        }
                        break;
                    default:
                        return;
                }

                return this.UIProcess.FireEvent(this, name, args, eventType);
            };

            MaskControl.prototype.Focus = function () {
                this.ShowPromptChar();

                if (!this.IsDragDrop && this.FocusType != 3 /* ClientEvent */ && this.FocusType != 6 /* SpinButton */) {
                    this.OldText = this.UIProcess.Format.Fields.GetText();
                    this.OldFocusText = this.UIProcess.Format.Fields.GetText();
                }

                if (this.UIProcess.Format.Fields.fieldCount > 0) {
                    var retInfo = this.UIProcess.FocusInternal(this.FocusType, this.InputElement, this.GetHighlightText(), this.CursorPosition, this.SelectionStart);
                    if (!retInfo) {
                        return;
                    }

                    if (retInfo.Text != null) {
                        this.Text = retInfo.Text;
                    }

                    if (retInfo.SelectionStart != null && this.NeedReCalCursorPos) {
                        this.SelectionStart = retInfo.SelectionStart;
                    }

                    if (retInfo.SelectionEnd != null && this.NeedReCalCursorPos) {
                        this.SelectionEnd = retInfo.SelectionEnd;
                        this.SelectionLength = this.GetSelectionLength();
                    }

                    if (!this.NeedReCalCursorPos) {
                        this.NeedReCalCursorPos = true;
                    }

                    if (this.japInput === true) {
                        if (this.truePosition != -1) {
                            this.SelectionStart = this.truePosition;
                            this.SelectionEnd = this.truePosition;
                        }
                        this.japInput = false;
                    }

                    if (this.GetReadOnly() === true && this.FocusType === 0 /* None */) {
                        this.SelectionStart = 0;
                        this.SelectionEnd = this.Text.length;
                    }

                    this.UpdateDisplayText(this.Text);

                    this.SetSelection(this.SelectionStart, this.SelectionEnd, true);

                    if (!this.IsDragDrop && this.FocusType != 3 /* ClientEvent */ && this.FocusType != 6 /* SpinButton */ && this.FocusType != 7 /* DropDown */) {
                        this.OldValue = this.Value;
                    }
                } else {
                    this.UpdateDisplayText(this.Text);
                    this.SetSelection(this.SelectionStart, this.SelectionEnd);
                    this.OldValue = this.Value;
                }

                this.IsDragDrop = false;
            };
            MaskControl.prototype._shouldFireValueChangedEvent = function () {
                return this.OldText != this.Text;
            };

            MaskControl.prototype.LoseFocus = function () {
                this.FireKeyExit();

                var imeMode = this.ImeMode;

                if (!input.CoreUtility.IsIE()) {
                    this.ImeInput("ReInput", true);
                } else {
                    this.ImeInput("LoseFocusInput");
                }
                if (this.SpinBtnPressed) {
                    return;
                }

                this.SetLastClientValues();

                var retInfo = this.UIProcess.LoseFocus();

                this.DisplayText = retInfo.Text;
                this.Value = retInfo.Value;
                this.Text = this.UIProcess.Format.Fields.GetText();

                if (input.CoreUtility.IsIE() || !imeMode) {
                    this.UpdateDisplayText(this.DisplayText);
                }
                if (!input.CoreUtility.IsIE() && imeMode) {
                    this.UpdateDisplayText(this.DisplayText);
                }

                this.FocusType = 0 /* None */;

                var focusType;
                if (retInfo.EventInfo != null) {
                    focusType = this.UIProcess.FireEvent(this, retInfo.EventInfo.Name, retInfo.EventInfo.Args, retInfo.EventInfo.Type); //end by Ryan Wu.

                    if (focusType != null) {
                        this.FocusType = focusType;
                    }
                }
                var self = this;
                if (!input.CoreUtility.IsIE() && this.DisplayText != this.UIUpdate.GetText() && imeMode) {
                    window.setTimeout(function () {
                        self.UpdateDisplayText(self.DisplayText);
                    }, 0);
                }

                if (this.GetHighlightText() === 2 /* All */) {
                    this.SelectionStart = 0;
                }

                if (this._shouldFireValueChangedEvent()) {
                    focusType = this.FireClientEvent("TextChanged", null);
                    if (focusType != null) {
                        this.FocusType = focusType;
                    }

                    focusType = this.FireClientEvent("ValueChanged", null);
                    if (focusType != null) {
                        this.FocusType = focusType;
                    }

                    this.OldText = this.UIProcess.Format.Fields.GetText();
                    this.OldFocusText = this.UIProcess.Format.Fields.GetText();
                    input.Utility.FireSystemEvent(this.InputElement, "onchange");

                    if (this._getAutoPostBack()) {
                    }
                }

                window.setTimeout(function () {
                    self.HidePromptChar();
                }, 50);
            };

            MaskControl.prototype.shouldFireValueChangedEvent = function () {
                return this.OldText != this.Text;
            };

            MaskControl.prototype.MouseDown = function (evt) {
                var mouseButton = input.Utility.GetMouseButton(evt);
                this.FocusedWhenMouseDown = document.activeElement === (evt.srcElement || evt.target);
                this.MouseDownOnClearButton = input.CoreUtility.IsMouseDownOnClearButton(evt);
                _super.prototype.MouseDown.call(this, evt);

                if (this.MouseButton === 2 /* Right */) {
                    this.FocusType = 2 /* ContextMenu */;
                } else {
                    this.MouseButton = 0 /* Left */;
                }

                this.UIProcess.isDblClick = false;
                this.SelectionLength = this.GetSelectionLength();

                if (!input.CoreUtility.IsIE() && this.ImeMode && mouseButton === 0 /* Left */) {
                    this.IsImplementImeInput = true;
                }
            };

            MaskControl.prototype.MouseUp = function (evt) {
                if (!input.CoreUtility.IsIE() && this.ImeMode) {
                    if (!this.IsImplementImeInput) {
                        return;
                    }
                    this.IsImplementImeInput = false;
                }

                this.LastStart = this.SelectionStart;
                this.LastEnd = this.SelectionEnd;
                _super.prototype.MouseUp.call(this, evt);

                if (!this.ImeMode) {
                    this.SelectionLength = this.GetSelectionLength();
                } else {
                    this.SelectionStart = this.LastStart;
                    this.SelectionEnd = this.LastEnd;
                    this.SelectionLength = this.GetSelectionLength();

                    if (input.CoreUtility.IsIE()) {
                        this.ImeInput("ClickInput");
                    } else {
                        this.ImeInput("ReInput", true);
                    }

                    if (!input.CoreUtility.IsIE() && this.Text != this.UIUpdate.GetText()) {
                        var self = this;
                        window.setTimeout(function () {
                            self.UpdateDisplayText(self.Text);
                        }, 0);
                    }
                }

                if (this.MouseUpPointerType == undefined) {
                    this.MouseUpHasValue = this.GetInputElement().value.length > 0;
                }
                this.HandleClearButton(evt);
            };

            MaskControl.prototype.KeyDown = function (evt) {
                var k = evt.keyCode;
                var funcKeysPressed = {};
                funcKeysPressed.Shift = false;
                funcKeysPressed.Ctrl = false;
                funcKeysPressed.Alt = false;
                if (evt.shiftKey) {
                    funcKeysPressed.Shift = true;
                }

                if (evt.ctrlKey) {
                    funcKeysPressed.Ctrl = true;
                }

                if (evt.altKey) {
                    funcKeysPressed.Alt = true;
                }

                var Data1 = {};
                var oldImeMode = this.ImeMode;

                this.ImeMode = false;

                if (k === 229) {
                    // DaryLuo 2013/08/29 fix bug 517 in IM HTML 5.0.
                    // Set IMeMode to true in the Composition start event.
                    if (input.CoreUtility.IsIE8OrBelow()) {
                        this.ImeMode = true;
                    }
                    return true;
                }

                if (!this.ImeMode && oldImeMode && !funcKeysPressed.Shift && !funcKeysPressed.Ctrl) {
                    if (k != 9 && k != 65545) {
                        this.ImeInput("ReInput", true);
                        this.ImeSelectTimes = 0;
                    }
                }

                Data1.KeyCode = k;
                Data1.Text = this.Text;
                Data1.FuncKeysPressed = funcKeysPressed;
                Data1.SelectionStart = this.SelectionStart;
                Data1.SelectionEnd = this.SelectionEnd;
                Data1.EditMode = this._getEditModeInternal();
                Data1.ReadOnly = this.GetReadOnly();
                Data1.ClipContent = this.GetClipContent();
                Data1.ExitOnLastChar = this.GetExitOnLastChar();
                Data1.ExitOnLeftRightKey = this.GetExitOnLeftRightKey();
                Data1.TabAction = this.GetTabAction();

                var retInfo = _super.prototype.KeyDown.call(this, Data1);

                if (retInfo.inputChar != null) {
                    return true;
                }

                if ((funcKeysPressed.Shift || funcKeysPressed.Ctrl || funcKeysPressed.Alt) && !retInfo) {
                    return true;
                }

                // enter key.
                if (this.GetHideEnter() && k === 13) {
                    return false;
                }

                return retInfo.System;
            };

            MaskControl.prototype.KeyPress = function (text, evt) {
                var k = evt.keyCode || evt.charCode;
                var _conditions = (k === 192) && evt.altKey;

                if (!input.CoreUtility.IsIE() && this.ImeMode) {
                    if (_conditions) {
                        this.ImeInput("ReInput", true);
                        return false;
                    }
                }

                if (!input.CoreUtility.IsIE() && (k === 229 || _conditions)) {
                    return false;
                }

                var inputChar = text;
                var retInfo = this.UIProcess.KeyPressInternal(this.InputElement, this.SelectionStart, this.SelectionEnd, this.GetExitOnLastChar(), inputChar);

                if (this.japInput != true) {
                    if (retInfo.SelectionStart != null) {
                        this.NewSelectionStart = retInfo.SelectionStart;
                    }

                    if (retInfo.SelectionEnd != null) {
                        this.NewSelectionEnd = retInfo.SelectionEnd;
                    }

                    if (retInfo.Text != null) {
                        if (!this.UpdateText(retInfo)) {
                            return false;
                        }

                        this.UpdateDisplayText(this.Text);
                    }

                    var shouldReturn = this._doExtraWorkForKeyPress(text);
                    if (shouldReturn === true) {
                        return;
                    }

                    if (retInfo.SelectionStart != null) {
                        this.SelectionStart = retInfo.SelectionStart;
                    }

                    if (retInfo.SelectionEnd != null) {
                        this.SelectionEnd = retInfo.SelectionEnd;
                        this.SelectionLength = this.GetSelectionLength();
                        if (retInfo.FocusExit != true) {
                            this.SetSelection(this.SelectionStart, this.SelectionEnd);
                        }
                    }
                    if (retInfo.exception != null) {
                        this.UpdateDisplayText(this.Text);
                        this.SetSelection(this.SelectionStart, this.SelectionEnd);
                    }
                    if (retInfo.EventInfo != null) {
                        this.UIProcess.FireEvent(this, retInfo.EventInfo.Name, retInfo.EventInfo.Args, retInfo.EventInfo.Type);
                        if (retInfo.EventInfo.Type === "KeyExit") {
                            this.EventInfo = retInfo.EventInfo;
                            this.FireKeyExit();
                        }

                        this.FocusType = 3 /* ClientEvent */;
                    }
                    if (evt.keyCode === 13) {
                        return true;
                    }
                } else {
                    if (evt.keyCode === 13) {
                        return true;
                    }
                    if (retInfo.SelectionStart != null)
                        this.truePosition = retInfo.SelectionStart;

                    if (retInfo.EventInfo != null) {
                        this.UIProcess.FireEvent(this, retInfo.EventInfo.Name, retInfo.EventInfo.Args, retInfo.EventInfo.Type);
                    }
                }
            };

            MaskControl.prototype._doExtraWorkForKeyPress = function (text) {
                return false;
            };

            MaskControl.prototype.innerKeyPress = function (text, isLoseFocusInput, unUpdate) {
                var inputChar = text;

                isLoseFocusInput = !!isLoseFocusInput;
                var retInfo = this.UIProcess.KeyPressInternal(this.InputElement, this.SelectionStart, this.SelectionEnd, this.GetExitOnLastChar(), inputChar);

                if (this.japInput != true) {
                    if (retInfo.Text != null) {
                        if (!this.UpdateText(retInfo)) {
                            return false;
                        }

                        if (!unUpdate) {
                            this.UpdateDisplayText(this.Text);
                        }
                    }
                    if (retInfo.SelectionStart != null) {
                        this.SelectionStart = retInfo.SelectionStart;
                    }

                    if (retInfo.SelectionEnd != null) {
                        this.SelectionEnd = retInfo.SelectionEnd;
                        this.SelectionLength = this.GetSelectionLength();

                        if (retInfo.FocusExit != true && !isLoseFocusInput && !unUpdate) {
                            if (retInfo.FocusExit != true) {
                                this.SetSelection(this.SelectionStart, this.SelectionEnd);
                            }
                        }
                    }
                    if (retInfo.exception != null) {
                        if (!unUpdate) {
                            this.UpdateDisplayText(this.Text);
                        }
                        if (retInfo.FocusExit != true) {
                            this.SetSelection(this.SelectionStart, this.SelectionEnd);
                        }
                    }
                    if (retInfo.EventInfo != null) {
                        this.UIProcess.FireEvent(this, retInfo.EventInfo.Name, retInfo.EventInfo.Args, retInfo.EventInfo.Type);

                        this.FocusType = 3 /* ClientEvent */;
                    }
                    if (window.event != null && event.keyCode === 13)
                        return true;
                } else {
                    if (window.event != null && event.keyCode === 13)
                        return true;
                    if (retInfo.SelectionStart != null)
                        this.truePosition = retInfo.SelectionStart;

                    if (retInfo.EventInfo != null) {
                        this.UIProcess.FireEvent(this, retInfo.EventInfo.Name, retInfo.EventInfo.Args, retInfo.EventInfo.Type);
                    }
                }
            };

            MaskControl.prototype.KeyUp = function (e) {
                if (this.ImeMode === true && input.CoreUtility.IsIE8OrBelow()) {
                    var k = e.keyCode;

                    var CharEx = input.CharProcess.CharEx;
                    var nowText = this.GetTextboxValue();
                    var inputText = nowText;
                    if (this.SelectionEnd < this.Text.GetLength()) {
                        var lastLength = this.Text.GetLength() - this.SelectionEnd;
                        inputText = nowText.Substring(0, nowText.GetLength() - lastLength);
                    }
                    inputText = inputText.Substring(inputText.GetLength() - 1, inputText.GetLength());

                    if (k === 13) {
                        this.ImeInput("DirectInput");
                    } else if ((k >= 48 && k <= 57) || (k >= 96 && k <= 105)) {
                        if (k >= 96)
                            k = k - 48;

                        inputText = CharEx.ToHalfWidth(inputText);
                        if (inputText != String.fromCharCode(k)) {
                        } else if (inputText === String.fromCharCode(k) && this.ImeSelectTimes < 1) {
                        } else if (this.ImeSelect) {
                        } else {
                            this.ImeInput("ReInput");
                        }
                        this.ImeSelectTimes = 0;
                    } else if (k === 32) {
                        if (this.ImeSelect === false) {
                            if (this.ImeSelectTimes === 1)
                                this.ImeSelect = true;
                            else {
                                if (CharEx.ToHalfWidth(inputText) != String.fromCharCode(k)) {
                                    this.ImeSelectTimes++;
                                } else {
                                    var unconfirmedString = nowText.Substring(this.SelectionStart, nowText.GetLength() - lastLength);
                                    if (CharEx.ToHalfWidth(unconfirmedString) === String.fromCharCode(k)) {
                                        this.ImeInput("DirectInput");
                                    }
                                }
                            }
                        }
                    } else if (k >= 65 && k <= 90) {
                        this.ImeSelectTimes = 0;
                    } else if (k === 32 || k === 106 || k === 107 || k === 109 || k === 110 || k === 111 || k === 219 || k === 220 || k === 221 || k === 222 || (k >= 186 && k <= 192)) {
                        if (this.ImeSelectTimes >= 1) {
                            this.ImeInput("ReInput");
                        }
                        this.ImeSelectTimes = 0;
                    } else if (k === 40 || k === 38) {
                        if (this.ImeSelect === false) {
                            if (this.ImeSelectTimes === 1)
                                this.ImeSelect = true;
                        }
                    } else if (k === 8 || k === 46 || k === 27) {
                        this.ImeSelectTimes = 0;
                    } else if (k === 244) {
                        this.IsJapanConvertKeyPress = true;
                    } else {
                    }
                }

                //else if (!isIE && this.Text != this.UIUpdate.GetText())
                //{
                //    if (e.keyCode === 13)
                //    {
                //        this.ImeInput("DirectInput");
                //        this.ImeSelectTimes = 0;
                //    }
                //}
                //if (e.keyCode === 242)
                //{
                //    this.ImeInput("ReInput", true);
                //}
                if (e.keyCode !== 13) {
                    return false;
                }
            };

            MaskControl.prototype.PerformSpin = function (type) {
                var increment = this.Spin.Increment;
                var isUp = true;

                if (type === "down") {
                    isUp = false;
                }

                this.PerformSpinProcess(this.SelectionStart, this.SelectionEnd, increment, this.Spin.Wrap, isUp, true);

                this.UIUpdate.SetFocus();
                this.SetSelection(this.SelectionStart, this.SelectionEnd);
            };

            MaskControl.prototype.PerformSpinProcess = function (selectionStart, selectionEnd, increment, isWrap, isUp, isButton) {
                if (this.GetReadOnly() && isButton) {
                    return;
                }

                var retInfo = this.UIProcess.PerformSpinInternal(selectionStart, selectionEnd, increment, isWrap, isUp);

                this.FocusType = 6 /* SpinButton */;

                if (!retInfo) {
                    this.UIUpdate.SetFocus();
                    return;
                }

                if (retInfo.Text != null) {
                    if (!this.UpdateText(retInfo)) {
                        return;
                    }
                }

                if (retInfo.SelectionStart != null) {
                    this.SelectionStart = retInfo.SelectionStart;
                }

                if (retInfo.SelectionEnd != null) {
                    this.SelectionEnd = retInfo.SelectionEnd;
                    this.SelectionLength = this.GetSelectionLength();
                }

                if (retInfo.EventInfo) {
                    var focusType = this.UIProcess.FireEvent(this, retInfo.EventInfo.Name, retInfo.EventInfo.Args, retInfo.EventInfo.Type);

                    if (focusType != null) {
                        this.FocusType = focusType;
                    }
                }
                if (this.Text !== this.GetTextboxValue()) {
                    var fieldArray = this.Format.Fields.fieldArray;
                    for (var i = 0; i < fieldArray.length; i++) {
                        if (fieldArray[i].fieldLabel === "EnumField") {
                            break;
                        }
                    }
                    if (i === fieldArray.length) {
                        return;
                    }
                    this.UpdateDisplayText(this.Text);
                }
            };

            MaskControl.prototype.SelectStart = function (selText) {
                if (!this.ImeMode) {
                    _super.prototype.SelectStart.call(this, selText);
                } else {
                    return false;
                }
            };

            MaskControl.prototype.Click = function () {
            };

            MaskControl.prototype.DragDrop = function (text) {
                if (!input.CoreUtility.IsIE() && this.GetReadOnly()) {
                    return false;
                }
                this.IsDragDrop = true;

                this.Paste(text, true, 0, 0);

                return false;
            };

            MaskControl.prototype.DragOver = function () {
            };

            MaskControl.prototype.DragInit = function () {
            };

            MaskControl.prototype.ImeInput = function (operate, reInputType) {
                var newValue = this.UIUpdate.GetText();

                if (newValue === this.Text) {
                    if (window.event) {
                        input.Utility.PreventDefault(window.event);
                    }

                    this.ImeMode = false;

                    return false;
                }
                var imeInputText;
                if (this.Text !== "") {
                    var start = Math.min(this.SelectionStart, this.SelectionEnd);
                    var end = Math.max(this.SelectionStart, this.SelectionEnd);
                    if (end < this.Text.GetLength()) {
                        var lastText = this.Text.Substring(end, this.Text.GetLength());

                        var textIndex = newValue.IndexOf(lastText);
                        if (textIndex !== -1) {
                            imeInputText = newValue.Substring(start, newValue.GetLength() - lastText.GetLength());
                        } else {
                            imeInputText = "";
                        }
                    } else {
                        imeInputText = newValue.Substring(start, newValue.GetLength());
                    }
                } else {
                    imeInputText = newValue;
                }

                if (operate === "ReInput") {
                    if (!reInputType) {
                        imeInputText = imeInputText.Substring(0, imeInputText.GetLength() - 1);
                    } else {
                        imeInputText = imeInputText.Substring(0, imeInputText.GetLength());
                    }
                }

                if (operate === "Record")
                    return imeInputText;

                var LoseFocusInput = false;
                if (operate === "LoseFocusInput") {
                    if (imeInputText === "") {
                        return;
                    }
                    MaskControl.Mask_ImeResponse = true;
                    LoseFocusInput = true;
                }

                for (var i = 0; i < imeInputText.GetLength(); i++) {
                    if (i === imeInputText.GetLength() - 1 && operate === "LoseFocusInput") {
                        this.japInput = true;
                    }

                    MaskControl.Mask_ImeResponse = true;

                    if (imeInputText.GetLength() > i + 1) {
                        var c = imeInputText.Substring(i + 1, i + 2);
                        var _charCategory = new input.CharCategory();
                        var daku = c.charCodeAt(0) - (_charCategory.KATAKANA_VOICED.charCodeAt(0) - 1);
                        if (daku === 1 || daku === 2) {
                            this.innerKeyPress(imeInputText.Substring(i, i + 2), LoseFocusInput);
                            i++;
                        } else {
                            if (operate === "ReInput") {
                                this.innerKeyPress(imeInputText.Substring(i, i + 1), LoseFocusInput, true);
                            } else {
                                this.innerKeyPress(imeInputText.Substring(i, i + 1), LoseFocusInput);
                            }
                        }
                    } else {
                        if (operate === "ReInput") {
                            this.innerKeyPress(imeInputText.Substring(i, i + 1), LoseFocusInput, true);
                        } else {
                            this.innerKeyPress(imeInputText.Substring(i, i + 1), LoseFocusInput);
                        }
                    }
                }

                this.japInput = false;
                this.ImeMode = false;
                this.ImeSelect = false;

                if (operate === "ReInput" || operate === "ClickInput") {
                    this.truePosition = this.SelectionStart;
                    this.FocusType = 8 /* ImeInput */;
                }
            };

            MaskControl.prototype.SetInnerText = function (text) {
                this.Clear();

                if (this.UIProcess.Format.Fields.SetText(text, true).isValid === false) {
                    this.UIProcess.Format.Fields.RollBack();
                } else {
                    this.UIProcess.Format.Fields.SaveOldState();
                }

                var retInfo = {};

                retInfo.Text = this.GetDisplayText("Focus");

                if (!this.UpdateText(retInfo)) {
                    return;
                }
                this.UpdateDisplayText(this.Text);
            };

            MaskControl.prototype.Copy = function () {
                this.SetSelection(this.SelectionStart, this.SelectionEnd);
                _super.prototype.Copy.call(this);
            };

            MaskControl.prototype.Cut = function () {
                this.SetSelection(this.SelectionStart, this.SelectionEnd); //add for bug: 4319
                _super.prototype.Cut.call(this);
            };

            MaskControl.prototype.Paste = function (text, isSetSelectedText, start, end) {
                var pasteText = "";

                if (text != null) {
                    pasteText = text;
                }

                if (!start) {
                    start = this.SelectionStart;
                }

                if (!end) {
                    end = this.SelectionEnd;
                }

                var retInfo = this.UIProcess.Paste(start, end, pasteText, this.GetExitOnLastChar(), isSetSelectedText);

                if (!retInfo) {
                    return false;
                }

                if (retInfo.Value != null) {
                    this.Value = retInfo.Value;
                }

                if (retInfo.Text != null) {
                    if (!this.UpdateText(retInfo)) {
                        return false;
                    }

                    this.UpdateDisplayText(this.Text);

                    if (!input.CoreUtility.IsIE()) {
                        this.SetInnerFocus();
                    }
                }

                if (retInfo.SelectionStart != null) {
                    this.SelectionStart = retInfo.SelectionStart;
                }

                if (retInfo.SelectionEnd != null) {
                    this.SelectionEnd = retInfo.SelectionEnd;
                    this.SelectionLength = Math.abs(this.SelectionEnd - this.SelectionStart);
                }

                if (retInfo && retInfo.FocusExit != null && retInfo.FocusExit) {
                } else {
                    this.SetSelection(this.SelectionStart, this.SelectionEnd);
                }

                if (retInfo.EventInfo) {
                    this.UIProcess.FireEvent(this, retInfo.EventInfo.Name, retInfo.EventInfo.Args, retInfo.EventInfo.Type);
                }
                return true;
            };

            MaskControl.prototype.SetHideValue = function () {
            };

            MaskControl.prototype.GetHideValue = function () {
            };

            MaskControl.prototype.CanUndo = function () {
                if (this.Format.Fields.CanUndo()) {
                    return true;
                } else {
                    return false;
                }
            };

            MaskControl.prototype.DoSpinUp = function (field, increment) {
                if (arguments.length === 1) {
                    increment = field;
                    field = undefined;
                }
                this.DoSpin("up", field, increment);
            };

            MaskControl.prototype.DoSpinDown = function (field, increment) {
                if (arguments.length === 1) {
                    increment = field;
                    field = undefined;
                }
                this.DoSpin("down", field, increment);
            };

            MaskControl.prototype.DoSpin = function (type, field, increment) {
                if ((typeof field === "number" && isNaN(field)) || (typeof increment === "number" && isNaN(increment))) {
                    return;
                }

                var startPos = this.SelectionStart;
                var endPos = this.SelectionEnd;

                var newIncrement = this.Increment;

                if (field != undefined) {
                    field = input.Utility.CheckInt(field, 0, Math.pow(2, 31));
                    var fieldRange = {};
                    fieldRange.start = 0;
                    fieldRange.length = 0;

                    fieldRange = this.Format.Fields.GetRealFieldRange(field);
                    startPos = fieldRange.start;
                    endPos = fieldRange.start + fieldRange.length;
                }

                if (increment != undefined) {
                    newIncrement = increment;
                }
                newIncrement = input.Utility.CheckInt(newIncrement, -Math.pow(2, 31), Math.pow(2, 31));

                if (type === "up") {
                    this.PerformSpinProcess(startPos, endPos, newIncrement, this.Wrap, true, false);
                } else {
                    this.PerformSpinProcess(startPos, endPos, newIncrement, this.Wrap, false, false);
                }
            };

            MaskControl.prototype.UpdateText = function (retInfo) {
                if (!retInfo) {
                    return false;
                }

                var text = "";

                if (retInfo.Text != null) {
                    text = retInfo.Text;
                }

                if (text !== this.Text && this.TextChanging != null && this.TextChanging != "") {
                    var eventInfo = {};
                    var eventArgs = {};

                    eventArgs.Result = text;
                    eventArgs.Cancel = false;

                    eventInfo.Name = this.TextChanging;
                    eventInfo.Args = eventArgs;

                    if (retInfo.SelectionStart != null) {
                        this.NewSelectionStart = retInfo.SelectionStart;
                    }

                    if (retInfo.SelectionEnd != null) {
                        this.NewSelectionEnd = retInfo.SelectionEnd;
                    }

                    var newFieldText = this.UIProcess.GetSepText();
                    this.RollBack();

                    if (typeof (this.NeedSetHideValue) === "undefined") {
                        this.NeedSetHideValue = true;
                    }
                    if (this.NeedSetHideValue) {
                        this.SetHideValue();
                    }

                    if (eventInfo.Name.IndexOf && eventInfo.Name.IndexOf("gcsh_InputManWeb_AjaxServerEventHandler") > -1) {
                        this.UIProcess.Format.Fields.ClearContent();
                        if (this.FormatIsNull) {
                            this.UIProcess.Format.Fields.SetText(newFieldText, true);
                        } else {
                            this.UIProcess.SetSepText(newFieldText);
                        }
                    }
                    var focusType = this.UIProcess.FireEvent(this, eventInfo.Name, eventInfo.Args, "TextChanging");
                    if (eventInfo.Name.IndexOf && eventInfo.Name.IndexOf("gcsh_InputManWeb_AjaxServerEventHandler") > -1) {
                    }

                    if (focusType != null) {
                        this.FocusType = focusType;
                    }

                    if (typeof (this.TextChanging) !== "undefined") {
                        this.NeedSetHideValue = false;
                    }

                    if (eventArgs.Cancel) {
                        this.UpdateDisplayText(this.Text);
                        this.SetSelection(this.SelectionStart, this.SelectionEnd);
                        return false;
                    }

                    this.UIProcess.Format.Fields.ClearContent();

                    if (this.FormatIsNull) {
                        this.UIProcess.Format.Fields.SetText(newFieldText, true);
                    } else {
                        this.UIProcess.SetSepText(newFieldText);
                    }
                }
                this.Text = text;
                this.Value = this.UIProcess.Format.Fields.GetValue();
                return true;
            };

            MaskControl.prototype.UpdateDisplayText = function (text) {
                if (typeof (this.NeedSetHideValue) === "undefined") {
                    this.NeedSetHideValue = true;
                }
                if (this.NeedSetHideValue) {
                    _super.prototype.UpdateDisplayText.call(this, text);

                    if (this.EditingTextChanged) {
                        this.EditingTextChanged.call(this);
                    }
                }
            };

            MaskControl.prototype.RollBack = function () {
                this.UIProcess.Format.Fields.RollBack();
            };

            MaskControl.prototype.ProcessReservedKey = function (k) {
                var retValue = _super.prototype.ProcessReservedKey.call(this, k);

                if (!retValue) {
                    switch (k) {
                        case 118:
                        case 119:
                            return true;
                    }
                } else {
                    return true;
                }

                return false;
            };

            MaskControl.prototype.AddAllEventsHandler = function () {
                _super.prototype.AddAllEventsHandler.call(this);

                var self = this;

                if (input.CoreUtility.IsIE10OrLater()) {
                    $(this.GetInputElement()).bind("MSPointerUp.wijinput", function (evt) {
                        input.GlobalEventHandler.OnMSPointerUp(self, evt);
                    }, false);
                }
            };

            MaskControl.prototype.CompositionStart = function (evt) {
                this.ImeMode = true;
            };

            MaskControl.prototype.CompositionUpdate = function (evt) {
            };

            MaskControl.prototype.CompositionEnd = function (evt) {
                var self = this;
                var iMeHandler = function () {
                    try  {
                        self.ImeInput("DirectInput");
                    } finally {
                        self.ImeMode = false;
                    }
                };

                if (input.CoreUtility.IsIE9OrLater()) {
                    iMeHandler();
                } else {
                    // DaryLuo 2013/05/15 fix bug 382 in IM HTML5.
                    window.setTimeout(iMeHandler, 0);
                }
            };

            MaskControl.prototype.Select = function () {
                if (this.ImeMode) {
                    // When IMe input, doesn't syn selection.
                    return;
                }
                this.SelectionStart = input.Utility.GetSelectionStartPosition(this.GetInputElement());
                this.SelectionEnd = this.SelectionStart + input.Utility.GetSelectionText(this.GetInputElement()).GetLength();
            };

            MaskControl.prototype.MSPointerUp = function (evt) {
                if (evt) {
                    this.MouseUpPointerType = evt.pointerType;
                    this.MouseUpHasValue = (evt.srcElement || evt.target).value.length > 0;
                }
            };

            MaskControl.prototype.Input = function (evt) {
                var _this = this;
                var iMeHandler = function () {
                    try  {
                        _this.ImeInput("DirectInput");
                    } finally {
                        _this.ImeMode = false;
                    }
                };
                setTimeout(iMeHandler, 0);
            };

            MaskControl.prototype.HandleClearButton = function (evt) {
                if (input.CoreUtility.IsIE10OrLater() && this.FocusedWhenMouseDown && this.MouseDownOnClearButton) {
                    if ((evt.srcElement || evt.target) === this.InputElement) {
                        var isFocused = document.activeElement === (evt.srcElement || evt.target);
                        var hitTestResult = input.CoreUtility.IsMouseDownOnClearButton(evt);

                        if (this.MouseUpHasValue && isFocused && hitTestResult) {
                            this.Clear();
                            var text = this.GetText();
                            var thisObj = this;
                            window.setTimeout(function () {
                                thisObj.UpdateDisplayText(text);
                                thisObj.SelectionStart = thisObj.SelectionEnd = thisObj.Format.Fields.GetFirstInputPosition();
                                thisObj.SetSelection(thisObj.SelectionStart, thisObj.SelectionEnd);
                            }, 0);
                        }
                    }
                }
            };

            MaskControl.prototype.HidePromptChar = function () {
                if (this.GetHidePromptOnLeave()) {
                    var value = this.GetInputElement().value;
                    this._textWithPromptChar = value;
                    value = value.replace(new RegExp(this.GetPromptChar(), "g"), " ");
                    this.GetInputElement().value = value;
                }
            };

            MaskControl.prototype.ShowPromptChar = function () {
                if (this._textWithPromptChar !== null) {
                    this.GetInputElement().value = this._textWithPromptChar;
                    this._textWithPromptChar = null;
                }
            };

            MaskControl.prototype.GetHideEnter = function () {
                return this._hideEnter;
            };

            MaskControl.prototype.SetHideEnter = function (hideEnter) {
                this._hideEnter = hideEnter;
            };

            MaskControl.prototype.GetHidePromptOnLeave = function () {
                return this._hidePromptOnLeave;
            };

            MaskControl.prototype.SetHidePromptOnLeave = function (value) {
                if (value !== this._hidePromptOnLeave) {
                    this._hidePromptOnLeave = value;
                    if (value && document.activeElement !== this.GetInputElement()) {
                        this.HidePromptChar();
                    }
                    if (!value && document.activeElement !== this.GetInputElement()) {
                        this.ShowPromptChar();
                    }
                }
            };

            MaskControl.prototype.FireKeyExit = function () {
                if (this.EventInfo != null && this.EventInfo.Type == "KeyExit") {
                    if (this.KeyExit) {
                        this.KeyExit.call(this);
                    }
                    this.FocusType = 4 /* KeyExit */;

                    //end by wuhao for fix bug 419
                    this.EventInfo = null;
                }
            };

            MaskControl.prototype.OnEditStatusChanged = function (callBack) {
                callBack = input.Utility.CheckFunction(callBack);
                this.EditStatusChangedEvent = callBack;
            };

            MaskControl.prototype.OnInvalidInput = function (callBack) {
                callBack = input.Utility.CheckFunction(callBack);
                this.InvalidInputEvent = callBack;
            };

            MaskControl.prototype.OnKeyExit = function (callBack) {
                callBack = input.Utility.CheckFunction(callBack);
                this.KeyExit = callBack;
            };

            MaskControl.prototype.OnSpinDown = function (callBack) {
                callBack = input.Utility.CheckFunction(callBack);
                this.SpinDown = callBack;
            };

            MaskControl.prototype.OnSpinUp = function (callBack) {
                callBack = input.Utility.CheckFunction(callBack);
                this.SpinUp = callBack;
            };

            MaskControl.prototype.OnTextChanged = function (callBack) {
                callBack = input.Utility.CheckFunction(callBack);
                this.TextChanged = callBack;
            };

            MaskControl.prototype.OnTextChanging = function (callBack) {
                callBack = input.Utility.CheckFunction(callBack);
                this.TextChanging = callBack;
            };

            MaskControl.prototype.OnValueChanged = function (callBack) {
                callBack = input.Utility.CheckFunction(callBack);
                this.ValueChanged = callBack;
            };

            MaskControl.prototype.OnMouseDownCallBack = function (callBack) {
                callBack = input.Utility.CheckFunction(callBack);
                this.MouseDownEvent = callBack;
            };

            MaskControl.prototype.OnMouseUpCallBack = function (callBack) {
                callBack = input.Utility.CheckFunction(callBack);
                this.MouseUpEvent = callBack;
            };

            MaskControl.prototype.OnEditingTextChanged = function (callBack) {
                callBack = input.Utility.CheckFunction(callBack);
                this.EditingTextChanged = callBack;
            };

            MaskControl.prototype.IsFocused = function () {
                try  {
                    return document.activeElement === this.GetInputElement();
                } catch (e) {
                    return false;
                }
            };

            MaskControl.prototype.GetTextOnSimpleMode = function () {
                if (!this.IsFocused() && this.Format.Fields.ValueIsNull() && this._getDisplayNullExpression() !== null) {
                    return this.GetTextboxValue();
                }
                var text = this.Format.Fields.GetTextSimpleMode(false);
                var reg = new RegExp("\\" + this.GetPromptChar(), "g");
                text = text.replace(reg, " ");
                return text;
            };

            MaskControl.prototype.GetPostValueOnSimpleMode = function () {
                if (!this.IsFocused() && this.Format.Fields.ValueIsNull() && this._getDisplayNullExpression() !== null) {
                    return this.GetTextboxValue();
                }
                var text = this.Format.Fields.GetTextSimpleMode(true);
                var reg = new RegExp("\\" + this.GetPromptChar(), "g");
                text = text.replace(reg, " ");
                return text;
            };
            MaskControl.Mask_ImeResponse = false;
            return MaskControl;
        })(BaseInputControl);
        input.MaskControl = MaskControl;
    })(wijmo.input || (wijmo.input = {}));
    var input = wijmo.input;
})(wijmo || (wijmo = {}));
;
/// <reference path="jquery.wijmo.wijcharex.ts" />
/// <reference path="jquery.wijmo.wijstringinfo.ts" />
/// <reference path="../wijutil/jquery.wijmo.wijutil.ts"/>
var wijmo;
(function (wijmo) {
    (function (input) {
        /** @ignore */
        (function (wijchartype) {
            wijchartype[wijchartype["editOptional"] = 1] = "editOptional";
            wijchartype[wijchartype["editRequired"] = 2] = "editRequired";
            wijchartype[wijchartype["separator"] = 4] = "separator";
            wijchartype[wijchartype["literal"] = 8] = "literal";
        })(input.wijchartype || (input.wijchartype = {}));
        var wijchartype = input.wijchartype;

        

        /** @ignore */
        var wijMaskedTextProvider = (function () {
            function wijMaskedTextProvider(inputWidget, mask, asciiOnly) {
                this.inputWidget = inputWidget;
                this.mask = mask;
                this.asciiOnly = asciiOnly;
                this.testString = '';
                this.assignedCharCount = 0;
                this.requiredCharCount = 0;
                this.noMask = false;
                this._autoConvertPosition = 0;
                this._needCheckNextChar = false;
                this.descriptors = [];
                this.initialize();
            }
            wijMaskedTextProvider.prototype.initialize = function () {
                this.noMask = (!this.mask || this.mask.length <= 0);
                if (this.noMask) {
                    return;
                }

                this.testString = '';
                this.assignedCharCount = 0;
                this.requiredCharCount = 0;
                this.descriptors = [];
                var caseType = 'none';
                var escape = false;
                var charType = 8 /* literal */;
                var text = '';
                var culture = this.inputWidget._getCulture();
                if (typeof culture === "undefined") {
                    culture = Globalize.findClosestCulture("");
                }

                for (var i = 0; i < this.mask.length; i++) {
                    var needDesc = false;
                    var ch = this.mask.charAt(i);
                    if (escape) {
                        escape = false;
                        needDesc = true;
                    }
                    if (!needDesc) {
                        var ch3 = ch;
                        if (ch3 <= 'C') {
                            switch (ch3) {
                                case '#':
                                case '9':
                                case '?':
                                case 'C':
                                    ch = this.getPromtChar();
                                    charType = 1 /* editOptional */;
                                    needDesc = true;
                                    break;
                                case '$':
                                    text = culture.numberFormat.currency.symbol;
                                    charType = 4 /* separator */;
                                    needDesc = true;
                                    break;
                                case '%':
                                case '-':
                                case ';':
                                case '=':
                                case '@':
                                    charType = 8 /* literal */;
                                    needDesc = true;
                                    break;
                                case '&':
                                case '0':
                                case 'A':
                                    ch = this.getPromtChar();
                                    charType = 2 /* editRequired */;
                                    needDesc = true;
                                    break;
                                case ',':
                                    text = culture.numberFormat[','];
                                    charType = 4 /* separator */;
                                    needDesc = true;
                                    break;
                                case '.':
                                    text = culture.numberFormat['.'];
                                    charType = 4 /* separator */;
                                    needDesc = true;
                                    break;
                                case '/':
                                    text = culture.calendars.standard['/'];
                                    charType = 4 /* separator */;
                                    needDesc = true;
                                    break;
                                case ':':
                                    text = culture.calendars.standard[':'];
                                    charType = 4 /* separator */;
                                    needDesc = true;
                                    break;
                                case '<':
                                    caseType = 'lower';
                                    continue;
                                case '>':
                                    caseType = 'upper';
                                    continue;
                            }
                            if (!needDesc) {
                                charType = 8 /* literal */;
                                needDesc = true;
                            }
                        }
                        if (!needDesc) {
                            if (ch3 <= '\\') {
                                switch (ch3) {
                                    case wijMaskedTextProvider.FK_K:
                                    case wijMaskedTextProvider.FK_H:
                                    case wijMaskedTextProvider.FK_N:
                                    case 'L':
                                        ch = this.getPromtChar();
                                        charType = 2 /* editRequired */;
                                        needDesc = true;
                                        break;
                                    case '\\':
                                        escape = true;
                                        charType = 8 /* literal */;
                                        continue;
                                }
                                if (!needDesc) {
                                    charType = 8 /* literal */;
                                    needDesc = true;
                                }
                            }
                            if (!needDesc) {
                                if (ch3 === 'a') {
                                    ch = this.getPromtChar();
                                    charType = 1 /* editOptional */;
                                    needDesc = true;
                                }

                                switch (ch3) {
                                    case wijMaskedTextProvider.FK_DB_K:
                                    case wijMaskedTextProvider.FK_DB_J:
                                    case wijMaskedTextProvider.FK_DB_9:
                                    case wijMaskedTextProvider.FK_DB_Z:
                                    case wijMaskedTextProvider.FK_DB_N:
                                    case wijMaskedTextProvider.FK_DB_G:
                                    case wijMaskedTextProvider.FK_DB_T:
                                        ch = this.getPromtChar();
                                        charType = 2 /* editRequired */;
                                        needDesc = true;
                                        break;
                                }

                                if (!needDesc) {
                                    if (ch3 !== '|') {
                                        charType = 8 /* literal */;
                                        needDesc = true;
                                    }
                                    if (!needDesc) {
                                        caseType = 'none';
                                        continue;
                                    }
                                }
                            }
                        }
                    }
                    if (needDesc) {
                        var cd = new wijCharDescriptor(i, charType);
                        if (this.isEditDesc(cd)) {
                            cd.caseConversion = caseType;
                        }
                        if (charType !== 4 /* separator */) {
                            text = ch;
                        }
                        for (var j = 0; j < text.length; j++) {
                            this.testString = this.testString + text.charAt(j);
                            this.descriptors[this.descriptors.length] = cd;
                        }
                    }
                }
            };

            wijMaskedTextProvider.prototype.getAllowPromptAsInput = function () {
                return !!this.inputWidget ? this.inputWidget._getAllowPromptAsInput() : false;
            };

            wijMaskedTextProvider.prototype.getPasswordChar = function () {
                var password = !!this.inputWidget ? this.inputWidget._getPasswordChar() : '*';
                if (password === "") {
                    password = "*";
                }
                if (password.length > 1) {
                    return password.charAt(0);
                } else {
                    return password;
                }
            };

            wijMaskedTextProvider.prototype.isPassword = function () {
                return !!this.inputWidget ? this.inputWidget._isPassword() : false;
            };

            wijMaskedTextProvider.prototype.getResetOnPrompt = function () {
                return !!this.inputWidget ? this.inputWidget._getResetOnPrompt() : true;
            };

            wijMaskedTextProvider.prototype.getResetOnSpace = function () {
                return !!this.inputWidget ? this.inputWidget._getResetOnSpace() : true;
            };

            wijMaskedTextProvider.prototype.getSkipLiterals = function () {
                return !!this.inputWidget ? this.inputWidget._getSkipLiterals() : true;
            };

            wijMaskedTextProvider.prototype.getHidePromptOnLeave = function () {
                return !!this.inputWidget ? this.inputWidget._getHidePromptOnLeave() : false;
            };

            wijMaskedTextProvider.prototype._trueOR = function (n1, n2) {
                return (n1 >>> 1 | n2 >>> 1) * 2 + (n1 & 1 | n2 & 1);
            };

            wijMaskedTextProvider.prototype.setValue = function (val) {
                return false;
            };

            wijMaskedTextProvider.prototype.getValue = function () {
                return null;
            };

            wijMaskedTextProvider.prototype.getPromtChar = function () {
                var promptChar = !!this.inputWidget ? this.inputWidget._getPromptChar() : '_';
                if (promptChar === "") {
                    promptChar = "_";
                }
                if (promptChar.length > 1) {
                    return promptChar.charAt(0);
                } else {
                    return promptChar;
                }
            };

            wijMaskedTextProvider.prototype.getAutoConvert = function () {
                return !!this.inputWidget ? this.inputWidget._getAutoConvert() : true;
            };

            wijMaskedTextProvider.prototype.updatePromptChar = function () {
                if (this.noMask) {
                    return;
                }
                for (var i = 0; i < this.descriptors.length; i++) {
                    var cd = this.descriptors[i];
                    if (cd.charType === 1 /* editOptional */ || cd.charType === 2 /* editRequired */) {
                        if (!cd.isAssigned) {
                            this.testString = $.wij.charValidator.setChar(this.testString, this.getPromtChar(), i);
                        }
                    }
                }
            };

            wijMaskedTextProvider.prototype.resetChar = function (pos) {
                var cd = this.descriptors[pos];
                if (this.isEditPos(pos) && cd.isAssigned) {
                    cd.isAssigned = false;
                    this.testString = $.wij.charValidator.setChar(this.testString, this.getPromtChar(), pos);
                    this.assignedCharCount--;
                    if (cd.charType === 2 /* editRequired */) {
                        this.requiredCharCount--;
                    }
                }
            };

            wijMaskedTextProvider.prototype.getAdjustedPos = function (pos) {
                if (this.noMask) {
                    pos = Math.min(pos, this.testString.length - 1);
                } else {
                    if (pos >= this.descriptors.length) {
                        pos--;
                    }
                }

                return Math.max(0, pos);
            };

            wijMaskedTextProvider.prototype.findNonEditPositionInRange = function (start, end, direction) {
                var trueOr = this._trueOR(8 /* literal */, 4 /* separator */);
                return this.findPositionInRange(start, end, direction, trueOr);
            };

            wijMaskedTextProvider.prototype.findPositionInRange = function (start, end, direction, charType) {
                start = Math.max(0, start);
                end = Math.min(end, this.testString.length - 1);

                if (start <= end) {
                    while (start <= end) {
                        var pos = (direction) ? start++ : end--;
                        var cd = this.descriptors[pos];
                        if (((cd.charType & 4294967295) & (charType & 4294967295)) === cd.charType) {
                            return pos;
                        }
                    }
                }
                return -1;
            };

            wijMaskedTextProvider.prototype.findAssignedEditPositionInRange = function (start, end, direction) {
                if (this.assignedCharCount === 0) {
                    return -1;
                }
                return this.findEditPositionInRange(start, end, direction, 2 /* editRequired */);
            };

            wijMaskedTextProvider.prototype.findEditPositionInRange = function (start, end, direction, assignedStatus) {
                do {
                    var trueOr = this._trueOR(2 /* editRequired */, 1 /* editOptional */);
                    var pos = this.findPositionInRange(start, end, direction, trueOr);
                    if (pos === -1) {
                        break;
                    }

                    var cd = this.descriptors[pos];
                    switch (assignedStatus) {
                        case 1 /* editOptional */:
                            if (!cd.isAssigned) {
                                return pos;
                            }
                            break;
                        case 2 /* editRequired */:
                            if (cd.isAssigned) {
                                return pos;
                            }
                            break;
                        default:
                            return pos;
                    }
                    if (direction) {
                        start++;
                    } else {
                        end--;
                    }
                } while(start <= end);

                return -1;
            };

            wijMaskedTextProvider.prototype.findAssignedEditPositionFrom = function (pos, direction) {
                if (!this.assignedCharCount) {
                    return -1;
                }

                var start, end;
                if (direction) {
                    start = pos;
                    end = this.testString.length - 1;
                } else {
                    start = 0;
                    end = pos;
                }
                return this.findAssignedEditPositionInRange(start, end, direction);
            };

            wijMaskedTextProvider.prototype.findEditPositionFrom = function (pos, direction) {
                var start, end;
                if (direction) {
                    start = pos;
                    end = this.testString.length - 1;
                } else {
                    start = 0;
                    end = pos;
                }
                return this.findEditPositionInRange(start, end, direction, 0);
            };

            wijMaskedTextProvider.prototype.setChar = function (strInput, pos, desc) {
                if (this.getAutoConvert()) {
                    var tempResult = new wijmo.input.wijInputResult();
                    var success = this.testInternal(strInput, pos, tempResult);
                    if (!success) {
                        var result = this._convert(strInput, 0);
                        if (strInput.length === 0) {
                            debugger;
                        }
                        strInput = result.strValue.charAt(0);
                        if (result.strValue.length > 1) {
                            this.inputWidget._appendChar = result.strValue.charAt(1);
                        }

                        if (result.index === 2) {
                            this.inputWidget._skipNextChar = true;
                        }
                    }
                }

                pos = Math.max(0, pos);
                if (!desc) {
                    desc = this.descriptors[pos];
                }
                if (this.testEscapeChar(strInput, pos, desc)) {
                    this.resetChar(pos);
                } else {
                    if ($.wij.charValidator.isLetter(strInput)) {
                        if ($.wij.charValidator.isUpper(strInput)) {
                            if (desc.caseConversion === 'lower') {
                                strInput = strInput.toLowerCase();
                            }
                        } else if (desc.caseConversion === 'upper') {
                            strInput = strInput.toUpperCase();
                        }
                    }
                    this.testString = $.wij.charValidator.setChar(this.testString, strInput, pos);
                    if (!desc.isAssigned) {
                        desc.isAssigned = true;
                        this.assignedCharCount++;
                        if (desc.charType === 2 /* editRequired */) {
                            this.requiredCharCount++;
                        }
                    }
                }
            };

            wijMaskedTextProvider.prototype.internalInsertAt = function (strInput, pos, inputResult, testOnly) {
                if (strInput.length === 0) {
                    inputResult.testPosition = pos;
                    inputResult.hint = inputResult.noEffect;
                    return true;
                }

                if (!this._testString(strInput, pos, inputResult)) {
                    return false;
                }

                var editPosition = this.findEditPositionFrom(pos, true);
                var hasAssignedRequiredField = this.findAssignedEditPositionInRange(editPosition, inputResult.testPosition, true) !== -1;

                if (hasAssignedRequiredField && (inputResult.testPosition === (this.testString.length - 1))) {
                    inputResult.hint = inputResult.unavailableEditPosition;
                    inputResult.testPosition = this.testString.length;
                    return false;
                }

                var rightEditablePosition = this.findEditPositionFrom(inputResult.testPosition + 1, true);
                if (hasAssignedRequiredField) {
                    var tempResult = new input.wijInputResult();
                    tempResult.hint = tempResult.unknown;
                    var repeat = true;
                    var lastAssignedReqField = this.findAssignedEditPositionFrom(this.testString.length - 1, false);
                    while (repeat) {
                        repeat = false;
                        if (rightEditablePosition === -1) {
                            inputResult.hint = inputResult.unavailableEditPosition;
                            inputResult.testPosition = this.testString.length;
                            return false;
                        }
                        var testCharResult = this.testChar(this.testString.charAt(editPosition), rightEditablePosition, tempResult);
                        if (this.descriptors[editPosition].isAssigned && !testCharResult) {
                            inputResult.hint = tempResult.hint;
                            inputResult.testPosition = rightEditablePosition;
                            return false;
                        }
                        if (editPosition !== lastAssignedReqField) {
                            editPosition = this.findEditPositionFrom(editPosition + 1, true);
                            rightEditablePosition = this.findEditPositionFrom(rightEditablePosition + 1, true);
                            repeat = true;
                            continue;
                        }
                    }
                    inputResult.hint = Math.max(inputResult.hint, tempResult.hint);
                }
                if (!testOnly) {
                    if (hasAssignedRequiredField) {
                        while (editPosition >= pos) {
                            if (this.descriptors[editPosition].isAssigned) {
                                this.setChar(this.testString.charAt(editPosition), rightEditablePosition);
                            } else {
                                this.resetChar(rightEditablePosition);
                            }
                            rightEditablePosition = this.findEditPositionFrom(rightEditablePosition - 1, false);
                            editPosition = this.findEditPositionFrom(editPosition - 1, false);
                        }
                    }
                    this.setString(strInput, pos);
                }
                return true;
            };

            wijMaskedTextProvider.prototype.insertAt = function (strInput, pos, inputResult) {
                if (typeof inputResult === "undefined") { inputResult = new input.wijInputResult(); }
                if (strInput === undefined) {
                    throw 'InsertAt: input';
                }

                if (this.noMask) {
                    this.testString = this.testString.substring(0, pos) + strInput + this.testString.substring(pos, this.testString.length);
                    inputResult.testPosition = pos + strInput.length - 1;
                    return true;
                }
                if ((pos >= 0) && (pos < this.testString.length)) {
                    return this.internalInsertAt(strInput, pos, inputResult, false);
                }
                inputResult.testPosition = pos;
                inputResult.hint = inputResult.positionOutOfRange;
                return false;
            };

            wijMaskedTextProvider.prototype.clear = function (inputResult) {
                if (this.noMask) {
                    this.testString = '';
                    inputResult.hint = inputResult.success;
                    return;
                }
                if (!this.assignedCharCount) {
                    inputResult.hint = inputResult.noEffect;
                } else {
                    inputResult.hint = inputResult.success;
                    for (var i = 0; i < this.testString.length; i++) {
                        this.resetChar(i);
                    }
                }
            };

            wijMaskedTextProvider.prototype.isLiteral = function (desc) {
                if (!desc) {
                    return false;
                }
                return desc.charType === 8 /* literal */ || desc.charType === 4 /* separator */;
            };

            wijMaskedTextProvider.prototype.testEscapeChar = function (strInput, pos, desc) {
                pos = Math.max(0, pos);
                if (!desc) {
                    desc = this.descriptors[pos];
                }
                if (this.isLiteral(desc)) {
                    if (this.getSkipLiterals()) {
                        return (strInput === this.testString.charAt(pos));
                    }
                    return false;
                }
                var c1 = this.getResetOnPrompt() && strInput === this.getPromtChar();
                var c2 = this.getResetOnSpace() && strInput === ' ';
                return c1 || c2;
            };

            wijMaskedTextProvider.prototype.testChar = function (strInput, pos, rh) {
                var success = this.testInternal(strInput, pos, rh);
                if (!success && this.getAutoConvert()) {
                    this._autoConvertPosition = pos;
                    var result = this._convert(strInput, 0);
                    success = result.strValue.length > 0;

                    if (result.strValue.length > 1) {
                        this.inputWidget._appendChar = result.strValue.charAt(1);
                    }

                    if (result.index === 2) {
                        this.inputWidget._skipNextChar = true;
                    }
                }
                return success;
            };

            wijMaskedTextProvider.prototype.testInternal = function (strInput, pos, rh) {
                if (!$.wij.charValidator.isPrintableChar(strInput)) {
                    rh.hint = rh.invalidInput;
                    return false;
                }
                var cd = this.descriptors[pos];
                if (!cd) {
                    return false;
                }

                if (this.isLiteral(cd)) {
                    if (this.getSkipLiterals() && strInput === this.testString.charAt(pos)) {
                        rh.hint = rh.characterEscaped;
                        return true;
                    }
                    rh.hint = rh.nonEditPosition;
                    return false;
                }
                if (strInput === this.getPromtChar()) {
                    if (this.getResetOnPrompt()) {
                        if (this.isEditDesc(cd) && cd.isAssigned) {
                            rh.hint = rh.sideEffect;
                        } else {
                            rh.hint = rh.characterEscaped;
                        }
                        return true;
                    }
                    if (!this.getAllowPromptAsInput()) {
                        rh.hint = rh.promptCharNotAllowed;
                        return false;
                    }
                }
                if ((strInput === ' ') && this.getResetOnSpace()) {
                    if (this.isEditDesc(cd) && cd.isAssigned) {
                        rh.hint = rh.sideEffect;
                    } else {
                        rh.hint = rh.characterEscaped;
                    }
                    return true;
                }
                switch (this.mask.charAt(cd.maskPosition)) {
                    case 'L':
                        if (!$.wij.charValidator.isLetter(strInput)) {
                            rh.hint = rh.letterExpected;
                            return false;
                        }
                        if (!$.wij.charValidator.isAsciiLetter(strInput) && this.asciiOnly) {
                            rh.hint = rh.asciiCharacterExpected;
                            return false;
                        }
                        break;
                    case '?':
                        if (!$.wij.charValidator.isLetter(strInput) && (strInput !== ' ')) {
                            rh.hint = rh.letterExpected;
                            return false;
                        }
                        if (!$.wij.charValidator.isAsciiLetter(strInput) && this.asciiOnly) {
                            rh.hint = rh.asciiCharacterExpected;
                            return false;
                        }
                        break;
                    case 'A':
                        if (!$.wij.charValidator.isAlphanumeric(strInput)) {
                            rh.hint = rh.alphanumericCharacterExpected;
                            return false;
                        }
                        if (!$.wij.charValidator.isAciiAlphanumeric(strInput) && this.asciiOnly) {
                            rh.hint = rh.asciiCharacterExpected;
                            return false;
                        }
                        break;
                    case 'a':
                        if (!$.wij.charValidator.isAlphanumeric(strInput) && (strInput !== ' ')) {
                            rh.hint = rh.alphanumericCharacterExpected;
                            return false;
                        }
                        if (!$.wij.charValidator.isAciiAlphanumeric(strInput) && this.asciiOnly) {
                            rh.hint = rh.asciiCharacterExpected;
                            return false;
                        }
                        break;
                    case '&':
                        if (!$.wij.charValidator.isAscii(strInput) && this.asciiOnly) {
                            rh.hint = rh.asciiCharacterExpected;
                            return false;
                        }
                        break;
                    case 'C':
                        if ((!$.wij.charValidator.isAscii(strInput) && this.asciiOnly) && (strInput !== ' ')) {
                            rh.hint = rh.asciiCharacterExpected;
                            return false;
                        }
                        break;
                    case '0':
                        if (!$.wij.charValidator.isDigit(strInput)) {
                            rh.hint = rh.digitExpected;
                            return false;
                        }
                        break;
                    case '9':
                        if (!$.wij.charValidator.isDigit(strInput) && (strInput !== ' ')) {
                            rh.hint = rh.digitExpected;
                            return false;
                        }
                        break;
                    case wijMaskedTextProvider.FK_N:
                        if (!input.CharProcess.CharEx.IsFullWidth(strInput) && input.CharProcess.CharEx.IsKatakana(strInput) && !input.CharProcess.CharEx.IsLowerKana(strInput)) {
                        } else {
                            return false;
                        }
                        break;
                    case wijMaskedTextProvider.FK_DB_N:
                        if (input.CharProcess.CharEx.IsFullWidth(strInput) && input.CharProcess.CharEx.IsKatakana(strInput) && !input.CharProcess.CharEx.IsLowerKana(strInput)) {
                        } else {
                            return false;
                        }
                        break;
                    case wijMaskedTextProvider.FK_DB_G:
                        if (input.CharProcess.CharEx.IsUpperKana(strInput) && input.CharProcess.CharEx.IsHiragana(strInput)) {
                        } else {
                            return false;
                        }

                        break;
                    case wijMaskedTextProvider.FK_DB_9:
                        if (strInput >= wijMaskedTextProvider.DBCS_0 && strInput <= wijMaskedTextProvider.DBCS_9) {
                        } else if (strInput === " ") {
                        } else {
                            return false;
                        }
                        break;
                    case '#':
                        if ((!$.wij.charValidator.isDigit(strInput) && (strInput !== '-')) && ((strInput !== '+') && (strInput !== ' '))) {
                            rh.hint = rh.digitExpected;
                            return false;
                        }
                        break;
                    case wijMaskedTextProvider.FK_K:
                        // HarfWidthKatakana
                        if (!input.CharProcess.CharEx.IsFullWidth(strInput) && input.CharProcess.CharEx.IsKatakana(strInput)) {
                        } else {
                            return false;
                        }
                        break;

                    case wijMaskedTextProvider.FK_H:
                        if (input.CharProcess.CharEx.IsFullWidth(strInput)) {
                            return false;
                        }
                        break;
                    case wijMaskedTextProvider.FK_DB_K:
                        if (input.CharProcess.CharEx.IsFullWidth(strInput) && input.CharProcess.CharEx.IsKatakana(strInput)) {
                        } else {
                            return false;
                        }
                        break;
                    case wijMaskedTextProvider.FK_DB_T:
                        if (input.CharProcess.CharEx.IsSurrogate(strInput)) {
                        } else {
                            return false;
                        }
                        break;
                    case wijMaskedTextProvider.FK_DB_J:
                        if (!input.CharProcess.CharEx.IsHiragana(strInput)) {
                            return false;
                        }
                        break;
                    case wijMaskedTextProvider.FK_DB_Z:
                        if (!input.CharProcess.CharEx.IsFullWidth(strInput)) {
                            return false;
                        }
                        break;
                }
                if (strInput === this.testString.charAt(pos) && cd.isAssigned) {
                    rh.hint = rh.noEffect;
                } else {
                    rh.hint = rh.success;
                }
                return true;
            };

            wijMaskedTextProvider.prototype._convert = function (text, index) {
                var retObj = {};
                retObj.success = true;
                retObj.strValue = "";
                retObj.index = index;

                var c = text.Substring(index, index + 1);

                var _isValid;
                var charEx = input.CharProcess.CharEx;

                //if (true) {
                //    var charLength = {};
                //    var result = IVSCharHelper.ConvertedWithIVS(c, 0, charLength);
                //    if (result.length > 0) {
                //        _isValid = this._isValid(result);
                //        if (_isValid) {
                //            index++;
                //            retObj.index = index;
                //            retObj.strValue = result;
                //            return retObj;
                //        }
                //    }
                //}
                // Convert between upper and lower alphabet automatically.
                var include = true;
                if (charEx.IsAlphabet(c)) {
                    var r = charEx.IsLower(c) ? c.toUpperCase() : c.toLowerCase();
                    _isValid = this._isValid(r);
                    if ((_isValid && include) || (!_isValid && !include)) {
                        index++;
                        retObj.index = index;
                        retObj.strValue = r;
                        return retObj;
                        //return new string(r, 1);
                    }

                    c = charEx.IsFullWidth(c) ? charEx.ToHalfWidth(c) : charEx.ToFullWidth(c).text;
                    _isValid = this._isValid(c);
                    if ((_isValid && include) || (!_isValid && !include)) {
                        index++;
                        retObj.index = index;
                        retObj.strValue = c;
                        return retObj;
                        //return new string(c, 1);;
                    }
                    r = charEx.IsFullWidth(r) ? charEx.ToHalfWidth(r) : charEx.ToFullWidth(r).text;
                    _isValid = this._isValid(r);

                    if ((_isValid && include) || (!_isValid && !include)) {
                        index++;
                        retObj.index = index;
                        retObj.strValue = r;
                        return retObj;
                        //return new string(r, 1);;
                    }
                    retObj.success = false;
                    return retObj;
                }

                // Convert from Hiragana to DBCS/SBCS Katakana automatically.
                if (charEx.IsHiragana(c)) {
                    // Large < - > Small
                    if (charEx.IsLowerKana(c)) {
                        var u = charEx.ToUpperKana(c);
                        _isValid = this._isValid(u);
                        if ((_isValid && include) || (!_isValid && !include)) {
                            index++;
                            retObj.index = index;
                            retObj.strValue = u;
                            return retObj;
                        }
                    } else if (charEx.HasLowerKana(c)) {
                        var l = charEx.ToLowerKana(c);
                        _isValid = this._isValid(l);
                        if ((_isValid && include) || (!_isValid && !include)) {
                            index++;
                            retObj.index = index;
                            retObj.strValue = l;
                            return retObj;
                        }
                    }

                    c = charEx.ToKatakana(c);

                    // DaryLuo 2012/05/31 fix bug 116 in IM7. Add this.
                    _isValid = this._isValid(c);
                    if ((_isValid && include) || (!_isValid && !include)) {
                        index++;
                        retObj.index = index;
                        retObj.strValue = c;
                        return retObj;
                        //return new string(c, 1);
                    }

                    if (charEx.IsLowerKana(c)) {
                        var u = charEx.ToUpperKana(c);

                        // DaryLuo 2012/05/31 fix bug 116 in IM7. Add this.
                        _isValid = this._isValid(u);
                        if ((_isValid && include) || (!_isValid && !include)) {
                            index++;
                            retObj.index = index;
                            retObj.strValue = u;
                            return retObj;
                        }
                    } else if (charEx.HasLowerKana(c)) {
                        var l = charEx.ToLowerKana(c);
                        _isValid = this._isValid(l);
                        if ((_isValid && include) || (!_isValid && !include)) {
                            index++;
                            retObj.index = index;
                            retObj.strValue = l;
                            return retObj;
                        }
                    }

                    var chars = charEx.ToHalfWidthEx(c);
                    _isValid = this._isValid(chars);
                    if ((_isValid && include) || (!_isValid && !include)) {
                        index++;
                        retObj.index = index;
                        retObj.strValue = chars;
                        return retObj;
                        //return new string(chars);
                    }

                    if (charEx.IsLowerKana(chars)) {
                        chars = charEx.ToUpperKana(chars);
                        _isValid = this._isValid(chars);
                        if ((_isValid && include) || (!_isValid && !include)) {
                            index++;
                            retObj.index = index;
                            retObj.strValue = chars;
                            return retObj;
                        }
                    } else if (charEx.HasLowerKana(chars)) {
                        chars = charEx.ToLowerKana(chars);
                        _isValid = this._isValid(chars);
                        if ((_isValid && include) || (!_isValid && !include)) {
                            index++;
                            retObj.index = index;
                            retObj.strValue = chars;
                            return retObj;
                        }
                    }

                    retObj.success = false;
                    return retObj;
                }

                // Convert from Katakana to Hiragana (or DBCS <-> SBCS)automatically.
                if (charEx.IsKatakana(c)) {
                    // Large < - > Small
                    if (charEx.IsLowerKana(c)) {
                        var u = charEx.ToUpperKana(c);
                        _isValid = this._isValid(u);
                        if ((_isValid && include) || (!_isValid && !include)) {
                            index++;
                            retObj.index = index;
                            retObj.strValue = u;
                            return retObj;
                        }
                    } else if (charEx.HasLowerKana(c)) {
                        var l = charEx.ToLowerKana(c);
                        _isValid = this._isValid(l);
                        if ((_isValid && include) || (!_isValid && !include)) {
                            index++;
                            retObj.index = index;
                            retObj.strValue = l;
                            return retObj;
                        }
                    }

                    var r = c;
                    var processedAll = false;

                    // Check the soundex character.
                    if (charEx.IsFullWidth(c)) {
                        var newChars = charEx.ToHalfWidthEx(c);

                        if (newChars.GetLength() > 0) {
                            _isValid = this._isValid(newChars);
                            if ((_isValid && include) || (!_isValid && !include)) {
                                index++;
                                retObj.index = index;
                                retObj.strValue = newChars;
                                return retObj;
                                //return new string(newChars);
                            }
                        }

                        if (charEx.IsLowerKana(newChars)) {
                            newChars = charEx.ToUpperKana(newChars);
                            _isValid = this._isValid(newChars);
                            if ((_isValid && include) || (!_isValid && !include)) {
                                index++;
                                retObj.index = index;
                                retObj.strValue = newChars;
                                return retObj;
                            }
                        } else if (charEx.HasLowerKana(newChars)) {
                            newChars = charEx.ToLowerKana(newChars);
                            _isValid = this._isValid(newChars);
                            if ((_isValid && include) || (!_isValid && !include)) {
                                index++;
                                retObj.index = index;
                                retObj.strValue = newChars;
                                return retObj;
                            }
                        }
                    } else {
                        if (index == null) {
                            r = charEx.ToFullWidth(c).text;

                            if (!charEx.IsKatakana(r)) {
                                return retObj;
                            }

                            _isValid = this._isValid(r);
                            if ((_isValid && include) || (!_isValid && !include)) {
                                index++;
                                retObj.index = index;
                                retObj.strValue = r;
                                return retObj;
                            }
                        } else {
                            // To process what??? kyle.wang
                            var nextChar = this.inputWidget._nextChar;
                            if (this._needCheckNextChar && nextChar && nextChar.length > 0) {
                                //r = charEx.ToFullWidthEx(out processedAll, new char[] {c, text[index + 1]});
                                var convertObj = charEx.ToFullWidth(text + nextChar);
                                r = convertObj.text;
                                processedAll = convertObj.processedAll;
                            } else {
                                r = charEx.ToFullWidth(c).text;
                            }

                            if (!charEx.IsKatakana(r)) {
                                return retObj;
                            }

                            _isValid = this._isValid(r);
                            if ((_isValid && include) || (!_isValid && !include)) {
                                index++;
                                if (processedAll) {
                                    index++;
                                }

                                retObj.index = index;
                                retObj.strValue = r;
                                return retObj;
                                //return new string(r, 1);
                            }
                        }

                        if (charEx.IsLowerKana(r)) {
                            var u = charEx.ToUpperKana(r);
                            _isValid = this._isValid(u);
                            if ((_isValid && include) || (!_isValid && !include)) {
                                index++;
                                retObj.index = index;
                                retObj.strValue = u;
                                return retObj;
                            }
                        } else if (charEx.HasLowerKana(r)) {
                            var l = charEx.ToLowerKana(r);
                            _isValid = this._isValid(l);
                            if ((_isValid && include) || (!_isValid && !include)) {
                                index++;
                                retObj.index = index;
                                retObj.strValue = l;
                                return retObj;
                            }
                        }
                    }

                    r = charEx.ToHiragana(r);
                    _isValid = this._isValid(r);
                    if ((_isValid && include) || (!_isValid && !include)) {
                        index++;
                        if (processedAll) {
                            index++;
                        }

                        retObj.index = index;
                        retObj.strValue = r;

                        //add by sj for bug 2955
                        if (r == '\u3094') {
                            if (processedAll) {
                                retObj.strValue = '\u3046' + '\u309B';
                            } else {
                                index--;
                                retObj.index = index;
                                retObj.strValue = "";
                                retObj.success = false;
                            }
                        }

                        //end by sj
                        return retObj;
                    }

                    if (charEx.IsLowerKana(r)) {
                        var u = charEx.ToUpperKana(r);
                        _isValid = this._isValid(u);
                        if ((_isValid && include) || (!_isValid && !include)) {
                            index++;
                            retObj.index = index;
                            retObj.strValue = u;
                            return retObj;
                        }
                    } else if (charEx.HasLowerKana(r)) {
                        var l = charEx.ToLowerKana(r);
                        _isValid = this._isValid(l);
                        if ((_isValid && include) || (!_isValid && !include)) {
                            index++;
                            retObj.index = index;
                            retObj.strValue = l;
                            return retObj;
                        }
                    }
                    //return new string(r, 1);;
                }

                // Convert between DBCS and SBCS automatically.
                c = charEx.IsFullWidth(c) ? charEx.ToHalfWidth(c) : charEx.ToFullWidth(c).text;
                _isValid = this._isValid(c);
                if ((_isValid && include) || (!_isValid && !include)) {
                    index++;
                    retObj.index = index;
                    retObj.strValue = c;
                    return retObj;
                    //return new string(c, 1);
                }

                retObj.success = false;
                return retObj;
            };

            wijMaskedTextProvider.prototype._isValid = function (text) {
                var inputText = new wijmo.input.wijInputResult();
                return this.testInternal(text, this._autoConvertPosition, inputText);
            };

            wijMaskedTextProvider.prototype._testString = function (strInput, pos, result) {
                result.hint = result.unknown;
                result.testPosition = pos;

                if (strInput.length) {
                    var tempResult = new input.wijInputResult();
                    tempResult.testPosition = result.testPosition;
                    tempResult.hint = result.hint;

                    for (var i = 0; i < strInput.length; i++) {
                        if (result.testPosition > this.testString.length) {
                            result.hint = result.unavailableEditPosition;
                            return false;
                        }
                        var ch = strInput.charAt(i);
                        if (!this.testEscapeChar(ch, result.testPosition)) {
                            result.testPosition = this.findEditPositionFrom(result.testPosition, true);
                            if (result.testPosition === -1) {
                                result.testPosition = this.testString.length;
                                result.hint = result.unavailableEditPosition;
                                return false;
                            }
                        }
                        this._needCheckNextChar = true;
                        if (!this.inputWidget._batchKeyPress) {
                            this.inputWidget._nextChar = i === strInput.length - 1 ? "" : strInput.charAt(i + 1);
                        }

                        if (!this.testChar(ch, result.testPosition, tempResult)) {
                            result.hint = tempResult.hint;
                            this._needCheckNextChar = false;
                            if (!this.inputWidget._batchKeyPress) {
                                this.inputWidget._nextChar = "";
                            }
                            return false;
                        }
                        this._needCheckNextChar = false;

                        if (!this.inputWidget._batchKeyPress) {
                            this.inputWidget._nextChar = "";

                            var appendChar = this.inputWidget._appendChar;
                            if (appendChar && appendChar.length > 0) {
                                this.inputWidget._appendChar = "";
                                result.testPosition++;
                                if (!this.testChar(appendChar, result.testPosition, tempResult)) {
                                    result.hint = tempResult.hint;
                                    this._needCheckNextChar = false;

                                    return false;
                                }
                            }
                            if (this.inputWidget._skipNextChar) {
                                i++;
                                this.inputWidget._skipNextChar = false;
                            }
                        }

                        result.hint = Math.max(tempResult.hint, result.hint);

                        result.testPosition++;

                        if (result.testPosition === this.testString.length) {
                            break;
                        }
                    }
                    result.testPosition--;
                }
                return true;
            };

            wijMaskedTextProvider.prototype.setText = function (strInput, inputResult) {
                if (typeof inputResult === "undefined") { inputResult = new input.wijInputResult(); }
                if (strInput === undefined) {
                    throw 'SetFromPos: input parameter is null or undefined.';
                }

                inputResult.hint = inputResult.unknown;
                inputResult.testPosition = 0;
                if (!strInput.length) {
                    this.clear(inputResult);
                    return true;
                }
                if (this.noMask) {
                    this.testString = strInput;
                    return true;
                }
                if (!this.testSetString(strInput, inputResult.testPosition, inputResult)) {
                    return false;
                }
                var rightEditPosition = this.findAssignedEditPositionFrom(inputResult.testPosition + 1, true);
                if (rightEditPosition !== -1) {
                    this.resetString(rightEditPosition, this.testString.length - 1);
                }
                return true;
            };

            wijMaskedTextProvider.prototype.resetString = function (start, end) {
                if (this.noMask) {
                    this.testString = '';
                    return;
                }
                start = this.findAssignedEditPositionFrom(start, true);
                if (start !== -1) {
                    end = this.findAssignedEditPositionFrom(end, false);
                    while (start <= end) {
                        start = this.findAssignedEditPositionFrom(start, true);
                        this.resetChar(start);
                        start++;
                    }
                }
            };

            wijMaskedTextProvider.prototype.setString = function (strInput, pos) {
                for (var i = 0; i < strInput.length; i++) {
                    var ch = strInput.charAt(i);
                    if (!this.testEscapeChar(ch, pos)) {
                        pos = this.findEditPositionFrom(pos, true);
                    }

                    if (pos < 0 || pos >= this.testString.length) {
                        return;
                    }
                    if (!this.inputWidget._batchKeyPress) {
                        this.inputWidget._nextChar = i === strInput.length - 1 ? "" : strInput.charAt(i + 1);
                    }
                    this._needCheckNextChar = true;
                    this.setChar(ch, pos);
                    pos++;
                    this._needCheckNextChar = false;
                    if (!this.inputWidget._batchKeyPress) {
                        this.inputWidget._nextChar = "";

                        var appendChar = this.inputWidget._appendChar;
                        if (appendChar && appendChar.length > 0) {
                            this.inputWidget._appendChar = "";
                            this.inputWidget._nextChar = "";
                            if (!this.testEscapeChar(appendChar, pos)) {
                                pos = this.findEditPositionFrom(pos, true);
                            }
                            this.setChar(appendChar, pos);
                            pos++;
                        }
                        if (this.inputWidget._skipNextChar) {
                            i++;
                            this.inputWidget._skipNextChar = false;
                        }
                    }
                }
            };

            wijMaskedTextProvider.prototype.testSetString = function (inputText, pos, inputResult) {
                if (inputText.length > this.testString.length) {
                    inputText = inputText.substring(0, this.testString.length);
                }

                if (this._testString(inputText, pos, inputResult)) {
                    this.setString(inputText, pos);
                    return true;
                }
                return false;
            };

            wijMaskedTextProvider.prototype.isAllDecriptorUnAssigned = function () {
                for (var i = 0; i < this.testString.length; i++) {
                    var cd = this.descriptors[i];
                    if (cd && (cd.charType === 1 /* editOptional */ || cd.charType === 2 /* editRequired */)) {
                        if (cd.isAssigned) {
                            return false;
                        }
                    }
                }
                return true;
            };

            wijMaskedTextProvider.prototype.toString = function (ignorePasswordChar, includePrompt, includeLiterals, start, len) {
                var c1 = this.inputWidget._showNullText();
                var c2 = !this.inputWidget.isFocused();
                var c3 = this.isAllDecriptorUnAssigned();

                if (c1 && c2 && c3) {
                    return this.inputWidget._getNullText();
                }

                ignorePasswordChar = (ignorePasswordChar === undefined) ? !this.isPassword() : ignorePasswordChar;
                var temp1 = this.getHidePromptOnLeave() ? this.inputWidget.isFocused() : true;

                includePrompt = (includePrompt === undefined) ? temp1 : includePrompt;
                includeLiterals = (includeLiterals === undefined) ? true : includeLiterals;

                if (this.noMask) {
                    if (!ignorePasswordChar) {
                        var s = '';
                        for (var i = 0; i < this.testString.length; i++) {
                            s += this.getPasswordChar();
                        }
                        return s;
                    }
                    return this.testString;
                }

                start = (start === undefined) ? 0 : start;
                len = (len === undefined) ? this.testString.length : len;

                if (len <= 0) {
                    return '';
                }
                start = Math.max(0, start);

                if (start >= this.testString.length) {
                    return '';
                }
                var num1 = this.testString.length - start;
                len = Math.min(len, num1);

                c1 = !this.isPassword() || ignorePasswordChar;
                c2 = includePrompt && includeLiterals;

                if (c1 && c2) {
                    return this.testString.substring(start, len - start);
                }
                var builder1 = '';
                var num2 = (start + len) - 1;
                for (var num5 = start; num5 <= num2; num5++) {
                    var ch = this.testString.charAt(num5);
                    var cd = this.descriptors[num5];
                    switch (cd.charType) {
                        case 1 /* editOptional */:
                        case 2 /* editRequired */:
                            if (!cd.isAssigned) {
                                break;
                            }
                            if (!this.isPassword() || ignorePasswordChar) {
                                builder1 = builder1 + ch;
                                continue;
                            }
                            builder1 = builder1 + this.getPasswordChar();
                            continue;
                        case (2 /* editRequired */ | 1 /* editOptional */):
                            builder1 = builder1 + ch;
                            continue;
                        case 4 /* separator */:
                        case 8 /* literal */:
                            if (!includeLiterals) {
                                continue;
                            }
                            builder1 = builder1 + ch;
                            continue;
                        default:
                            builder1 = builder1 + ch;
                            continue;
                    }
                    if (includePrompt) {
                        builder1 = builder1 + ch;
                        continue;
                    }
                    builder1 = builder1 + ' ';
                    continue;
                }

                return builder1;
            };

            wijMaskedTextProvider.prototype.isEditDesc = function (desc) {
                if (this.noMask) {
                    return true;
                }

                return desc.charType === 2 /* editRequired */ || desc.charType === 1 /* editOptional */;
            };

            wijMaskedTextProvider.prototype.isEditPos = function (pos) {
                if (this.noMask) {
                    return true;
                }
                if (pos < 0 || pos >= this.testString.length) {
                    return false;
                }

                var cd = this.descriptors[pos];
                return this.isEditDesc(cd);
            };

            wijMaskedTextProvider.prototype.internalRemoveAt = function (start, end, inputResult, testOnly) {
                if (typeof testOnly === "undefined") { testOnly = false; }
                if (this.noMask) {
                    try  {
                        this.testString = this.testString.substring(0, start) + this.testString.substring(end + 1, this.testString.length);
                        inputResult.testPosition = start;
                    } catch (e) {
                    }
                    return true;
                }

                var num1 = this.findAssignedEditPositionFrom(this.testString.length - 1, false);
                var i = this.findEditPositionInRange(start, end, true, 0);

                inputResult.hint = inputResult.noEffect;
                if ((i === -1) || (i > num1)) {
                    inputResult.testPosition = start;
                    return true;
                }
                inputResult.testPosition = start;
                if (this.findAssignedEditPositionInRange(start, end, true) !== -1) {
                    inputResult.hint = inputResult.success;
                }
                if (end < num1) {
                    var num3 = this.findEditPositionFrom(end + 1, true);
                    var num4 = num3;
                    start = i;
                    var repeat = true;
                    var tempInputResult = new input.wijInputResult();
                    while (repeat) {
                        repeat = false;
                        var ch = this.testString.charAt(num3);
                        var cd = this.descriptors[num3];

                        var c1 = (ch !== this.getPromtChar()) || cd.isAssigned;
                        var c2 = !this.testChar(ch, i, tempInputResult);

                        if (c1 && c2) {
                            inputResult.hint = tempInputResult.hint;
                            inputResult.testPosition = i;
                            return false;
                        }
                        if (num3 !== num1) {
                            num3 = this.findEditPositionFrom(num3 + 1, true);
                            i = this.findEditPositionFrom(i + 1, true);
                            repeat = true;
                            continue;
                        }
                    }
                    if (inputResult.sideEffect > inputResult.hint) {
                        inputResult.hint = inputResult.sideEffect;
                    }
                    if (testOnly) {
                        return true;
                    }
                    num3 = num4;
                    i = start;
                    repeat = true;
                    while (repeat) {
                        repeat = false;
                        var ch2 = this.testString.charAt(num3);
                        var descriptor2 = this.descriptors[num3];
                        if ((ch2 === this.getPromtChar()) && !descriptor2.isAssigned) {
                            this.resetChar(i);
                        } else {
                            this.setChar(ch2, i);
                            this.resetChar(num3);
                        }
                        if (num3 !== num1) {
                            num3 = this.findEditPositionFrom(num3 + 1, true);
                            i = this.findEditPositionFrom(i + 1, true);
                            repeat = true;
                            continue;
                        }
                    }
                    start = i + 1;
                }
                if (start <= end) {
                    this.resetString(start, end);
                }
                return true;
            };

            wijMaskedTextProvider.prototype.removeAt = function (start, end, inputResult, skipCheck) {
                if (typeof end === "undefined") { end = start; }
                if (typeof inputResult === "undefined") { inputResult = new input.wijInputResult(); }
                if (end >= this.testString.length) {
                    inputResult.testPosition = end;
                    inputResult.hint = inputResult.positionOutOfRange;
                    return false;
                }
                if ((start >= 0) && (start <= end)) {
                    return this.internalRemoveAt(start, end, inputResult, false);
                }
                inputResult.testPosition = start;
                inputResult.hint = inputResult.positionOutOfRange;
                return false;
            };

            wijMaskedTextProvider.prototype._isLastCharAssigned = function () {
                var lastPosistion = this.findEditPositionFrom(this.testString.length, false);
                if (lastPosistion >= 0 && lastPosistion < this.testString.length) {
                    return this.descriptors[lastPosistion].isAssigned;
                }
                return false;
            };

            wijMaskedTextProvider.prototype._getFieldList = function () {
                var editPositionList = [];

                var position = this.findEditPositionFrom(0, true);
                while (position >= 0 && position < this.testString.length) {
                    editPositionList.push(position);
                    position = this.findEditPositionFrom(position + 1, true);
                }

                var rangeList = [];
                if (editPositionList.length > 0) {
                    var previousEditPos = editPositionList[0];
                    var currentIndex = 1;
                    var startPos = previousEditPos;
                    while (currentIndex < editPositionList.length) {
                        if (editPositionList[currentIndex] - previousEditPos == 1) {
                        } else {
                            rangeList.push({ start: startPos, end: previousEditPos });
                            startPos = editPositionList[currentIndex];
                        }
                        previousEditPos = editPositionList[currentIndex];
                        currentIndex++;
                    }
                    rangeList.push({ start: startPos, end: previousEditPos });
                }

                return rangeList;
            };

            wijMaskedTextProvider.prototype.replaceWith = function (range, text) {
                var index = range.start;
                var result = new input.wijInputResult();
                if (range.start < range.end) {
                    this.removeAt(range.start, range.end - 1, result, true);
                    index = result.testPosition;
                }
                return this.insertAt(text, index, result) ? result : null;
            };
            wijMaskedTextProvider.FK_K = "K";
            wijMaskedTextProvider.FK_H = "H";
            wijMaskedTextProvider.FK_DB_9 = "\uff19";
            wijMaskedTextProvider.FK_N = "N";
            wijMaskedTextProvider.FK_DB_N = "\uff2e";
            wijMaskedTextProvider.FK_DB_G = "\uff27";

            wijMaskedTextProvider.FK_DB_K = "\uff2b";
            wijMaskedTextProvider.FK_DB_J = "\uff2a";
            wijMaskedTextProvider.FK_DB_Z = "\uff3a";
            wijMaskedTextProvider.FK_DB_T = "\uff34";

            wijMaskedTextProvider.DBCS_0 = "\uff10";
            wijMaskedTextProvider.DBCS_9 = "\uff19";

            wijMaskedTextProvider.DBCS_A = "\uff21";
            wijMaskedTextProvider.DBCS_a = "\uff41";

            wijMaskedTextProvider.DBCS_Z = "\uff3a";
            wijMaskedTextProvider.DBCS_z = "\uff5a";
            return wijMaskedTextProvider;
        })();
        input.wijMaskedTextProvider = wijMaskedTextProvider;

        ////////////////////////////////////////////////////////////////////////////////
        // wijCharDescriptor
        /** @ignore */
        var wijCharDescriptor = (function () {
            function wijCharDescriptor(maskPos, charType) {
                this.maskPos = maskPos;
                this.charType = charType;
                this.caseConversion = 'none';
                this.isAssigned = false;
                this.maskPosition = 0;
                this.maskPosition = maskPos;
                this.charType = charType;
            }
            return wijCharDescriptor;
        })();
        input.wijCharDescriptor = wijCharDescriptor;

        /** @ignore */
        var MaskStub = (function () {
            function MaskStub(maskOptions) {
                this._imaskOptions = maskOptions;
            }
            MaskStub.prototype._getCulture = function () {
                return Globalize.findClosestCulture(this._imaskOptions.culture);
            };
            MaskStub.prototype._getAllowPromptAsInput = function () {
                return false;
            };
            MaskStub.prototype._getPasswordChar = function () {
                return "";
            };

            MaskStub.prototype._getResetOnPrompt = function () {
                return true;
            };
            MaskStub.prototype._getResetOnSpace = function () {
                return true;
            };
            MaskStub.prototype._getSkipLiterals = function () {
                return true;
            };
            MaskStub.prototype._getHidePromptOnLeave = function () {
                return false;
            };
            MaskStub.prototype._getPromptChar = function () {
                return "_";
            };
            MaskStub.prototype._getAutoConvert = function () {
                return this._imaskOptions.autoConvert;
            };
            MaskStub.prototype._getNullText = function () {
                return "";
            };

            //element: JQuery;
            MaskStub.prototype._isPassword = function () {
                return false;
            };
            MaskStub.prototype._showNullText = function () {
                return false;
            };
            MaskStub.prototype.isFocused = function () {
                return false;
            };
            return MaskStub;
        })();
        input.MaskStub = MaskStub;
    })(wijmo.input || (wijmo.input = {}));
    var input = wijmo.input;
})(wijmo || (wijmo = {}));
$.wijinputcore = $.wijinputcore || {};
;
$.wijinputcore.formatmask = $.wijinputcore.formatmask || function (val, formatOrType, opt) {
    var option = (opt || {});
    if (option.autoConvert !== false) {
        option.autoConvert = true;
    }
    option.culture = "";
    var maskStub = new wijmo.input.MaskStub(option);
    var provider = new wijmo.input.wijMaskedTextProvider(maskStub, formatOrType, false);
    var result = provider.setText(val);
    if (result) {
        return provider.toString(true, true, true);
    } else {
        return provider.toString(true, false, false);
    }
};

$.wijinputcore.validateMask = function (value, format) {
    var option = { autoConvert: false };
    option.culture = "";
    var maskStub = new wijmo.input.MaskStub(option);
    var provider = new wijmo.input.wijMaskedTextProvider(maskStub, format, false);
    provider.setText(value);
    var formatString = provider.toString(true, true, true);
    return formatString === value;
};
;
/// <reference path="jquery.wijmo.wijstringinfo.ts"/>
/// <reference path="jquery.wijmo.wijinputcore.ts"/>
/// <reference path="jquery.wijmo.wijinpututility.ts"/>
/// <reference path="jquery.wijmo.wijinputmaskcore.ts"/>
/// <reference path="jquery.wijmo.wijinputmaskformat.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*globals wijinputcore wijMaskedTextProvider wijCharDescriptor wijInputResult jQuery*/
    /*
    * Depends:
    *	jquery-1.4.2.js
    *	jquery.ui.core.js
    *	jquery.ui.widget.js
    *	jquery.ui.position.js
    *	jquery.effects.core.js
    *	jquery.effects.blind.js
    *	globalize.js
    *	jquery.wijmo.wijpopup.js
    *	jquery.wijmo.wijcharex.js
    *	jquery.wijmo.wijstringinfo.js
    *	jquery.wijmo.wijinputcore.js
    *  jquery.wijmo.wijinputmaskcore.js
    *  jquery.wijmo.wijinputmaskformat.js
    *
    */
    (function (_input) {
        var $ = jQuery;

        //#region wijinputMask
        /** @widget */
        var wijinputmask = (function (_super) {
            __extends(wijinputmask, _super);
            function wijinputmask() {
                _super.apply(this, arguments);
                this._imMask = null;
                this._advanceMode = false;
            }
            wijinputmask.prototype._createTextProvider = function () {
                this._textProvider = new _input.wijMaskedTextProvider(this, this.options.mask, false);
            };

            wijinputmask.prototype._checkMaskAndPassword = function () {
                var noMask = !this.options.mask || this.options.mask.length < 0;
                if (noMask && this._isPassword()) {
                    throw 'Option "passwordChar" requires a mask';
                }
            };

            wijinputmask.prototype._updateIsPassword = function () {
                var isPassword = this.options.passwordChar.length > 0 && this.element.attr('type') !== 'password';
                this.element.data('isPassword', isPassword);
                this._checkMaskAndPassword();
            };

            wijinputmask.prototype._beginUpdate = function () {
                var element = this.element;
                element.addClass(this.options.wijCSS.wijinputmask);
                element.attribute("aria-label", "wijinputmask");
                this._updateIsPassword();
                element.data('defaultText', this.options.text);
            };

            wijinputmask.prototype._setOption = function (key, value) {
                switch (key) {
                    case "maskFormat":
                        this._super(key, value);
                        key = "mask";
                        break;
                }

                _super.prototype._setOption.call(this, key, value);

                if (this._advanceMode) {
                    if (wijinputmask._imMaskAssociatedoptions.indexOf) {
                        if (wijinputmask._imMaskAssociatedoptions.indexOf(key) !== -1) {
                            this._syncProperties();
                        }
                    } else {
                        for (var i = 0; i < wijinputmask._imMaskAssociatedoptions.length; i++) {
                            if (wijinputmask._imMaskAssociatedoptions[i] === key) {
                                this._syncProperties();
                                break;
                            }
                        }
                    }
                }

                switch (key) {
                    case 'text':
                        if (this._advanceMode && this.options.textWithPromptAndLiterals) {
                            value = this.options.textWithPromptAndLiterals;
                        }
                        this.setText(value);
                        break;

                    case 'mask':
                    case 'culture':
                        if (typeof (value) === 'undefined' || value.length <= 0) {
                            value = "";
                        }
                        this._checkMaskAndPassword();
                        var text = this.getText();
                        if (text === this._getNullText()) {
                            text = "";
                        }
                        if (key === "mask") {
                            if (!this._isAdvanceMode() && value instanceof RegExp) {
                                return;
                            }
                            this._textProvider.mask = value;
                        }
                        this._checkFormatPattern(value);
                        if (this._advanceMode) {
                            this._imMask.SetText(text);
                            this._updateText();
                        } else {
                            this._textProvider.initialize();
                            this._textProvider.setText(text);
                            this._updateText();
                        }

                        break;
                    case 'promptChar':
                    case 'nullText':
                        if (this._textProvider) {
                            this._textProvider.updatePromptChar();
                            this._updateText();
                        }

                        break;
                    case 'hidePromptOnLeave':
                    case 'resetOnPrompt':
                        this._updateText();
                        break;
                    case 'passwordChar':
                        this._updateIsPassword();
                        this._updateText();
                        break;
                }
            };

            wijinputmask.prototype._isAdvanceMode = function () {
                return typeof (_input.MaskControl) !== "undefined";
            };

            wijinputmask.prototype._checkFormatPattern = function (value) {
                if (value instanceof RegExp || this.options.formatMode === "advanced") {
                    if (!this._advanceMode) {
                        this._detachInputEvent();
                        if (!this._imMask) {
                            this._imMask = new _input.MaskControl();
                            this._addimMaskCustomEvent();
                        }
                        this._imMask.AttachInput(this.element.get(0));
                        this._attachKeyEventForDropDownList();

                        this._advanceMode = true;
                    }
                    if (value instanceof RegExp) {
                        var reg = value;
                        this._imMask.SetFormatPattern(reg.source);
                    } else {
                        this._imMask.SetFormatPattern(value);
                    }
                    this._syncProperties();
                } else {
                    if (this._advanceMode) {
                        this._imMask.DetachInput();
                        this._detachEventForDropDownList();
                        _super.prototype._attachInputEvent.call(this);
                    }
                    this._advanceMode = false;
                }
            };

            wijinputmask.prototype._attachKeyEventForDropDownList = function () {
                this.element.bind({
                    'keydown.wijinput': $.proxy(this._onKeyDownForDropDownList, this)
                });
            };

            wijinputmask.prototype._detachEventForDropDownList = function () {
                this.element.unbind(".wijinput");
            };

            wijinputmask.prototype._onKeyDownForDropDownList = function (e) {
                _super.prototype._processKeyForDropDownList.call(this, e);
            };

            wijinputmask.prototype._syncProperties = function () {
                this._imMask.SetEnabled(!this._isDisabled());
                this._imMask.SetReadOnly(!!this.options.disableUserInput);
                this._imMask.SetExitOnLastChar(!!this.options.blurOnLastChar);
                this._imMask.SetImeMode(this.options.imeMode);
                this._imMask.SetExitOnLeftRightKey(this._convertExistOnLeftRightKey(this.options.blurOnLeftRightKey));
                this._imMask.SetTabAction(this._convertTabAction(this.options.tabAction));
                this._imMask.SetDisplayNull(this.options.nullText);

                this._imMask.SetHideEnter(!!this.options.hideEnter);

                this._imMask.SetPromptChar(this.options.promptChar);
                this._imMask.SetAutoConvert(!!this.options.autoConvert);
                this._imMask.SetHidePromptOnLeave(!!this.options.hidePromptOnLeave);
                this._imMask.SetHighlightText(this._convertHighlightText(this.options.highlightText));
            };
            wijinputmask.prototype._convertExistOnLeftRightKey = function (str) {
                if (!str) {
                    str = "none";
                }
                str = str.toLowerCase();
                if (str === "none") {
                    return 0 /* None */;
                } else if (str === "left") {
                    return 1 /* Left */;
                } else if (str === "right") {
                    return 2 /* Right */;
                } else if (str === "both") {
                    return 3 /* Both */;
                }
            };

            wijinputmask.prototype._convertHighlightText = function (str) {
                if (!str) {
                    return 0 /* None */;
                }

                str = str.toLowerCase();
                if (str === "field") {
                    return 1 /* Field */;
                } else if (str === "all") {
                    return 2 /* All */;
                } else {
                    return 0 /* None */;
                }
            };

            wijinputmask.prototype._convertTabAction = function (str) {
                if (!str) {
                    str = "control";
                }
                str = str.toLowerCase();
                if (str === "control") {
                    return 0 /* Control */;
                } else {
                    return 1 /* Field */;
                }
            };

            wijinputmask.prototype._addimMaskCustomEvent = function () {
                var _this = this;
                this._imMask.OnInvalidInput(function (e) {
                    _this._fireIvalidInputEvent("");
                });
                this._imMask.OnTextChanged(function (e) {
                    _this._raiseTextChanged();
                });
                this._imMask.OnEditingTextChanged(function (e) {
                    _this._updateText(true);
                });
                this._imMask.OnKeyExit(function (e) {
                    _this._trigger("keyExit");
                });
            };

            wijinputmask.prototype._processClearButton = function () {
                this._textProvider.clear(new _input.wijInputResult());
                this._updateText();
                var firstEditPosition = this._textProvider.findEditPositionFrom(0, true);
                this.selectText(firstEditPosition, firstEditPosition);
            };

            wijinputmask.prototype._resetData = function () {
                var txt = this.element.data('defaultText');
                if (txt === undefined || txt === null) {
                    txt = this.element.data('elementValue');
                }

                if (txt === undefined || txt === null) {
                    txt = "";
                }

                this.setText(txt);
            };

            wijinputmask.prototype._isPassword = function () {
                return !!this.element.data('isPassword');
            };

            wijinputmask.prototype._getTextWithPrompts = function () {
                return !this._isInitialized() ? this.element.val() : this._textProvider.toString(true, true, false);
            };

            wijinputmask.prototype._getTextWithLiterals = function () {
                return !this._isInitialized() ? this.element.val() : this._textProvider.toString(true, false, true);
            };

            wijinputmask.prototype._getTextWithPromptAndLiterals = function () {
                return !this._isInitialized() ? this.element.val() : this._textProvider.toString(true, true, true);
            };

            wijinputmask.prototype._getTextWithPromptAndLiteralsAndPassword = function () {
                return !this._isInitialized() ? this.element.val() : this._textProvider.toString(false, true, true);
            };

            wijinputmask.prototype._onChange = function () {
                if (!this.element) {
                    return;
                }
                var val = this.element.val();
                if (this.getText() !== val && this._getTextWithPrompts() !== val && this._getTextWithPromptAndLiterals() !== val) {
                    if (this._textProvider.getPasswordChar() !== "") {
                        if (this._getTextWithPromptAndLiteralsAndPassword() !== val) {
                            if (this.element.data("customRaiseChange") == true && !!this.options.hidePromptOnLeave) {
                                // DaryLuo 2015/1026 fix bug 128164.
                            } else {
                                this.setText(val);
                            }
                        }
                    } else {
                        this.setText(val);
                    }
                }
            };

            wijinputmask.prototype._onMouseDown = function (e) {
                _super.prototype._onMouseDown.call(this, e);
                this.element.data('prevSelection', null);
            };

            wijinputmask.prototype._afterFocused = function () {
                if (this._isNullText() || !!this.options.hidePromptOnLeave) {
                    this._doFocus();
                }
                if (this.options.highlightText === "none") {
                    var prevPos = this.element.data('prevSelection');
                    if (prevPos) {
                        this.element.wijtextselection(prevPos.start, prevPos.end);
                    }
                } else if (this.options.highlightText === "field") {
                    var fieldState = this._getCurrentField();
                    var currentField = fieldState.currentField;
                    var fieldList = fieldState.fieldList;
                    if (currentField >= fieldList.length) {
                        currentField = fieldList.length - 1;
                    }
                    var curField = fieldList[currentField];
                    if (curField) {
                        this.selectText(curField.start, curField.end + 1);
                    }
                } else if (this.options.highlightText === "all") {
                    var input = this.element.get(0);
                    this.selectText(0, input.value.length);
                }
            };

            wijinputmask.prototype._processTabKey = function (e) {
                var _this = this;
                var tabAction = this.options.tabAction;
                tabAction = tabAction ? tabAction.toLowerCase() : "control";
                if (tabAction === "control") {
                    setTimeout(function () {
                        _this._trigger("keyExit");
                    }, 0);
                    return false;
                } else {
                    return this._moveField(!e.shiftKey);
                }
            };

            wijinputmask.prototype._getCurrentField = function () {
                var fieldList = this._textProvider._getFieldList();
                var range = this.element.wijtextselection();
                var start = range.start;
                var currentField = -1;

                if (fieldList.length > 0) {
                    if (start > fieldList[fieldList.length - 1].end) {
                        currentField = fieldList.length;
                    }
                }
                if (currentField === -1) {
                    for (var i = 0; i < fieldList.length; i++) {
                        if (start >= fieldList[i].start && start <= fieldList[i].end) {
                            currentField = i;
                            break;
                        }

                        if (start < fieldList[i].start) {
                            if (i != 0) {
                                currentField = i;
                            } else {
                                currentField = -1;
                            }
                            break;
                        }
                    }
                }

                var ret = {};
                ret.currentField = currentField;
                ret.fieldList = fieldList;
                return ret;
            };

            wijinputmask.prototype._moveField = function (direction) {
                var fieldState = this._getCurrentField();
                var currentField = fieldState.currentField;
                var fieldList = fieldState.fieldList;
                if (direction) {
                    if (currentField === fieldList.length - 1) {
                        return false;
                    }
                    this.element.wijtextselection(fieldList[currentField + 1].start, fieldList[currentField + 1].start);
                } else {
                    if (currentField <= 0) {
                        return false;
                    }
                    this.element.wijtextselection(fieldList[currentField - 1].start, fieldList[currentField - 1].start);
                }

                return true;
            };

            wijinputmask.prototype._processLeftRightKey = function (isLeft) {
                var range = this.element.wijtextselection();
                var exitLeftRightKey = this.options.blurOnLeftRightKey ? this.options.blurOnLeftRightKey.toLowerCase() : "none";

                if (isLeft && range.start === 0) {
                    if (exitLeftRightKey === "both" || exitLeftRightKey === "left") {
                        this._moveControl(this.element.get(0), false, true);
                        return true;
                    }
                } else {
                    var exitSettingToRight = exitLeftRightKey === "both" || exitLeftRightKey === "right";
                    var caretInLast = false;
                    if (this._textProvider.noMask && range.start === this.options.text.length) {
                        caretInLast = true;
                    } else if (!this._textProvider.noMask && range.start === this._textProvider.testString.length) {
                        caretInLast = true;
                    }
                    if (!isLeft && exitSettingToRight && caretInLast) {
                        this._moveControl(this.element.get(0), true, true);
                        return true;
                    }
                }
                return false;
            };

            wijinputmask.prototype._onKeyPress = function (e) {
                if (!this._textProvider.noMask && this.options.blurOnLastChar) {
                    var before = this._textProvider._isLastCharAssigned();
                }
                _super.prototype._onKeyPress.call(this, e);
                if (!this._textProvider.noMask && this.options.blurOnLastChar) {
                    var end = this._textProvider._isLastCharAssigned();
                    if (!before && end) {
                        this._moveControl(this.element.get(0), true, true);
                    }
                }
            };

            /** Sets the text displayed in the input box.
            * @example
            * // This example sets text of a wijinputcore to "Hello"
            * $(".selector").wijinputcore("setText", "Hello");
            */
            wijinputmask.prototype.setText = function (text) {
                if (text === undefined) {
                    return;
                }
                if (this._advanceMode) {
                    if (text == this.options.textWithPromptAndLiterals) {
                        this.options.textWithPromptAndLiterals = undefined;
                        this._imMask.SetText(text);
                    } else {
                        this._imMask.SetValue(text);
                    }
                } else {
                    _super.prototype.setText.call(this, text);
                }
            };

            /** Gets the text displayed in the input box.
            */
            wijinputmask.prototype.getText = function () {
                if (this._advanceMode) {
                    return this._imMask.GetTextOnSimpleMode();
                } else {
                    return _super.prototype.getText.call(this);
                }
            };

            /** Selects a range of text in the widget.
            * @param {Number} start Start of the range.
            * @param {Number} end End of the range.
            * @example
            * // Select first two symbols in a wijinputmask
            * $(".selector").wijinputmask("selectText", 0, 2);
            */
            wijinputmask.prototype.selectText = function (start, end) {
                if (typeof start === "undefined") { start = 0; }
                if (typeof end === "undefined") { end = this.getText().length; }
                if (isNaN(start)) {
                    start = 0;
                }
                if (isNaN(end)) {
                    end = 0;
                }
                if (this._advanceMode) {
                    this._imMask.SetSelectionStart(start);
                    this._imMask.SetSelectionLength(Math.abs(end - start));
                    this._imMask.SetFocus();
                } else {
                    _super.prototype.selectText.call(this, start, end);
                }
            };

            /**  Gets the selected text.
            */
            wijinputmask.prototype.getSelectedText = function () {
                if (this._advanceMode) {
                    return this._imMask.GetSelectedText();
                } else {
                    return _super.prototype.getSelectedText.call(this);
                }
            };

            wijinputmask.prototype._attachInputEvent = function () {
                if (this._advanceMode) {
                    this._imMask.AttachInput(this.element.get(0));
                } else {
                    _super.prototype._attachInputEvent.call(this);
                }
            };

            wijinputmask.prototype._detachInputEvent = function () {
                if (this._advanceMode) {
                    this._imMask.DetachInput();
                } else {
                    _super.prototype._detachInputEvent.call(this);
                }
            };

            /** Gets the text value when the container
            * form is posted back to server.
            */
            wijinputmask.prototype.getPostValue = function () {
                if (this._advanceMode) {
                    return this._imMask.GetPostValueOnSimpleMode();
                } else {
                    return _super.prototype.getPostValue.call(this);
                }
            };

            wijinputmask.prototype._initialize = function () {
                if (this.options.maskFormat) {
                    this.options.mask = this.options.maskFormat;
                }
                _super.prototype._initialize.call(this);
            };

            wijinputmask.prototype._init = function () {
                _super.prototype._init.call(this);

                var val = this.options.text || this.element.val();
                if (this.options.mask) {
                    this._setOption("mask", this.options.mask);
                }

                if (val && val !== this._getNullText()) {
                    this._setOption("text", val);
                }

                if (!_input.CoreUtility.IsIE()) {
                    this.element.data('prevSelection', { "start": 0, "end": 0 });
                }
            };

            wijinputmask.prototype._updateText = function (keepSelection) {
                if (typeof keepSelection === "undefined") { keepSelection = false; }
                if (!this.element.data("initialized")) {
                    if (this.options.mask instanceof RegExp || this.options.formatMode === "advanced") {
                        return;
                    }
                }
                if (this._advanceMode) {
                    if (!this._isInitialized()) {
                        return;
                    }
                    if (this.element.is(':disabled')) {
                        return;
                    }
                    var text = this._imMask.GetTextOnSimpleMode();
                    this.options.advancedText = this._imMask.GetText();
                    if (text !== this.options.text) {
                        this.options.text = text;
                        this._raiseTextChanged();
                    }
                } else {
                    _super.prototype._updateText.call(this, keepSelection);

                    // DaryLuo 2014/04/04 fix bug 48485.
                    // placeHolder value should never set to the option's text value.
                    if (this.options.text === this._getNullText()) {
                        this.options.text = "";
                    }
                }
            };

            /** Determines whether the widget has the focus.
            */
            wijinputmask.prototype.isFocused = function () {
                if (this._advanceMode) {
                    return this._imMask.IsFocused();
                } else {
                    return _super.prototype.isFocused.call(this);
                }
            };

            wijinputmask.prototype._getAllowPromptAsInput = function () {
                return this.options.allowPromptAsInput;
            };

            wijinputmask.prototype._getPasswordChar = function () {
                return this.options.passwordChar;
            };

            wijinputmask.prototype._getResetOnPrompt = function () {
                return this.options.resetOnPrompt;
            };

            wijinputmask.prototype._getResetOnSpace = function () {
                return this.options.resetOnSpace;
            };

            wijinputmask.prototype._getSkipLiterals = function () {
                return this.options.skipLiterals;
            };

            wijinputmask.prototype._getHidePromptOnLeave = function () {
                return this.options.hidePromptOnLeave;
            };

            wijinputmask.prototype._getPromptChar = function () {
                return this.options.promptChar;
            };

            wijinputmask.prototype._getAutoConvert = function () {
                return this.options.autoConvert;
            };

            wijinputmask.prototype._getNullText = function () {
                return this.options.nullText;
            };
            wijinputmask._imMaskAssociatedoptions = [
                "disabled", "disableUserInput", "blurOnLastChar", "imeMode", "blurOnLeftRightKey",
                "tabAction", "nullText", "placeholder", "readonly", "promptChar", "autoConvert",
                "showNullText", "hideEnter", "hidePromptOnLeave", "highlightText"];
            return wijinputmask;
        })(_input.wijinputcore);
        _input.wijinputmask = wijinputmask;

        var wijinputmask_options = (function () {
            function wijinputmask_options() {
                this.wijCSS = {
                    wijinputmask: _input.wijinputcore.prototype.options.wijCSS.wijinput + "-mask"
                };
                /** Gets whether the control automatically converts to the proper format according to the format setting.
                * @example
                * // In this example, when input the lower case alphabet, it will be convert to upper case alphabet.
                * $(".selector").wijinputmask({
                *   maskFormat: /\A{3}-\A{4}/,
                *   autoConvert:true
                * });
                */
                this.autoConvert = true;
                /** Determines the default text.
                */
                this.text = null;
                /** Determines whether to highlight the control's text on receiving input focus.
                * Possible values are : "none", "field", "all";
                * The default value is "none";
                */
                this.highlightText = "none";
                /** Determines the input mask to use at run time.
                * Mask must be a string composed of one or more of the masking elements.
                * Obsoleted, use maskFormat instead.
                * @ignore
                */
                this.mask = "";
                /** Determines the input mask to use at run time.
                * @remarks
                * <pre>
                * The property can be a string composed of one or more of the masking elements as shown in the following table,
                * 0  --------- Digit, required. This element will accept any single digit between 0 and 9.<br />
                * 9  --------- Digit or space, optional.
                * #  --------- Digit or space, optional. Plus (+) and minus (-) signs are allowed.
                * L  --------- Letter, required. Restricts input to the ASCII letters a-z and A-Z.
                *              This mask element is equivalent to [a-zA-Z] in regular expressions.
                * ?  --------- Letter, optional. Restricts input to the ASCII letters a-z and A-Z.
                *              This mask element is equivalent to [a-zA-Z]? in regular expressions.
                * &amp;  --------- Character, required.<br />
                * C  --------- Character, optional. Any non-control character.<br />
                * A  --------- Alphanumeric, optional.
                * a  --------- Alphanumeric, optional.
                * .  --------- Decimal placeholder. The actual display character used will be the decimal placeholder appropriate to the culture option.<br />
                * ,  --------- Thousands placeholder. The actual display character used will be the thousands placeholder appropriate to the culture option.
                * :  --------- Time separator. The actual display character used will be the time placeholder appropriate to the culture option.
                * /  --------- Date separator. The actual display character used will be the date placeholder appropriate to the culture option.
                * $  --------- Currency symbol. The actual character displayed will be the currency symbol appropriate to the culture option.
                * &lt;  --------- Shift down. Converts all characters that follow to lowercase.
                * &gt;  --------- Shift up. Converts all characters that follow to uppercase.
                * |  --------- Disable a previous shift up or shift down.
                * H  --------- All SBCS characters.
                * K  --------- SBCS Katakana.
                * ９ --------- DBCS Digit.
                * Ｋ --------- DBCS Katakana.
                * Ｊ --------- Hiragana.
                * Ｚ --------- All DBCS characters.
                * N  --------- All SBCS big Katakana.
                * Ｎ --------- Matches DBCS big Katakana.
                * Ｇ --------- Matches DBCS big Hiragana.
                * \\ --------- Escape. Escapes a mask character, turning it into a literal. The escape sequence for a backslash is: \\\\
                * All other characters, Literals. All non-mask elements appear as themselves within wijinputmask.
                * Literals always occupy a static position in the mask at run time, and cannot be moved or deleted by the user.
                *
                *
                * The following table shows example masks.
                *     00/00/0000            A date (day, numeric month, year) in international date format. The "/" character is a logical date separator, and will appear to the user as the date separator appropriate to the application's current culture.
                *     00-&gt;L&lt;LL-0000         A date (day, month abbreviation, and year) in United States format in which the three-letter month abbreviation is displayed with an initial uppercase letter followed by two lowercase letters.
                *     (999)-000-0000        United States phone number, area code optional. If users do not want to enter the optional characters, they can either enter spaces or place the mouse pointer directly at the position in the mask represented by the first 0.
                *     $999,999.00           A currency value in the range of 0 to 999999. The currency, thousandth, and decimal characters will be replaced at run time with their culture-specific equivalents.
                *  For example:
                *  $(".selector").wijinputmask({
                *      maskFormat: "(999)-000-0000 "
                *  });
                *
                *  Value of maskFormat can also be a regex value, attentation, only the following key word supported by the regex value.<br />
                *  \A   ----------- Matches any upper case alphabet [A-Z].
                *  \a   ----------- Matches any lower case alphabet [a-z].
                *  \D   ----------- Matches any decimal digit. Same as [0-9].
                *  \W   ----------- Matches any word character. It is same as [a-zA-Z_0-9].
                *  \K   ----------- Matches SBCS Katakana.
                *  \H   ----------- Matches all SBCS characters.
                *  \Ａ  ----------- Matches any upper case DBCS alphabet [Ａ-Ｚ].
                *  \ａ  ----------- Matches any lower case DBCS alphabet [ａ-ｚ].
                *  \Ｄ  ----------- Matches any DBCS decimal digit. Same as [０-９].
                *  \Ｗ  ----------- Matches any DBCS word character. It is same as [ａ-ｚＡ-Ｚ＿０-９].
                *  \Ｋ  ----------- DBCS Katakana
                *  \Ｊ  ----------- Hiragana
                *  \Ｚ  ----------- All DBCS characters.
                *  \N   ----------- Matches all SBCS big Katakana.
                *  \Ｎ  ----------- Matches DBCS big Katakana.
                *  \Ｇ  ----------- Matches DBCS big Hiragana.
                *  \Ｔ  ----------- Matchese surrogate char.
                *  [^] Used to express an exclude subset.
                *  - Used to define a contiguous character range.
                *  {} Specifies that the pattern.
                *  * The short expression of {0,}.
                *  + The short expression of {1,}.
                *  ? The short expression of {0,1}.
                *
                *
                *  The following shows some example use Regex value.
                *  \D{3}-\D{4}                      Zip Code (012-3456)
                *  ℡ \D{2,4}-\D{2,4}-\D{4}/        Phone number (℡ 012-345-6789)
                *  \D{2,4}-\D{2,4}-\D{4}            Phone number (012-345-6789)
                *  Attentation, because maskFormat requrie that it uses a regex value, so assign the value as follows example.
                * </pre>
                *  @example
                *  <pre>
                *  $(".selector").wijinputmask({
                *      maskFormat: /\D{3}-\D{4}/
                *  }); <br />
                *  $(".selector").wijinputmask({
                *          maskFormat: new RegExp("\\D{3}-\\D{4}")
                *  });
                *  </pre>
                */
                this.maskFormat = "";
                /** Determines the character that appears when the widget has focus but no input has been entered.
                */
                this.promptChar = '_';
                /** Indicates whether the prompt characters in the input mask are hidden when the input loses focus.
                * @remarks
                * This property doesn't take effect when maskFormat property is set to a Regex value.
                */
                this.hidePromptOnLeave = false;
                /** Determines how an input character that matches
                * the prompt character should be handled.
                * @remarks
                * This property doesn't take effect when maskFormat property is set to a Regex value.
                */
                this.resetOnPrompt = true;
                /** Indicates whether promptChar can be entered as valid data by the user.
                * @remarks
                * This property doesn't take effect when maskFormat property is set to a Regex value.
                */
                this.allowPromptAsInput = false;
                /** Determines the character to be substituted for the actual input characters.
                * @remarks
                * This property doesn't take effect when maskFormat property is set to a Regex value.
                */
                this.passwordChar = '';
                /** Determines how a space input character should be handled.
                * @remarks
                * This property doesn't take effect when maskFormat property is set to a Regex value.
                */
                this.resetOnSpace = true;
                /** Indicates whether the user is allowed to re-enter literal values.
                * @remarks
                * This property doesn't take effect when maskFormat property is set to a Regex value.
                */
                this.skipLiterals = true;
                /** Determines whether or not the next control in the tab order receives
                the focus as soon as the control is filled at the last character.
                */
                this.blurOnLastChar = false;
                /** Determines whether the focus will move to the next filed or the next control when press the tab key.
                * Possible values are "control", "field".
                * @remarks
                * The caret moves to the next field when this property is "field".
                * If the caret is in the last field, the input focus leaves this control when pressing the TAB key.
                * If the value is "control", the behavior is similar to the standard control.
                */
                this.tabAction = "control";
                /** Determines the input method setting of widget.
                * Possible values are: 'auto', 'active', 'inactive', 'disabled'
                * @remarks
                * This property only take effect on IE and firefox browser.
                */
                this.imeMode = "auto";
                /** @ignore */
                this.allowSpinLoop = false;
                /** @ignore */
                this.spinnerAlign = "verticalRight";
                /** @ignore */
                this.showSpinner = false;
            }
            return wijinputmask_options;
        })();
        wijinputmask.prototype.options = $.extend(true, {}, _input.wijinputcore.prototype.options, new wijinputmask_options());

        $.wijmo.registerWidget("wijinputmask", wijinputmask.prototype);
    })(wijmo.input || (wijmo.input = {}));
    var input = wijmo.input;
})(wijmo || (wijmo = {}));

;
/// <reference path="../External/declarations/jquery.d.ts"/>
/// <reference path="../External/declarations/globalize.d.ts"/>
/// <reference path="../wijutil/jquery.wijmo.wijutil.ts"/>
var wijmo;
(function (wijmo) {
    /*
    * Depends:
    *	jquery-1.11.1.js
    *	globalize.js
    *  jquery.wijmo.wijutil.js
    *
    */
    (function (input) {
        //============================
        /** @ignore */
        var wijNumberFormat = (function () {
            //_cultureObj;
            //_positivePrefix: string;
            //_positiveSuffix: string;
            //_negativePrefix: string;
            //_negativeSuffix: string;
            function wijNumberFormat() {
                // stripped value with en-US culture
                this._currentValueInString = '0';
                this._currentText = '0';
                this._strippedText = '0';
                this._groupSeparator = ' ';
            }
            wijNumberFormat.prototype._isNegtive = function (value) {
                return value.indexOf('-') !== -1 || value.indexOf('(') !== -1;
            };

            wijNumberFormat.prototype._stripValue = function (value, cultureObj, options) {
                var nf = cultureObj.numberFormat, specificFormat = nf[options.type] || nf, isNegative = this._isNegtive(value), groupSep = specificFormat[','], decimalSep = specificFormat['.'], stripRgx = new RegExp('[' + groupSep + nf.percent.symbol + options.currencySymbol + ' ]', 'g'), match;

                this._groupSeparator = groupSep;

                value = this._removeNegativeSign(value);
                value = value.replace(stripRgx, '');
                value = value.replace(decimalSep, '.');
                match = /([\d\.])+/.exec(value);
                if (match) {
                    value = match[0];
                } else {
                    // HelenLiu 2015/01/23 fix bug 106287 in Wijmo.
                    value = '';
                }
                if (isNegative) {
                    value = '-' + value;
                }

                return value;
            };

            wijNumberFormat.prototype.tryParseValue = function (value, cultureObj, options) {
                try  {
                    var result = parseFloat(this._stripValue(value, cultureObj, options));
                    if (isNaN(result)) {
                        result = null;
                    }
                    return result;
                } catch (e) {
                    return null;
                }
            };

            wijNumberFormat.prototype.deFormatValue = function (value, cultureObj, positivePrefix, positiveSuffix, negativePrefix, negativeSuffix, options) {
                value = this._stripValue(value, cultureObj, options);
                this._currentValueInString = value;
                this._currentText = this._formatValue(value, cultureObj, positivePrefix, positiveSuffix, negativePrefix, negativeSuffix, options);
            };

            wijNumberFormat.prototype._formatValue = function (strippedValue, cultureObj, positivePrefix, positiveSuffix, negativePrefix, negativeSuffix, options) {
                var ops = options;
                var nf = cultureObj.numberFormat, specificFormat = nf[ops.type] || nf, dp = ops.decimalPlaces, groupSep = specificFormat[','], decimalSep = specificFormat['.'], decimals = dp !== -2 ? dp : specificFormat.decimals, groupSizes = ops.showGroup ? specificFormat.groupSizes : [0], digitsString;

                strippedValue = this._removeLeadingZero(strippedValue);
                digitsString = this._formatDigit(strippedValue, groupSep, decimalSep, decimals, groupSizes);
                digitsString = this._removeLeadingZero(digitsString, ops.showGroup ? groupSep : "");
                if (digitsString.indexOf(decimalSep) === 0) {
                    digitsString = '0' + digitsString;
                }
                if (digitsString === '') {
                    digitsString = '0';
                }

                this._currentValueInString = strippedValue;

                //this._currentText = this.applyFormatPattern(pattern, digitsString,
                //    nf.percent.symbol, this.inputWidget.options.currencySymbol);
                this._strippedText = digitsString;

                var prefix = this.isNegative() ? negativePrefix : positivePrefix;
                var suffix = this.isNegative() ? negativeSuffix : positiveSuffix;

                this._currentText = prefix + digitsString + suffix;
                return this._currentText;
            };

            wijNumberFormat.prototype._showNullText = function (options) {
                return !!options.nullText || options.nullText === "";
            };

            wijNumberFormat.prototype.getFormattedValue = function (initialValue, isValueNull, cultureObj, positivePrefix, positiveSuffix, negativePrefix, negativeSuffix, options) {
                //var prefix = this.inputWidget._getPrefix(),
                //    suffix = this.inputWidget._getSuffix();
                //return prefix + this._removeNegativeSign(this.formatValue(this._currentValueInString)) + suffix;
                if (!this._showNullText(options) && isValueNull) {
                    this._currentValueInString = initialValue + '';
                }

                return this._formatValue(this._currentValueInString, cultureObj, positivePrefix, positiveSuffix, negativePrefix, negativeSuffix, options);
            };

            wijNumberFormat.prototype.getJSFloatValue = function () {
                try  {
                    if (this._currentValueInString === '' || this._currentValueInString === '.') {
                        return 0;
                    }
                    return parseFloat(this._currentValueInString);
                } catch (e) {
                    return Number.NaN;
                }
            };

            wijNumberFormat.prototype.clear = function () {
                this._currentValueInString = '0';
                this._currentText = '0';
                this._strippedText = '0';
            };

            wijNumberFormat.prototype.setValueFromJSFloat = function (value, cultureObj, positivePrefix, positiveSuffix, negativePrefix, negativeSuffix, options) {
                var strValue = value.toFixed(options.decimalPlaces + 1);
                try  {
                    this._currentValueInString = strValue;
                    this._formatValue(strValue, cultureObj, positivePrefix, positiveSuffix, negativePrefix, negativeSuffix, options);
                    return true;
                } catch (e) {
                    return false;
                }
            };

            wijNumberFormat.prototype.isZero = function (val) {
                if (typeof val === "undefined") { val = this._currentValueInString; }
                var test = this._removeNegativeSign(val), dbl;
                if (!test) {
                    return true;
                }
                dbl = parseFloat(test);
                return !isNaN(dbl) && !dbl;
            };

            wijNumberFormat.prototype.setPositiveSign = function () {
                this._currentValueInString = this._removeNegativeSign(this._currentValueInString);
            };

            wijNumberFormat.prototype._removeNegativeSign = function (text) {
                return text.replace(/[()\-]/g, "");
            };

            wijNumberFormat.prototype._removeLeadingZero = function (text, groupSep) {
                if (typeof groupSep === "undefined") { groupSep = ""; }
                var text = text.replace(/^0+/, "");
                while (groupSep.length > 0 && text.indexOf(groupSep) === 0) {
                    text = text.substr(groupSep.length);
                    var text = text.replace(/^0+/, "");
                }
                return text;
            };

            wijNumberFormat.prototype.isNegative = function () {
                return this._currentValueInString.indexOf('-') !== -1 || this._currentValueInString.indexOf('(') !== -1;
            };

            wijNumberFormat.prototype.invertSign = function (cultureObj, positivePrefix, positiveSuffix, negativePrefix, negativeSuffix, options) {
                var isNegative = this.isNegative();
                if (isNegative) {
                    this.setPositiveSign();
                } else {
                    this._currentValueInString = (!this._currentValueInString.length) ? '0' : '-' + this._currentValueInString;
                }
                if (this.isZero()) {
                    this._currentValueInString = isNegative ? '0' : '-0';
                }
                this._formatValue(this._currentValueInString, cultureObj, positivePrefix, positiveSuffix, negativePrefix, negativeSuffix, options);
            };

            wijNumberFormat.prototype.checkDigitsLimits = function (digitCount) {
                var arr = this._currentValueInString.split("."), fraction = '';

                if (!arr.length || (arr.length === 1 && arr[0] === '')) {
                    return;
                }

                if (arr.length > 1) {
                    fraction = arr[1];
                }

                fraction = fraction.substring(0, digitCount);
                while (fraction.length < digitCount) {
                    fraction += "0";
                }

                this._currentValueInString = arr[0];
                if (fraction) {
                    this._currentValueInString += "." + fraction;
                }
            };

            wijNumberFormat.prototype.checkMinValue = function (minValue, chkAndRepair, chkIsLessOrEqMin) {
                if (typeof chkIsLessOrEqMin === "undefined") { chkIsLessOrEqMin = false; }
                var result = true, integerFractionArr, currentIntegerPart, currentFractionPart, minIntegerPart, minFractionPart;
                try  {
                    integerFractionArr = this._currentValueInString.split(".");
                    currentIntegerPart = parseFloat((integerFractionArr[0] === '' || integerFractionArr[0] === '-') ? '0' : integerFractionArr[0]);
                    currentFractionPart = 0;

                    if (integerFractionArr.length > 1 && parseFloat(integerFractionArr[1]) >= 0) {
                        currentFractionPart = parseFloat('1.' + integerFractionArr[1]);
                    }
                    if (currentIntegerPart < 0 || integerFractionArr[0] === '-' || (integerFractionArr[0].length > 0 && integerFractionArr[0][0] === '-')) {
                        currentFractionPart = currentFractionPart * (-1);
                    }
                    minValue = '' + minValue.toFixed(12) + '';
                    integerFractionArr = minValue.split(".");
                    minIntegerPart = parseFloat((integerFractionArr[0] === '' || integerFractionArr[0] === '-') ? '0' : integerFractionArr[0]);
                    minFractionPart = 0;
                    if (integerFractionArr.length > 1 && parseFloat(integerFractionArr[1]) >= 0) {
                        minFractionPart = parseFloat('1.' + integerFractionArr[1]);
                    }

                    if (minIntegerPart < 0 || integerFractionArr[0] === '-' || (integerFractionArr[0].length > 0 && integerFractionArr[0][0] === '-')) {
                        minFractionPart = minFractionPart * (-1);
                    }

                    if (currentIntegerPart > minIntegerPart) {
                        return true;
                    }
                    if (currentIntegerPart < minIntegerPart || (chkIsLessOrEqMin && currentIntegerPart === minIntegerPart && currentFractionPart <= minFractionPart)) {
                        result = false;
                    } else if (currentIntegerPart === minIntegerPart && currentIntegerPart < 0 && currentFractionPart < minFractionPart) {
                        result = false;
                    } else if (currentIntegerPart === minIntegerPart && currentIntegerPart >= 0 && currentFractionPart < minFractionPart) {
                        result = false;
                    }
                    if (!result && chkAndRepair) {
                        this._currentValueInString = '' + minValue + '';
                    }
                } catch (e) {
                }
                return result;
            };

            wijNumberFormat.prototype.checkMaxValue = function (maxValue, chkAndRepair) {
                var result = true, integerFractionArr, currentIntegerPart, currentFractionPart, maxIntegerPart, maxFractionPart;
                try  {
                    integerFractionArr = this._currentValueInString.split(".");
                    currentIntegerPart = parseFloat((integerFractionArr[0] === '' || integerFractionArr[0] === '-') ? '0' : integerFractionArr[0]);
                    currentFractionPart = 0;
                    if (integerFractionArr.length > 1 && parseFloat(integerFractionArr[1]) >= 0) {
                        currentFractionPart = parseFloat('1.' + integerFractionArr[1]);
                    }
                    if (currentIntegerPart < 0 || integerFractionArr[0] === '-' || (integerFractionArr[0].length > 0 && integerFractionArr[0][0] === '-')) {
                        currentFractionPart = currentFractionPart * (-1);
                    }

                    maxValue = '' + maxValue.toFixed(12) + '';
                    integerFractionArr = maxValue.split(".");
                    maxIntegerPart = parseFloat((integerFractionArr[0] === '' || integerFractionArr[0] === '-') ? '0' : integerFractionArr[0]);
                    maxFractionPart = 0;
                    if (integerFractionArr.length > 1 && parseFloat(integerFractionArr[1]) >= 0) {
                        maxFractionPart = parseFloat('1.' + integerFractionArr[1]);
                    }
                    if (maxIntegerPart < 0 || integerFractionArr[0] === '-' || (integerFractionArr[0].length > 0 && integerFractionArr[0][0] === '-')) {
                        maxFractionPart = maxFractionPart * (-1);
                    }

                    if (currentIntegerPart < maxIntegerPart) {
                        return true;
                    }
                    if (currentIntegerPart > maxIntegerPart) {
                        result = false;
                    }
                    if (currentIntegerPart === maxIntegerPart && currentIntegerPart >= 0 && currentFractionPart > maxFractionPart) {
                        result = false;
                    }
                    if (currentIntegerPart === maxIntegerPart && currentIntegerPart < 0 && currentFractionPart > maxFractionPart) {
                        result = false;
                    }
                    if (!result && chkAndRepair) {
                        this._currentValueInString = '' + maxValue + '';
                    }
                } catch (e) {
                }
                return result;
            };

            //applyFormatPattern(pattern: string, digitString: string, percentSymbol: string, currencySymbol: string) {
            //    return pattern
            //        .replace(/n/g, digitString)
            //        .replace(/%/g, percentSymbol)
            //        .replace(/\$/g, currencySymbol);
            //}
            wijNumberFormat.prototype._formatDigit = function (strippedValue, groupSep, decimalSep, decimals, groupSizes) {
                var absValue = this._removeNegativeSign(strippedValue), decimalPos, result, groupSizeIndex, groupCount, ch, i;

                decimalPos = absValue.indexOf('.');
                if (decimalPos === -1) {
                    decimalPos = absValue.length;
                }

                result = '';
                groupSizeIndex = 0;
                groupCount = 0;

                for (i = absValue.length - 1; i >= 0; i--) {
                    ch = absValue.charAt(i);
                    if (i < decimalPos) {
                        result = ch + result;
                        groupCount++;
                        if (groupCount === groupSizes[groupSizeIndex] * 1 && groupSizes[groupSizeIndex] * 1 && i) {
                            result = groupSep + result;
                            groupCount = 0;
                            if (groupSizes.length - 1 > groupSizeIndex) {
                                groupSizeIndex++;
                            }
                        }
                    }
                }
                if (decimals > 0) {
                    result = result + decimalSep;
                    for (i = 0; i < decimals; i++) {
                        ch = '0';
                        if (i + decimalPos + 1 < absValue.length) {
                            ch = absValue.charAt(i + decimalPos + 1);
                        }
                        result = result + ch;
                    }
                }
                if (decimals === -1) {
                    if (decimalPos < absValue.length - 1) {
                        result = result + decimalSep;
                        result = result + absValue.substr(decimalPos + 1);
                    }
                }
                return result;
            };
            return wijNumberFormat;
        })();
        input.wijNumberFormat = wijNumberFormat;

        //#region format library
        var _format;

        function numberFormatter(num, type, options) {
            if (!_format) {
                _format = new input.wijNumberFormat();
            }

            if (!type) {
                type = 'numeric';
            }

            if (!options) {
                if (typeof type === "string") {
                    options = {};
                } else {
                    options = type;
                }
            }

            if (_format._showNullText(options) && num === null) {
                return options.nullText;
            }

            if (num === null || num === undefined) {
                return "";
            }

            _format._currentValueInString = num.toString();

            var cultureObj = Globalize.findClosestCulture(options.culture);

            options.type = options.type || type;
            options.showGroup = options.showGroup || false;
            if (typeof options.decimalPlaces !== 'number') {
                options.decimalPlaces = 2;
            }

            _updateCultureRelatedOptions(cultureObj, options);

            return _format.getFormattedValue(0, false, cultureObj, options.positivePrefix, options.positiveSuffix, options.negativePrefix, options.negativeSuffix, options);
        }

        function _updateCultureRelatedOptions(cultureObj, options) {
            var numberFormat = cultureObj.numberFormat, specificFormat = numberFormat[options.type] || numberFormat, negPattern = specificFormat.pattern[0], posPattern = specificFormat.pattern[1] || 'n';

            var negSplitArray = negPattern.split('n'), posSplitArray = posPattern.split('n'), percentSymbol = numberFormat.percent.symbol;
            if (options.currencySymbol === undefined) {
                options.currencySymbol = numberFormat.currency.symbol;
            }
            options.negativePrefix = (options.negativePrefix ? options.negativePrefix : negSplitArray[0]).replace(/%/g, percentSymbol).replace(/\$/g, options.currencySymbol);
            options.negativeSuffix = (options.negativeSuffix ? options.negativeSuffix : negSplitArray[1]).replace(/%/g, percentSymbol).replace(/\$/g, options.currencySymbol);
            options.positivePrefix = (options.positivePrefix ? options.positivePrefix : posSplitArray[0]).replace(/%/g, percentSymbol).replace(/\$/g, options.currencySymbol);
            options.positiveSuffix = (options.positiveSuffix ? options.positiveSuffix : posSplitArray[1]).replace(/%/g, percentSymbol).replace(/\$/g, options.currencySymbol);
        }

        var $ = jQuery;
        $.wijinputcore = $.wijinputcore || {};
        ;
        $.wijinputcore.formatnumber = $.wijinputcore.formatnumber || numberFormatter;

        //#endregion
        //#region parse library
        function numberParser(value, culture) {
            var cultureObj = Globalize.findClosestCulture(culture);
            var nf = cultureObj.numberFormat, cf = nf.currency, pf = nf.percent;

            var np = nf.pattern, cp = cf.pattern, pp = pf.pattern;

            var strippedValue;

            var cRegs = [];
            for (var i in cp) {
                var reg = new RegExp(cp[i].replace(/n/g, '\\d*\\.?\\d+'));
                cRegs.push(reg);
            }
            for (var i in cRegs) {
                var currencyValue = value.replace(new RegExp(cf[','], 'g'), '');
                strippedValue = currencyValue.match(cRegs[i]);
                if (strippedValue) {
                    return Globalize.parseFloat(strippedValue[0], culture);
                }
            }

            var pRegs = [];
            for (var i in pp) {
                var reg = new RegExp(pp[i].replace(/n/g, '\\d*\\.?\\d+'));
                pRegs.push(reg);
            }
            for (var i in pRegs) {
                var percentValue = value.replace(new RegExp(pf[','], 'g'), '');
                strippedValue = percentValue.match(pRegs[i]);
                if (strippedValue) {
                    return Globalize.parseFloat(strippedValue[0], culture) / 100;
                }
            }

            var nRegs = [];
            for (var i in np) {
                var reg = new RegExp(np[i].replace(/n/g, '\\d*\\.?\\d+'));
                nRegs.push(reg);
            }
            var numberValue = value.replace(new RegExp(nf[','], 'g'), '');
            for (var i in nRegs) {
                strippedValue = numberValue.match(nRegs[i]);
                if (strippedValue) {
                    return Globalize.parseFloat(strippedValue[0], culture);
                }
            }
            strippedValue = numberValue.match(/\d*\.?\d+/);
            if (strippedValue) {
                return Globalize.parseFloat(strippedValue[0], culture);
            }

            return Globalize.parseFloat(value, culture);
        }

        $.wijinputcore.parseNumber = $.wijinputcore.parseNumber || numberParser;

        //#endregion
        //#region validate library
        function numberValidator(value, minValue, maxValue, culture) {
            var numberValue = numberParser(value, culture);
            return numberValue >= minValue && numberValue <= maxValue;
        }

        $.wijinputcore.validateNumber = $.wijinputcore.validateNumber || numberValidator;
    })(wijmo.input || (wijmo.input = {}));
    var input = wijmo.input;
})(wijmo || (wijmo = {}));
;
/// <reference path="jquery.wijmo.wijstringinfo.ts"/>
/// <reference path="jquery.wijmo.wijinputcore.ts"/>
/// <reference path="jquery.wijmo.wijinputnumberformat.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*globals wijinputcore wijNumberTextProvider wijInputResult
    wijNumberFormat window jQuery*/
    /*
    * Depends:
    *	jquery-1.4.2.js
    *	jquery.ui.core.js
    *	jquery.ui.widget.js
    *	jquery.ui.position.js
    *	jquery.effects.core.js
    *	jquery.effects.blind.js
    *	globalize.js
    *	jquery.mousewheel.js
    *	jquery.wijmo.wijpopup.js
    *	jquery.wijmo.wijcharex.js
    *	jquery.wijmo.wijstringinfo.js
    *	jquery.wijmo.wijinputcore.js
    *  jquery.wijmo.wijinputnumberformat.js
    *
    */
    (function (input) {
        var $ = jQuery, jqKeyCode = wijmo.getKeyCodeEnum();

        /** @widget */
        var wijinputnumber = (function (_super) {
            __extends(wijinputnumber, _super);
            function wijinputnumber() {
                _super.apply(this, arguments);
                this._initialValue = 0;
            }
            wijinputnumber.prototype._init = function () {
                _super.prototype._init.call(this);
                this._initUserCultureOptions();
                this._updateCultureRelatedOptions();
                this._updateText();
                this.element.data('changed', false);
                this.element.attribute({
                    "role": "spinbutton",
                    "aria-label": "wijinputnumber"
                });
            };

            wijinputnumber.prototype._onKeyPress = function (e) {
                if (e.charCode && !e.ctrlKey) {
                    // prevent invalid input
                    var chr = String.fromCharCode(e.charCode);
                    if (!this._isNumeric(chr)) {
                        e.preventDefault();
                        return false;
                    }
                }
                _super.prototype._onKeyPress.call(this, e);
            };

            wijinputnumber.prototype._isNumeric = function (chr) {
                var isNum = (chr === this._textProvider.getDecimalSeparator()) || (chr >= '0' && chr <= '9');
                if (!isNum) {
                    isNum = '+-()'.indexOf(chr) > -1;
                }
                return isNum;
            };

            wijinputnumber.prototype._initUserCultureOptions = function () {
                if (this.options.negativePrefix !== null) {
                    this._userNegativePrefix = this.options.negativePrefix;
                }
                if (this.options.negativeSuffix !== null) {
                    this._userNegativeSuffix = this.options.negativeSuffix;
                }
                if (this.options.positivePrefix !== null) {
                    this._userPositivePrefix = this.options.positivePrefix;
                }
                if (this.options.positiveSuffix !== null) {
                    this._userPositiveSuffix = this.options.positiveSuffix;
                }
                if (this.options.currencySymbol !== null) {
                    this._userCurrencySymbol = this.options.currencySymbol;
                }
            };

            wijinputnumber.prototype._deleteUserCultureOptions = function () {
                delete this._userNegativePrefix;
                delete this._userNegativeSuffix;
                delete this._userPositivePrefix;
                delete this._userPositiveSuffix;
                delete this._userCurrencySymbol;
            };

            // should be called when 'culture', 'type' and 'currencySymbol' changes.
            wijinputnumber.prototype._updateCultureRelatedOptions = function () {
                var numberFormat = this._getCulture().numberFormat, specificFormat = numberFormat[this.options.type] || numberFormat, negPattern = specificFormat.pattern[0], posPattern = specificFormat.pattern[1] || 'n';

                var negSplitArray = negPattern.split('n'), posSplitArray = posPattern.split('n'), percentSymbol = this._getPercentSymbol(), currencySymbol = this._getCulture().numberFormat.currency.symbol;
                if (this._userNegativePrefix === undefined) {
                    this.options.negativePrefix = negSplitArray[0].replace(/%/g, percentSymbol).replace(/\$/g, currencySymbol);
                }
                if (this._userNegativeSuffix === undefined) {
                    this.options.negativeSuffix = negSplitArray[1].replace(/%/g, percentSymbol).replace(/\$/g, currencySymbol);
                }
                if (this._userPositivePrefix === undefined) {
                    this.options.positivePrefix = posSplitArray[0].replace(/%/g, percentSymbol).replace(/\$/g, currencySymbol);
                }
                if (this._userPositiveSuffix === undefined) {
                    this.options.positiveSuffix = posSplitArray[1].replace(/%/g, percentSymbol).replace(/\$/g, currencySymbol);
                }
                if (this._userCurrencySymbol === undefined) {
                    this.options.currencySymbol = numberFormat.currency.symbol;
                }
            };

            wijinputnumber.prototype._createTextProvider = function () {
                if (this._textProvider) {
                    return this._textProvider;
                }
                this._textProvider = new wijNumberTextProvider(this, this.options.type);
                this._textProvider.setNullValue(this.element.val() === "" && this.options.value === null);
            };

            wijinputnumber.prototype._beginUpdate = function () {
                this._initialValue = 0;
                var o = this.options;
                this.element.addClass(o.wijCSS.wijinputnumber);

                this.element.data({
                    defaultValue: o.value,
                    preValue: o.value
                }).attribute({
                    'aria-valuemin': o.minValue,
                    'aria-valuemax': o.maxValue,
                    'aria-valuenow': o.value || this._initialValue
                });
            };

            /** Set the focus to the widget. */
            wijinputnumber.prototype.focus = function () {
                this._doFocus();
            };

            wijinputnumber.prototype._setOption = function (key, value) {
                _super.prototype._setOption.call(this, key, value);

                switch (key) {
                    case 'minValue':
                        this.element.attribute('aria-valuemin', value);
                        this._updateText();
                        break;

                    case 'maxValue':
                        this.element.attribute('aria-valuemax', value);
                        this._updateText();
                        break;

                    case 'value':
                        this.setValue(value);
                        this._updateText();
                        break;

                    case 'showGroup':
                    case 'decimalPlaces':
                    case 'culture':
                        //this._textProvider.updateStringFormat();
                        this._updateCultureRelatedOptions();
                        this._updateText();
                        break;
                    case 'positivePrefix':
                        this._userPositivePrefix = value;
                        this._updateText();
                        break;
                    case 'negativePrefix':
                        this._userNegativePrefix = value;
                        this._updateText();
                        break;
                    case 'positiveSuffix':
                        this._userPositiveSuffix = value;
                        this._updateText();
                        break;
                    case 'negativeSuffix':
                        this._userNegativeSuffix = value;
                        this._updateText();
                        break;
                    case 'currencySymbol':
                        this._userCurrencySymbol = value;
                        this._updateCultureRelatedOptions();
                        this._updateText();
                        break;
                    case 'type':
                        this._deleteUserCultureOptions();
                        this._updateCultureRelatedOptions();
                        this._updateText();
                        break;
                }
            };

            wijinputnumber.prototype._setData = function (val) {
                this.setValue(val);
            };

            wijinputnumber.prototype._resetData = function () {
                var val = this.element.data('defaultValue');
                if (val === 0) {
                    var elementValue = this.element.data('elementValue');
                    if (elementValue !== undefined && elementValue !== null && elementValue !== "") {
                        val = elementValue;
                    }
                }

                if (val !== this._textProvider.getValue() || (this._textProvider._nullvalue && val === 0)) {
                    this.setValue(val);
                }
            };

            wijinputnumber.prototype._validateData = function () {
                if (!this._textProvider.checkAndRepairBounds(true, false) && this.options.value !== null) {
                    this._updateText();
                }
            };

            wijinputnumber.prototype._raiseDataChanged = function () {
                var v = this.options.value, prevValue = this.element.data('preValue');
                this.element.data('preValue', v);
                if (prevValue !== v) {
                    this.element.attribute('aria-valuenow', v);
                    this._trigger('valueChanged', null, { value: v });
                }
            };

            wijinputnumber.prototype._onChange = function () {
            };

            wijinputnumber.prototype._getPrefix = function () {
                if (this._textProvider._stringFormat.isNegative()) {
                    if (this._userNegativePrefix !== undefined) {
                        return this._userNegativePrefix;
                    } else {
                        return this.options.negativePrefix;
                    }
                } else {
                    if (this._userPositivePrefix !== undefined) {
                        return this._userPositivePrefix;
                    } else {
                        return this.options.positivePrefix;
                    }
                }
            };

            wijinputnumber.prototype._getInvertPrefix = function () {
                if (this._textProvider._stringFormat.isNegative()) {
                    if (this._userPositivePrefix !== undefined) {
                        return this._userPositivePrefix;
                    } else {
                        return this.options.positivePrefix;
                    }
                } else {
                    if (this._userNegativePrefix !== undefined) {
                        return this._userNegativePrefix;
                    } else {
                        return this.options.negativePrefix;
                    }
                }
            };

            wijinputnumber.prototype._getSuffix = function () {
                if (this._textProvider._stringFormat.isNegative()) {
                    if (this._userNegativeSuffix !== undefined) {
                        return this._userNegativeSuffix;
                    } else {
                        return this.options.negativeSuffix;
                    }
                } else {
                    if (this._userPositiveSuffix !== undefined) {
                        return this._userPositiveSuffix;
                    } else {
                        return this.options.positiveSuffix;
                    }
                }
            };

            wijinputnumber.prototype._getCurrencySymbol = function () {
                if (this._userCurrencySymbol !== undefined) {
                    return this._userCurrencySymbol;
                } else {
                    return this._getCulture().numberFormat.currency.symbol;
                }
            };

            wijinputnumber.prototype._getPercentSymbol = function () {
                return this._getCulture().numberFormat.percent.symbol;
            };

            /** Gets the value. */
            wijinputnumber.prototype.getValue = function () {
                if (this._textProvider._nullvalue) {
                    return null;
                }

                var val = this._textProvider.getValue();
                if (val === undefined || val === null) {
                    val = this.getText();
                }
                return val;
            };

            /** Sets the value.
            * @example
            * // set value of a wijinputnumber to 10
            * $(".selector").wijinputnumber("setValue", 10, true);
            */
            wijinputnumber.prototype.setValue = function (val, exact) {
                if (typeof exact === "undefined") { exact = false; }
                try  {
                    exact = !!exact;
                    if (val === null || typeof val === 'undefined' || isNaN(val)) {
                        val = null;
                    } else if (typeof val === 'boolean') {
                        val = val ? 1 : 0;
                    } else if (typeof val === 'string') {
                        val = this._textProvider.tryParseValue(val);
                    }

                    if (this._textProvider.setValue(val)) {
                        this._updateText();
                    } else {
                        if (exact) {
                            var prevVal = this.getText();
                            this.setText(val);
                            var txt = this.getText().trim();
                            val = val.trim();
                            if (txt !== val) {
                                this.setText(prevVal);
                            }
                        } else {
                            this.setText(val);
                        }
                    }

                    return true;
                } catch (e) {
                    return false;
                }
            };

            wijinputnumber.prototype._isLastValueNull = function () {
                return _super.prototype._isLastValueNull.call(this) && !this._textProvider._nullvalue;
            };

            /** Determines whether the value is in null state. */
            wijinputnumber.prototype.isValueNull = function () {
                try  {
                    return (this._textProvider).isValueNull();
                } catch (e) {
                    return true;
                }
            };

            /** Gets the text value when the container form is posted back to server. */
            wijinputnumber.prototype.getPostValue = function () {
                if (!this._isInitialized()) {
                    return this.element.val();
                }
                if (_super.prototype._showNullText.call(this) && this.isValueNull()) {
                    return "0";
                }

                var val = this.options.value ? this.options.value : 0;
                if (this.options.type === "percent") {
                    val = (val / 100).toFixed(10);
                }

                return val.toString();
            };

            wijinputnumber.prototype._updateText = function (keepSelection) {
                if (typeof keepSelection === "undefined") { keepSelection = false; }
                if (!this._isInitialized()) {
                    return;
                }

                if (this._textProvider._stringFormat.isNegative()) {
                    this.element.addClass(this.options.negativeClass);
                } else {
                    this.element.removeClass(this.options.negativeClass);
                }

                if (!this._textProvider._nullvalue) {
                    this.options.value = this._textProvider.getValue();
                } else {
                    this.options.value = null;
                }
                _super.prototype._updateText.call(this, keepSelection);
                if (!this._textProvider.checkAndRepairBounds(true, false)) {
                    this._trigger('valueBoundsExceeded');
                    if (!this.isFocused()) {
                        this._textProvider.setNullValue(false);
                        this.options.value = this._textProvider.getValue();
                        if (this._textProvider._stringFormat.isNegative()) {
                            this.element.addClass(this.options.negativeClass);
                        } else {
                            this.element.removeClass(this.options.negativeClass);
                        }
                        _super.prototype._updateText.call(this, keepSelection);
                    }
                }
            };

            wijinputnumber.prototype._doSpin = function (up, repeating, noFocus) {
                if (!this._allowEdit()) {
                    return false;
                }
                if (repeating && this.element.data('breakSpinner')) {
                    return false;
                }
                var selRange = this.element.wijtextselection(), rh = new input.wijInputResult();
                if (this.element.data('focusNotCalledFirstTime') !== -9 && (new Date().getTime() - this.element.data('focusNotCalledFirstTime')) < 600) {
                    this.element.data('focusNotCalledFirstTime', -9);
                    this.element.data('prevSelection', { start: 0, end: 0 });
                }
                if (this.element.data('prevSelection') === null) {
                    this.element.data('prevSelection', { start: selRange.start, end: selRange.start });
                } else {
                    selRange.start = (this.element.data('prevSelection').start);
                }
                rh.testPosition = selRange.start;
                if (this.options.increment < 0) {
                    var incrementBackup = this.options.increment;
                    this.options.increment *= -1;
                    this._textProvider.spinEnumPart(selRange.start, rh, this.options.increment, !up);
                    this.options.increment = incrementBackup;
                } else {
                    this._textProvider.spinEnumPart(selRange.start, rh, this.options.increment, up);
                }
                up ? this._trigger('spinUp', null) : this._trigger('spinDown', null);
                this._updateText();
                this.element.data('prevSelection', { start: rh.testPosition, end: rh.testPosition });
                if (!noFocus) {
                    this.selectText(rh.testPosition, rh.testPosition);
                }
                if (repeating && !this.element.data('breakSpinner')) {
                    var spintimer = window.setTimeout($.proxy(function () {
                        this._doSpin(up, true);
                    }, this), this._calcSpinInterval());
                    this.element.data("spintimer", spintimer);
                }
                return true;
            };

            wijinputnumber.prototype._deleteSelText = function (backspace) {
                if (typeof backspace === "undefined") { backspace = false; }
                var sel = this.element.wijtextselection(), everythingSelected = sel.start === 0 && sel.end === this.element.val().length, text;

                if (sel.start === sel.end) {
                    // move right if "delete" key is pressed and there cursor is to left from a group/decimal separator symbol
                    if (!backspace) {
                        text = this._textProvider._stringFormat._currentText;
                        if (text.charAt(sel.end) === this._textProvider.getGroupSeparator() || text.charAt(sel.end) === this._textProvider.getDecimalSeparator()) {
                            sel.start++;
                            sel.end++;
                            this.element.wijtextselection(sel);
                            return;
                        }
                    }
                }

                var previousValue = this._textProvider.getEditingValue();

                _super.prototype._deleteSelText.call(this, backspace);

                // this will set value to repaired max/min value.
                //this._textProvider.checkAndRepairBounds(true, false);
                //this.options.value = this._textProvider.getValue();
                //if ((everythingSelected || parseFloat(this.element.val()) === 0) &&  this.options.value === 0){
                if (previousValue === 0 && (everythingSelected || this._textProvider.getEditingValue() === 0)) {
                    // everything is selected
                    this._textProvider.setNullValue(true);
                    this._updateText(true);
                    this.options.value = null;
                }
            };

            wijinputnumber.prototype._processClearButton = function () {
                this._setOption("value", null);
            };

            wijinputnumber.prototype._processLeftRightKey = function (isLeftKey) {
                if (isLeftKey) {
                    if (this.element.wijtextselection().start === 0 && (this.options.blurOnLeftRightKey.toLowerCase() === "left" || this.options.blurOnLeftRightKey.toLowerCase() === "both")) {
                        input.CoreUtility.MoveFocus(this.element.get(0), false);
                        return true;
                    }
                } else {
                    if (this.element.wijtextselection().start === this.element.val().length && (this.options.blurOnLeftRightKey.toLowerCase() === "right" || this.options.blurOnLeftRightKey.toLowerCase() === "both")) {
                        input.CoreUtility.MoveFocus(this.element.get(0), true);
                        return true;
                    }
                }
                return false;
            };

            wijinputnumber.prototype._processTabKey = function (e) {
                var key = e.keyCode || e.which;
                switch (key) {
                    case jqKeyCode.TAB:
                        if (this.options.tabAction !== "field") {
                            this._trigger('keyExit');
                            break;
                        }
                        var dpPosition = this.element.val().indexOf('.');
                        if (dpPosition === -1) {
                            dpPosition = this.element.val().length;
                        }
                        var selRange = this.element.wijtextselection();
                        if (e.shiftKey) {
                            if (selRange.start > dpPosition) {
                                this._toPrevField();
                            }
                        } else {
                            if (selRange.start < dpPosition) {
                                this._toNextField();
                            }
                        }
                        return true;
                }
                return false;
            };

            wijinputnumber.prototype._toPrevField = function () {
                var prefix = this._getPrefix();

                //if (this.options.type === 'currency') {
                //    prefix = '$' + prefix;
                //}
                this.element.wijtextselection(prefix.length, prefix.length);
            };

            wijinputnumber.prototype._toNextField = function () {
                var dpPosition = this.element.val().indexOf('.');
                if (dpPosition === -1) {
                    this._toPrevField();
                } else {
                    this.element.wijtextselection(dpPosition + 1, dpPosition + 1);
                }
            };

            /** Performs spin up by the specified field and increment value. */
            wijinputnumber.prototype.spinUp = function () {
                this._doSpin(true, false, true);
            };

            /** Performs spin down by the specified field and increment value. */
            wijinputnumber.prototype.spinDown = function () {
                this._doSpin(false, false, true);
            };

            wijinputnumber.prototype._getRealNegativePrefix = function () {
                if (this._userNegativePrefix !== undefined) {
                    return this._userNegativePrefix.replace(/\$/g, this.options.currencySymbol);
                } else {
                    if (this.options.negativePrefix === null) {
                        return "";
                    }
                    return this.options.negativePrefix.replace(/\$/g, this.options.currencySymbol);
                }
            };

            wijinputnumber.prototype._getRealPositivePrefix = function () {
                if (this._userPositivePrefix !== undefined) {
                    return this._userPositivePrefix.replace(/\$/g, this.options.currencySymbol);
                } else {
                    if (this.options.positivePrefix === null) {
                        return "";
                    }
                    return this.options.positivePrefix.replace(/\$/g, this.options.currencySymbol);
                }
            };

            wijinputnumber.prototype._getRealNegativeSuffix = function () {
                if (this._userNegativeSuffix !== undefined) {
                    return this._userNegativeSuffix.replace(/\$/g, this.options.currencySymbol);
                } else {
                    if (this.options.negativeSuffix === null) {
                        return "";
                    }
                    return this.options.negativeSuffix.replace(/\$/g, this.options.currencySymbol);
                }
            };

            wijinputnumber.prototype._getRealPositiveSuffix = function () {
                if (this._userPositiveSuffix !== undefined) {
                    return this._userPositiveSuffix.replace(/\$/g, this.options.currencySymbol);
                } else {
                    if (this.options.positiveSuffix === null) {
                        return "";
                    }
                    return this.options.positiveSuffix.replace(/\$/g, this.options.currencySymbol);
                }
            };

            wijinputnumber.prototype._afterFocused = function () {
                if (this._isNullText()) {
                    _super.prototype._doFocus.call(this);
                } else {
                    this._doFocus();
                }
            };

            wijinputnumber.prototype._doFocus = function () {
                _super.prototype.focus.call(this);

                if (this.options.highlightText) {
                    this.element.wijtextselection(0, this.element.val().length);
                } else {
                    // if focused by calling this method, recover the caret position.
                    var prevPos = this.element.data('prevSelection');
                    if (prevPos) {
                        this.element.wijtextselection(prevPos.start, prevPos.end);
                    }
                }

                this.element.data('isFocusSelecting', true);
            };
            return wijinputnumber;
        })(input.wijinputcore);
        input.wijinputnumber = wijinputnumber;
        var wijinputnumber_options = (function () {
            function wijinputnumber_options() {
                this.wijCSS = {
                    wijinputnumber: input.wijinputcore.prototype.options.wijCSS.wijinput + "-numeric",
                    wijinputnumberNegative: "ui-state-negative"
                };
                /** Determines the type of the number input.
                * Possible values are: 'numeric', 'percent', 'currency'.
                */
                this.type = 'numeric';
                /** Determines the default numeric value.
                */
                this.value = 0;
                /** Determines the minimal value that can be entered for
                * numeric/percent/currency inputs.
                */
                this.minValue = -1000000000;
                /** Determines the maximum value that can be entered for
                * numeric/percent/currency inputs.
                */
                this.maxValue = 1000000000;
                /** Indicates whether the thousands group separator will be
                * inserted between between each digital group
                * (number of digits in thousands group depends on the selected Culture).
                */
                this.showGroup = false;
                /** Indicates the number of decimal places to display.
                * @remarks
                * Possible values are integer from -2 to 8.
                */
                this.decimalPlaces = 2;
                /** Determines how much to increase/decrease the active field when performing spin on the the active field.
                */
                this.increment = 1;
                /** Determine the current symbol when number type is currency.
                * @remarks
                * If the currencySymbol's value is null and number's type is currency, wijinputnumber will dispaly the currency symbol from the current culture, for use US culture, it is '$'.  <br />
                * But user can change this behavior by setting the currencySymbol option, then the '$' will changed to the specified value.
                */
                this.currencySymbol = null;
                /** Determine the prefix string used for negative value.
                * The default value will depend on the wijinputnumber's type option.
                */
                this.negativePrefix = null;
                /** Determine the suffix string used for negative value.
                * The default value will depend on the wijinputnumber's type option.
                */
                this.negativeSuffix = null;
                /** Determine the prefix string used for positive value.
                * The default value will depend on the wijinputnumber's type option.
                */
                this.positivePrefix = null;
                /** Determine the suffix stirng used for positive value.
                * The default value will depend on the wijinputnumber's type option.
                */
                this.positiveSuffix = null;
                /** @ignore */
                this.imeMode = '';
                /** Indicates whether to highlight the control's Text on receiving input focus.
                */
                this.highlightText = false;
                /** The valueChanged event handler.
                * A function called when the value of the input is changed.
                * @event
                * @dataKey value The new value */
                this.valueChanged = null;
                /** The spinUp event handler.
                * A function called when spin up event fired.
                * @event
                */
                this.spinUp = null;
                /** The spinDown event handler.
                * A function called when spin down event fired.
                * @event
                */
                this.spinDown = null;
                /** The valueBoundsExceeded event handler. A function called when
                * the value of the input exceeds the valid range.
                * @event
                */
                this.valueBoundsExceeded = null;
                this.negativeClass = this.wijCSS.wijinputnumberNegative;
            }
            return wijinputnumber_options;
        })();
        wijinputnumber.prototype.options = $.extend(true, {}, input.wijinputcore.prototype.options, new wijinputnumber_options());

        $.wijmo.registerWidget("wijinputnumber", wijinputnumber.prototype);

        //==============================
        /** @ignore */
        var wijNumberTextProvider = (function () {
            function wijNumberTextProvider(owner, type) {
                this._type = 'numeric';
                this._stringFormat = null;
                this._nullvalue = false;
                this.inputWidget = owner;
                this._type = type;
                this._stringFormat = new input.wijNumberFormat();
                this._stringFormat.setValueFromJSFloat(this.getValue(), this.inputWidget._getCulture(), this.inputWidget._getRealPositivePrefix(), this.inputWidget._getRealPositiveSuffix(), this.inputWidget._getRealNegativePrefix(), this.inputWidget._getRealNegativeSuffix(), this.inputWidget.options);
            }
            wijNumberTextProvider.prototype.getEditingValue = function () {
                return this._stringFormat.tryParseValue(this._stringFormat._strippedText, this.inputWidget._getCulture(), this.inputWidget.options);
            };
            wijNumberTextProvider.prototype._getCulture = function () {
                return this.inputWidget._getCulture();
            };

            wijNumberTextProvider.prototype.getDecimalSeparator = function () {
                return this._getCulture().numberFormat['.'];
            };

            wijNumberTextProvider.prototype.getGroupSeparator = function () {
                return this._getCulture().numberFormat[","];
            };

            wijNumberTextProvider.prototype.tryParseValue = function (value) {
                return this._stringFormat.tryParseValue(value, this.inputWidget._getCulture(), this.inputWidget.options);
            };

            wijNumberTextProvider.prototype.toString = function () {
                if (this.inputWidget._showNullText() && !this.inputWidget.isFocused() && this.isValueNull()) {
                    return this.inputWidget.options.nullText;
                }

                //if (!this.inputWidget._showNullText() && this.inputWidget.isValueNull()) {
                //    if (this.inputWidget._initialValue === null || isNaN(this.inputWidget._initialValue)) {
                //        return '';
                //    }
                //}
                if (this.isValueNull()) {
                    return "";
                }

                return this._stringFormat.getFormattedValue(this.inputWidget._initialValue, this.isValueNull(), this.inputWidget._getCulture(), this.inputWidget._getRealPositivePrefix(), this.inputWidget._getRealPositiveSuffix(), this.inputWidget._getRealNegativePrefix(), this.inputWidget._getRealNegativeSuffix(), this.inputWidget.options);
            };

            wijNumberTextProvider.prototype.isValueNull = function () {
                var o = this.inputWidget.options;

                //    nullValue = o.minValue;
                //nullValue = Math.max(0, o.minValue);
                //return null === o.value || undefined === o.value || nullValue === o.value || this._nullvalue;
                //for fix the issue 40695
                return null === o.value || undefined === o.value || this._nullvalue;
            };

            wijNumberTextProvider.prototype.setText = function (inputText, rh) {
                this.clear();
                this.insertAt(inputText, 0, rh);
                return true;
            };

            wijNumberTextProvider.prototype.clear = function () {
                this._stringFormat.clear();
            };

            wijNumberTextProvider.prototype.checkAndRepairBounds = function (chkAndRepair, onlyChkIsLessOrEqMin, allowWrap) {
                if (typeof allowWrap === "undefined") { allowWrap = false; }
                if (this._nullvalue) {
                    return true;
                }
                var result = true, minValue, maxValue;
                if (typeof (chkAndRepair) === 'undefined') {
                    chkAndRepair = false;
                }

                minValue = this.inputWidget.options.minValue;
                maxValue = this.inputWidget.options.maxValue;

                if (typeof (onlyChkIsLessOrEqMin) !== 'undefined' && onlyChkIsLessOrEqMin) {
                    return this._stringFormat.checkMinValue(minValue, false, true);
                }
                var needCheckMax = true;
                if (!this._stringFormat.checkMinValue(minValue, chkAndRepair, false)) {
                    result = false;
                    if (allowWrap) {
                        needCheckMax = false;
                        this._stringFormat._currentValueInString = maxValue.toString();
                    }
                }
                if (needCheckMax && !this._stringFormat.checkMaxValue(maxValue, chkAndRepair)) {
                    result = false;
                    if (allowWrap) {
                        this._stringFormat._currentValueInString = minValue.toString();
                    }
                }
                if (this.inputWidget.options.decimalPlaces >= 0) {
                    this._stringFormat.checkDigitsLimits(this.inputWidget.options.decimalPlaces);
                }

                return result;
            };

            wijNumberTextProvider.prototype._countSubstring = function (txt, subStr) {
                var c = 0, pos = txt.indexOf(subStr);
                while (pos !== -1) {
                    c++;
                    pos = txt.indexOf(subStr, pos + 1);
                }
                return c;
            };

            wijNumberTextProvider.prototype._getAdjustedPositionFromLeft = function (position) {
                var currentStrippedText = this._stringFormat._strippedText, i, ch;
                for (i = 0; i < currentStrippedText.length; i++) {
                    ch = currentStrippedText.charAt(i);
                    if (!$.wij.charValidator.isDigit(ch) && (ch !== this.getGroupSeparator() && ch !== this.getDecimalSeparator()) || ch === '0') {
                        if (this._stringFormat.isZero()) {
                            if (position < i) {
                                position++;
                            }
                        } else {
                            if (position <= i) {
                                position++;
                            }
                        }
                    } else {
                        break;
                    }
                }

                return position;
            };

            wijNumberTextProvider.prototype._getDecimalSeparatorPos = function () {
                var currentStrippedText = this._stringFormat._strippedText;
                return currentStrippedText.indexOf(this.getDecimalSeparator());
            };

            wijNumberTextProvider.prototype._removeLeadingZero = function (num) {
                var pos = 0;
                if (num.charAt(pos) === ' ' || num.charAt(pos) === this.inputWidget.options.currencySymbol) {
                    pos++;
                }

                var cultureObj = Globalize.findClosestCulture(this.inputWidget.options.culture);
                var nf = cultureObj.numberFormat, specificFormat = nf[this.inputWidget.options.type] || nf;

                while (num.charAt(pos) === '0' && num.charAt(pos + 1) !== specificFormat['.']) {
                    num = num.substr(0, pos) + num.substr(pos + 1);
                }

                return num;
            };

            wijNumberTextProvider.prototype.insertAt = function (strInput, position, rh) {
                var nf = this._getCulture().numberFormat, pos, slicePos, beginText, endText, newText, oldGroupSeparatorCount, newGroupSeparatorCount, leftPrevCh, leftCh;

                var currentTextWithoutMinus = this._stringFormat._strippedText;

                var prefix = this.inputWidget._getPrefix(), invertPrefix = this.inputWidget._getInvertPrefix();

                if (position < prefix.length) {
                    position = prefix.length;
                } else if (position > prefix.length + currentTextWithoutMinus.length) {
                    position = prefix.length + currentTextWithoutMinus.length;
                }
                position -= prefix.length;

                if (!rh) {
                    rh = new input.wijInputResult();
                }

                var isNullValueBackup = this._nullvalue;
                this.setNullValue(false);

                if (strInput.length === 1) {
                    if (strInput === '+') {
                        var signBefore = this._stringFormat.isNegative();
                        this._stringFormat.setPositiveSign();
                        this.checkAndRepairBounds(true, false);
                        var isInvert = signBefore !== this._stringFormat.isNegative();
                        if (isInvert) {
                            rh.testPosition = invertPrefix.length + position - 1;
                        } else {
                            rh.testPosition = prefix.length + position - 1;
                        }
                        return true;
                    }
                    if (strInput === '-' || strInput === ')' || strInput === '(') {
                        var isNegativeBefore = this._stringFormat.isNegative();
                        this._stringFormat.invertSign(this.inputWidget._getCulture(), this.inputWidget._getRealPositivePrefix(), this.inputWidget._getRealPositiveSuffix(), this.inputWidget._getRealNegativePrefix(), this.inputWidget._getRealNegativeSuffix(), this.inputWidget.options);
                        this.checkAndRepairBounds(true, false);
                        if (this._stringFormat.isNegative() === isNegativeBefore) {
                            rh.testPosition = prefix.length + position - 1;
                            return true;
                        } else {
                            rh.testPosition = invertPrefix.length + position - 1;

                            //if (this._stringFormat.isNegative()) {
                            //    rh.testPosition = position;
                            //}
                            //else {
                            //    rh.testPosition = position - 2;
                            //}
                            return true;
                        }
                    }
                    if (!$.wij.charValidator.isDigit(strInput)) {
                        if (strInput === this.getDecimalSeparator()) {
                            pos = this._getDecimalSeparatorPos() + prefix.length;

                            //if (this._stringFormat.isNegative()) {
                            //    pos = pos - 1;  // _stringFormat._currentText starts with '-'.
                            //}
                            if (pos >= 0) {
                                rh.testPosition = pos;
                                return true;
                            }
                        }
                        if (strInput !== this.getGroupSeparator() && strInput !== this.getDecimalSeparator() && strInput !== ')' && strInput !== '+' && strInput !== '-' && strInput !== '(' && strInput !== this.getDecimalSeparator()) {
                            if (this._type === 'percent' && strInput === nf.percent.symbol) {
                                rh.testPosition = position;
                                return true;
                            } else if (this._type === 'currency' && strInput === this.inputWidget.options.currencySymbol) {
                                rh.testPosition = position;
                                return true;
                            } else {
                                this.setNullValue(isNullValueBackup);
                                return false;
                            }
                        }
                    }
                }

                position = this._getAdjustedPositionFromLeft(position);
                slicePos = position;
                if (slicePos > currentTextWithoutMinus.length) {
                    slicePos = currentTextWithoutMinus.length - 1;
                }

                // if (input.length === 1) {
                // if (currentText.charAt(slicePos) === input) {
                // rh.testPosition = slicePos;
                // return true;
                // }
                // }
                beginText = this._removeLeadingZero(currentTextWithoutMinus.substring(0, slicePos));
                endText = currentTextWithoutMinus.substring(slicePos, currentTextWithoutMinus.length);
                if (this._stringFormat.isZero()) {
                    endText = endText.replace(/0/, '');
                }

                var filtratedText = strInput, sign = '';
                while (filtratedText.charAt(0) === '+' || filtratedText.charAt(0) === '-' || filtratedText.charAt(0) === ')' || filtratedText.charAt(0) === '(') {
                    sign = filtratedText.charAt(0);
                    filtratedText = filtratedText.substring(1);
                }
                filtratedText = filtratedText.replace(/[^0-9\.]/gi, "");
                var decimalPosition = filtratedText.indexOf('.');
                if (decimalPosition !== -1) {
                    var clips = filtratedText.split('.');
                    var integerString, decimalString;

                    integerString = clips.shift();
                    var decimalClips = clips;
                    decimalString = decimalClips.join('');

                    filtratedText = integerString + '.' + decimalString;
                } else {
                    filtratedText = filtratedText;
                }
                if (sign === '+') {
                    this._stringFormat.setPositiveSign();
                    this.checkAndRepairBounds(true, false);
                }
                if (sign === '-' || sign === ')' || sign === '(') {
                    this._stringFormat.invertSign(this.inputWidget._getCulture(), this.inputWidget._getRealPositivePrefix(), this.inputWidget._getRealPositiveSuffix(), this.inputWidget._getRealNegativePrefix(), this.inputWidget._getRealNegativeSuffix(), this.inputWidget.options);
                    this.checkAndRepairBounds(true, false);
                }

                rh.testPosition = prefix.length + beginText.length + filtratedText.length - 1;
                this._stringFormat.deFormatValue((this._stringFormat.isNegative() ? "-" : "") + beginText + filtratedText + endText, this.inputWidget._getCulture(), this.inputWidget._getRealPositivePrefix(), this.inputWidget._getRealPositiveSuffix(), this.inputWidget._getRealNegativePrefix(), this.inputWidget._getRealNegativeSuffix(), this.inputWidget.options);
                newText = this._stringFormat._strippedText;

                try  {
                    if (this.inputWidget.options.showGroup) {
                        oldGroupSeparatorCount = this._countSubstring(beginText, this._stringFormat._groupSeparator);
                        newGroupSeparatorCount = this._countSubstring(newText.substring(0, beginText.length + filtratedText.length), this._stringFormat._groupSeparator);
                        rh.testPosition += newGroupSeparatorCount - oldGroupSeparatorCount;
                    } else if (filtratedText.length === 1) {
                        leftPrevCh = beginText.charAt(beginText.length - 1);
                        leftCh = newText.charAt(beginText.length - 1);

                        //leftCh = newText.charAt(rh.testPosition - 1);
                        if (leftCh !== leftPrevCh) {
                            rh.testPosition--;
                        }
                    }
                } catch (e) {
                }

                return true;
            };

            wijNumberTextProvider.prototype.removeAt = function (start, end, rh, skipCheck) {
                if (typeof rh === "undefined") { rh = new input.wijInputResult(); }
                if (typeof skipCheck === "undefined") { skipCheck = false; }
                var nf = this._getCulture().numberFormat, curText, beginText, newText, decimalSepRemoved, oldGroupSeparatorCount, newGroupSeparatorCount;

                rh.testPosition = start;
                try  {
                    curText = this._stringFormat._currentText;
                    if ((start === end) && curText.substring(start, end + 1) === this.getDecimalSeparator()) {
                        return false;
                    }
                    beginText = curText.slice(0, start);

                    newText = beginText;
                    decimalSepRemoved = curText.slice(start, end + 1).indexOf(this.getDecimalSeparator()) >= 0;
                    if (decimalSepRemoved) {
                        newText += this.getDecimalSeparator();
                    }
                    newText += curText.slice(end + 1);
                    newText = newText || "0";
                    this._stringFormat.deFormatValue(newText, this.inputWidget._getCulture(), this.inputWidget._getRealPositivePrefix(), this.inputWidget._getRealPositiveSuffix(), this.inputWidget._getRealNegativePrefix(), this.inputWidget._getRealNegativeSuffix(), this.inputWidget.options);
                    newText = this._stringFormat._currentText;

                    this.setNullValue(false);

                    if (this.inputWidget.options.showGroup) {
                        if (decimalSepRemoved) {
                            rh.testPosition = newText.indexOf(this.getDecimalSeparator());
                        } else {
                            try  {
                                oldGroupSeparatorCount = this._countSubstring(beginText, this._stringFormat._groupSeparator);
                                newGroupSeparatorCount = this._countSubstring(newText.substring(0, Math.max(0, start - 1)), this._stringFormat._groupSeparator);
                                rh.testPosition -= oldGroupSeparatorCount - newGroupSeparatorCount;
                                if (curText.indexOf(this.inputWidget.options.currencySymbol) === rh.testPosition || curText.indexOf(nf.percent.symbol) === rh.testPosition) {
                                    rh.testPosition++;
                                }
                            } catch (e1) {
                            }
                        }
                    }

                    // if (!skipCheck){
                    // this.checkAndRepairBounds(true, false);
                    // }
                    return true;
                } catch (e2) {
                }

                // if (!skipCheck){
                // this.checkAndRepairBounds(true, false);
                // }
                return true;
            };

            wijNumberTextProvider.prototype.replaceWith = function (range, text) {
                if (text === '.' && this.inputWidget.options.decimalPlaces <= 0) {
                    var result = new input.wijInputResult();
                    result.testPosition = range.start - 1;
                    return result;
                }

                var shouldInvertAgain = false;
                if (this._stringFormat.isNegative() && text === '-' && range.text.length === this._stringFormat._currentText.length) {
                    shouldInvertAgain = true;
                }

                var superResult = this.superReplaceWith(range, text);

                if (shouldInvertAgain) {
                    this.insertAt('-', this.inputWidget.element.wijtextselection().start, superResult);
                }

                return superResult;
            };

            wijNumberTextProvider.prototype.superReplaceWith = function (range, text) {
                var index = range.start;
                var result = new input.wijInputResult();
                if (range.start < range.end) {
                    this.removeAt(range.start, range.end - 1, result, true);
                    index = result.testPosition;
                }
                return this.insertAt(text, index, result) ? result : null;
            };

            wijNumberTextProvider.prototype._parseNumber = function (strippedValue) {
                if (typeof strippedValue === "undefined") { strippedValue = this._stringFormat._currentValueInString; }
                var arr = strippedValue.split(".", 2);

                var retObj = {
                    integer: parseInt(arr[0], 10) || 0,
                    fraction: (arr.length > 1 ? parseInt(arr[1], 10) : 0) || 0,
                    isNegative: arr[0].indexOf('-') !== -1
                };

                if (retObj.integer === 0 && retObj.fraction === 0) {
                    retObj.isNegative = false;
                }

                return retObj;
            };

            wijNumberTextProvider.prototype._doSpin = function (delta, nullValue) {
                var num = this._parseNumber();

                var deltaDirection = delta >= 0 ? 1 : -1;
                var spinPosition = Math.abs(delta) >= 1 ? 'integer' : 'decimal';
                var deltaUnit = this.inputWidget.options.increment;
                if (deltaUnit >= Math.pow(10, this.inputWidget.options.decimalPlaces)) {
                    if (spinPosition === 'integer') {
                        deltaUnit = Math.abs(delta);
                    } else {
                        deltaUnit = Math.abs(delta) * Math.pow(10, this.inputWidget.options.decimalPlaces);
                    }
                }
                var deltaInPosition = deltaDirection * deltaUnit;

                var signPrefix = '', integerString, decimalString;

                var integerResult = num.integer, decimalResult = num.fraction;

                if (spinPosition === 'integer') {
                    integerResult = num.integer + deltaInPosition;
                    if (integerResult < 0) {
                        signPrefix = '-';
                        integerResult = -integerResult;
                    }
                } else if (spinPosition === 'decimal') {
                    var decimalValue = num.isNegative ? -num.fraction : num.fraction;
                    integerResult = num.integer;

                    if (decimalValue < 0) {
                        decimalResult = -Math.abs(decimalValue + deltaInPosition);
                        if (decimalValue * (decimalValue + deltaInPosition) < 0) {
                            integerResult = Math.abs(integerResult);
                            signPrefix = '-';
                        }
                    } else {
                        decimalResult = decimalValue + deltaInPosition;
                    }

                    if (decimalValue === 0 && num.isNegative) {
                        decimalResult = -Math.abs(decimalResult);
                        signPrefix = '-';
                        if (deltaDirection === 1) {
                            integerResult = Math.abs(integerResult);
                        }
                    }

                    if (decimalResult < 0) {
                        if (integerResult > 0) {
                            integerResult = integerResult - 1;
                            decimalResult = Math.pow(10, this.inputWidget.options.decimalPlaces) + decimalResult;
                        } else {
                            integerResult = Math.abs(num.integer);
                            decimalResult = Math.abs(decimalResult);
                            signPrefix = '-';
                        }
                    }
                }

                integerString = integerResult.toString();
                decimalString = decimalResult.toString();

                if (parseInt(this.inputWidget.options.decimalPlaces) > 0 && decimalString.length > parseInt(this.inputWidget.options.decimalPlaces)) {
                    integerResult++;
                    decimalString = decimalString.substring(1);
                    integerString = integerResult.toString();
                }

                while (decimalString.length < this.inputWidget.options.decimalPlaces) {
                    decimalString = '0' + decimalString;
                }

                if (integerString.indexOf('-') !== -1) {
                    signPrefix = '';
                }

                if (parseInt(integerString) === 0 && parseInt(decimalString) === 0) {
                    signPrefix = '';
                }
                if (nullValue) {
                    if (delta >= 0) {
                        this._stringFormat._currentValueInString = this.inputWidget.options.minValue.toString();
                    } else {
                        this._stringFormat._currentValueInString = this.inputWidget.options.maxValue.toString();
                    }
                } else {
                    this._stringFormat._currentValueInString = signPrefix + integerString + '.' + decimalString;
                }
            };
            wijNumberTextProvider.prototype.spinUp = function (val, nullValue) {
                if (val === null || val === undefined) {
                    val = 1;
                }
                this._doSpin(val, nullValue);
            };
            wijNumberTextProvider.prototype.spinDown = function (val, nullValue) {
                if (val === null || val === undefined) {
                    val = 1;
                }
                this._doSpin(-val, nullValue);
            };

            wijNumberTextProvider.prototype.spinEnumPart = function (position, rh, val, isIncrease) {
                if (!rh) {
                    rh = new input.wijInputResult();
                }
                val = parseInt(val.toString());
                var prefixBeforeSpin = this.inputWidget._getPrefix();
                var dpPosition = this._stringFormat._currentText.indexOf(this._getCulture().numberFormat['.']);
                var valueStringWithoutMinus = this._stringFormat._currentValueInString.replace('-', '');
                var dpPositionInValueString = valueStringWithoutMinus.indexOf('.');
                var hasDecimalPoint = true;
                if (dpPosition === -1) {
                    hasDecimalPoint = false;
                    dpPosition = this._stringFormat._currentText.length;
                }
                if (dpPositionInValueString === 0) {
                    dpPositionInValueString = 1;
                } else if (dpPositionInValueString === -1) {
                    dpPositionInValueString = dpPosition;
                }

                var scope = Math.pow(10, this.inputWidget.options.decimalPlaces);
                if (rh.testPosition > dpPosition && hasDecimalPoint) {
                    var fullVal = val;
                    val = val / scope;
                    if (Math.abs(val) >= 1) {
                        isIncrease ? this.spinUp(parseInt(val), this._nullvalue) : this.spinDown(parseInt(val), this._nullvalue);
                        val = (fullVal - parseInt(val) * scope) / scope; // prevent float precision problem.
                    }
                }

                isIncrease ? this.spinUp(val, this._nullvalue) : this.spinDown(val, this._nullvalue);

                this.setNullValue(false);
                var allowWrap = this.inputWidget.options.allowSpinLoop;
                this.checkAndRepairBounds(true, false, allowWrap);

                var valueStringWithoutMinusAfterSpin = this._stringFormat._currentValueInString.replace('-', '');
                var dpPositionInValueStringAfterSpin = valueStringWithoutMinusAfterSpin.indexOf('.');
                if (dpPositionInValueStringAfterSpin === -1) {
                    hasDecimalPoint = false;
                    dpPositionInValueStringAfterSpin = valueStringWithoutMinusAfterSpin.length;
                }
                var prefixAfterSpin = this.inputWidget._getPrefix();
                if (dpPositionInValueStringAfterSpin !== dpPositionInValueString && hasDecimalPoint) {
                    rh.testPosition = rh.testPosition - prefixBeforeSpin.length + prefixAfterSpin.length + dpPositionInValueStringAfterSpin - dpPositionInValueString;
                } else {
                    rh.testPosition = rh.testPosition - prefixBeforeSpin.length + prefixAfterSpin.length;
                }
            };

            wijNumberTextProvider.prototype.getValue = function () {
                return this._stringFormat.getJSFloatValue();
            };

            wijNumberTextProvider.prototype.setValue = function (val) {
                try  {
                    //if val is null, show null value instead of 0
                    if (val === null) {
                        this.setNullValue(true);
                        val = this.inputWidget._initialValue;
                    } else {
                        this.setNullValue(false);
                    }
                    this._stringFormat.setValueFromJSFloat(val, this.inputWidget._getCulture(), this.inputWidget._getRealPositivePrefix(), this.inputWidget._getRealPositiveSuffix(), this.inputWidget._getRealNegativePrefix(), this.inputWidget._getRealNegativeSuffix(), this.inputWidget.options);
                    this.checkAndRepairBounds(true, false);
                    return true;
                } catch (e) {
                    return false;
                }
            };

            wijNumberTextProvider.prototype.setNullValue = function (value) {
                this._nullvalue = value;
            };
            return wijNumberTextProvider;
        })();
        input.wijNumberTextProvider = wijNumberTextProvider;
    })(wijmo.input || (wijmo.input = {}));
    var input = wijmo.input;
})(wijmo || (wijmo = {}));

;
var wijmo;
(function (wijmo) {
    /// <reference path="../External/declarations/jquery.d.ts"/>
    /// <reference path="jquery.wijmo.wijcharex.ts" />
    /// <reference path="../wijutil/jquery.wijmo.wijutil.ts"/>
    (function (input) {
        /** @ignore */
        var CharacterType = (function () {
            function CharacterType() {
                this.DBCS_UpperAlphabet = 0x80000002;
                this.SBCS_UpperAlphabet = 0x40000001;
                this.DBCS_LowerAlphabet = 0x80000008;
                this.SBCS_LowerAlphabet = 0x40000004;
                this.DBCS_Number = 0x80000020;
                this.SBCS_Number = 0x40000010;
                this.DBCS_Binary = 0x80000080;
                this.SBCS_Binary = 0x40000040;
                this.DBCS_Hexadecimal = 0x80000200;
                this.SBCS_Hexadecimal = 0x40000100;
                this.DBCS_Symbol = 0x80000800;
                this.SBCS_Symbol = 0x40000400;
                this.DBCS_NumberSymbol = 0x80002000;
                this.SBCS_NumberSymbol = 0x40001000;
                this.DBCS_Katakana = 0x80008000;
                this.SBCS_Katakana = 0x40004000;
                this.DBCS_Space = 0x80020000;
                this.SBCS_Space = 0x40010000;
                this.TwoBytes = 0x80080000;
                this.FourBytes = 0x80040000;
                this.DBCS_ShiftJIS = 0x80100000;
                this.DBCS_JISX0208 = 0x80200000;
                this.Emoji = 0x00400000;
                this.IVS = 0x00800000;
                //add new format here
                this.DBCS_Hiragana = 0x81000000;
                this.Upper_SBCS_Katakana = 0x48000000;
                this.Upper_DBCS_Katakana = 0x90000000;
                this.Upper_DBCS_Hiragana = 0xA0000000;
                this.All = 0xC6000000;
                this.DBCS_All = 0x84000000;
                this.SBCS_All = 0x42000000;
                this.DBCS = 0x80000000;
                this.SBCS = 0x40000000;
            }
            return CharacterType;
        })();
        ;

        /** @ignore */
        var TextFilter = (function () {
            function TextFilter(autoConvert, format) {
                //Character type enum object
                this.charType = new CharacterType();

                //Indicates the format string.
                this.format = format;
                this.includeFormat = "";
                this.excludeFormat = "";
                this.includeNormalChar = "";
                this.excludeNormalChar = "";

                this.allowTypes = this.charType.All;
                this.excludeTypes = this.charType.All;

                //Wheher the format is "^"
                this.include = true;

                this.autoConvert = autoConvert;

                //this.allowSpace = allowSpace;
                //this.allowSpace = "None";
                //The CharProcess object
                this.charExInstance = input.CharProcess.CharEx;

                this.isInputValid = true;

                //Indicates which type is allowed.
                this.ParseFormat(this.format);
            }
            /// <summary>
            /// Gets whether the filter allow DBCS.
            /// </summary>
            TextFilter.prototype.allowDBCS = function () {
                return !(((this.allowTypes & this.charType.DBCS_All) != 0) ^ this.include);
            };

            /// <summary>
            /// Gets whether the filter allow SBCS.
            /// </summary>
            TextFilter.prototype.allowSBCS = function () {
                return !(((this.allowTypes & this.charType.SBCS_All) != 0) ^ this.include);
            };

            TextFilter.prototype.GetIncludeFormat = function (format) {
                if (format == null || format.GetLength() == 0) {
                    return "";
                }

                var includeFormat = "";

                for (var i = 0; i < format.GetLength(); i++) {
                    var currentChar = format.Substring(i, i + 1);

                    if (currentChar == '\\') {
                        if (i != format.GetLength() - 1) {
                            includeFormat = includeFormat + currentChar;
                            includeFormat = includeFormat + format.Substring(i + 1, i + 2);
                            i++;
                        } else {
                            throw "Exception.TextFilter.Format.Invalid";
                        }
                    } else if (currentChar == '^') {
                        return includeFormat;
                    } else {
                        includeFormat = includeFormat + currentChar;
                    }
                }

                return includeFormat;
            };

            TextFilter.prototype.GetExcludeFormat = function (format) {
                if (format == null || format.GetLength() == 0) {
                    return "";
                }

                var caretCount = 0;

                var excludeFormat = "";

                for (var i = 0; i < format.GetLength(); i++) {
                    var currentChar = format.Substring(i, i + 1);

                    if (currentChar == '\\') {
                        if (i != format.GetLength() - 1) {
                            if (caretCount != 0) {
                                excludeFormat = excludeFormat + currentChar;
                                excludeFormat = excludeFormat + format.Substring(i + 1, i + 2);
                            }
                            i++;
                        } else {
                            throw "Exception.TextFilter.Format.Invalid";
                        }
                    } else if (currentChar == '^') {
                        caretCount++;

                        if (caretCount > 1) {
                            throw "Exception.TextFilter.Format.DuplicatedChar";
                        }
                    } else {
                        if (caretCount != 0) {
                            excludeFormat = excludeFormat + currentChar;
                        }
                    }
                }

                if (caretCount == 1) {
                    excludeFormat = '^' + excludeFormat;
                }

                return excludeFormat;
            };

            TextFilter.prototype.ParseIncludeFormat = function (format) {
                if (format == null || format.GetLength() == 0) {
                    this.allowTypes = this.charType.All;
                    this.includeNormalChar = "";
                    this.includeFormat = "";
                    return;
                }

                this.allowTypes = 0;
                this.includeNormalChar = "";
                for (var i = 0; i < format.GetLength(); i++) {
                    switch (format.charCodeAt(i)) {
                        case 94:
                            break;
                        case 92:
                            if (i == format.GetLength() - 1) {
                                throw "Exception.TextFilter.Format.Invalid";
                            }
                            this.includeNormalChar = this.includeNormalChar + format.Substring(i + 1, i + 2);
                            i++;
                            break;
                        case 65313:
                            if ((this.allowTypes & this.charType.DBCS_UpperAlphabet) == (this.charType.DBCS_UpperAlphabet | 0))
                                ;
                            else
                                this.allowTypes |= this.charType.DBCS_UpperAlphabet;
                            break;

                        case 65:
                            if ((this.allowTypes & this.charType.SBCS_UpperAlphabet) == this.charType.SBCS_UpperAlphabet)
                                ;
                            else
                                this.allowTypes |= this.charType.SBCS_UpperAlphabet;
                            break;

                        case 65345:
                            if ((this.allowTypes & this.charType.DBCS_LowerAlphabet) == (this.charType.DBCS_LowerAlphabet | 0))
                                ;
                            else
                                this.allowTypes |= this.charType.DBCS_LowerAlphabet;
                            break;

                        case 97:
                            if ((this.allowTypes & this.charType.SBCS_LowerAlphabet) == this.charType.SBCS_LowerAlphabet)
                                ;
                            else
                                this.allowTypes |= this.charType.SBCS_LowerAlphabet;
                            break;

                        case 65323:
                            if ((this.allowTypes & this.charType.DBCS_Katakana) == (this.charType.DBCS_Katakana | 0))
                                ;
                            else
                                this.allowTypes |= this.charType.DBCS_Katakana;
                            break;

                        case 75:
                            if ((this.allowTypes & this.charType.SBCS_Katakana) == this.charType.SBCS_Katakana)
                                ;
                            else
                                this.allowTypes |= this.charType.SBCS_Katakana;
                            break;

                        case 65305:
                            if ((this.allowTypes & this.charType.DBCS_Number) == (this.charType.DBCS_Number | 0))
                                ;
                            else
                                this.allowTypes |= this.charType.DBCS_Number;
                            break;

                        case 57:
                            if ((this.allowTypes & this.charType.SBCS_Number) == this.charType.SBCS_Number)
                                ;
                            else
                                this.allowTypes |= this.charType.SBCS_Number;
                            break;

                        case 65283:
                            if ((this.allowTypes & this.charType.DBCS_NumberSymbol) == (this.charType.DBCS_NumberSymbol | 0))
                                ;
                            else
                                this.allowTypes |= this.charType.DBCS_NumberSymbol;
                            break;

                        case 35:
                            if ((this.allowTypes & this.charType.SBCS_NumberSymbol) == this.charType.SBCS_NumberSymbol)
                                ;
                            else
                                this.allowTypes |= this.charType.SBCS_NumberSymbol;
                            break;

                        case 65312:
                            if ((this.allowTypes & this.charType.DBCS_Symbol) == (this.charType.DBCS_Symbol | 0))
                                ;
                            else
                                this.allowTypes |= this.charType.DBCS_Symbol;
                            break;

                        case 64:
                            if ((this.allowTypes & this.charType.SBCS_Symbol) == this.charType.SBCS_Symbol)
                                ;
                            else
                                this.allowTypes |= this.charType.SBCS_Symbol;
                            break;

                        case 65314:
                            if ((this.allowTypes & this.charType.DBCS_Binary) == (this.charType.DBCS_Binary | 0))
                                ;
                            else
                                this.allowTypes |= this.charType.DBCS_Binary;
                            break;

                        case 66:
                            if ((this.allowTypes & this.charType.SBCS_Binary) == this.charType.SBCS_Binary)
                                ;
                            else
                                this.allowTypes |= this.charType.SBCS_Binary;
                            break;

                        case 65336:
                            if ((this.allowTypes & this.charType.DBCS_Hexadecimal) == (this.charType.DBCS_Hexadecimal | 0))
                                ;
                            else
                                this.allowTypes |= this.charType.DBCS_Hexadecimal;
                            break;

                        case 88:
                            if ((this.allowTypes & this.charType.SBCS_Hexadecimal) == this.charType.SBCS_Hexadecimal)
                                ;
                            else
                                this.allowTypes |= this.charType.SBCS_Hexadecimal;
                            break;

                        case 65322:
                            if ((this.allowTypes & this.charType.DBCS_Hiragana) == (this.charType.DBCS_Hiragana | 0))
                                ;
                            else
                                this.allowTypes |= this.charType.DBCS_Hiragana;
                            break;

                        case 65338:
                            if ((this.allowTypes & this.charType.DBCS_All) == (this.charType.DBCS_All | 0))
                                ;
                            else
                                this.allowTypes |= this.charType.DBCS_All;
                            break;
                        case 65325:
                            if ((this.allowTypes & this.charType.DBCS_ShiftJIS) == (this.charType.DBCS_ShiftJIS | 0))
                                ;
                            else
                                this.allowTypes |= this.charType.DBCS_ShiftJIS;
                            break;
                        case 65321:
                            if ((this.allowTypes & this.charType.DBCS_JISX0208) == (this.charType.DBCS_JISX0208 | 0))
                                ;
                            else
                                this.allowTypes |= this.charType.DBCS_JISX0208;
                            break;
                        case 72:
                            if ((this.allowTypes & this.charType.SBCS_All) == this.charType.SBCS_All)
                                ;
                            else
                                this.allowTypes |= this.charType.SBCS_All;
                            break;
                        case 78:
                            if ((this.allowTypes & this.charType.Upper_SBCS_Katakana) == this.charType.Upper_SBCS_Katakana)
                                ;
                            else
                                this.allowTypes |= this.charType.Upper_SBCS_Katakana;
                            break;
                        case 65326:
                            if ((this.allowTypes & this.charType.Upper_DBCS_Katakana) == this.charType.Upper_DBCS_Katakana)
                                ;
                            else
                                this.allowTypes |= this.charType.Upper_DBCS_Katakana;
                            break;
                        case 65319:
                            if ((this.allowTypes & this.charType.Upper_DBCS_Hiragana) == this.charType.Upper_DBCS_Hiragana)
                                ;
                            else
                                this.allowTypes |= this.charType.Upper_DBCS_Hiragana;
                            break;
                        case 65331:
                            if ((this.allowTypes & this.charType.DBCS_Space) == this.charType.DBCS_Space)
                                ;
                            else
                                this.allowTypes |= this.charType.DBCS_Space;
                            break;
                        case 83:
                            if ((this.allowTypes & this.charType.SBCS_Space) == this.charType.SBCS_Space)
                                ;
                            else
                                this.allowTypes |= this.charType.SBCS_Space;
                            break;
                        case 65332:
                            if ((this.allowTypes & this.charType.FourBytes) == this.charType.FourBytes)
                                ;
                            else
                                this.allowTypes |= this.charType.FourBytes;
                            break;
                        case 65316:
                            if ((this.allowTypes & this.charType.TwoBytes) == this.charType.TwoBytes)
                                ;
                            else
                                this.allowTypes |= this.charType.TwoBytes;
                            break;
                        case 65317:
                            this.allowTypes |= this.charType.Emoji;
                            break;
                        case 65334:
                            this.allowTypes |= this.charType.IVS;
                            break;
                        default:
                            this.includeNormalChar = this.includeNormalChar + format.Substring(i, i + 1);
                            break;
                    }
                }
            };

            TextFilter.prototype.ParseExcludeFormat = function (format) {
                if (format == null || format.GetLength() == 0) {
                    this.excludeTypes = this.excludeTypes.All;
                    this.excludeNormalChar = "";
                    this.excludeFormat = "";
                    return;
                }

                if (format == "^") {
                    this.excludeTypes = this.charType.All;
                    this.excludeNormalChar = "";
                    this.excludeFormat = "^";
                    return;
                }

                this.excludeTypes = 0;
                this.excludeNormalChar = "";
                for (var i = 0; i < format.GetLength(); i++) {
                    switch (format.charCodeAt(i)) {
                        case 94:
                            break;
                        case 92:
                            if (i == format.GetLength() - 1) {
                                throw "Exception.TextFilter.Format.Invalid";
                            }
                            this.excludeNormalChar = this.excludeNormalChar + format.Substring(i + 1, i + 2);
                            i++;
                            break;
                        case 65313:
                            if ((this.excludeTypes & this.charType.DBCS_UpperAlphabet) == (this.charType.DBCS_UpperAlphabet | 0))
                                ;
                            else
                                this.excludeTypes |= this.charType.DBCS_UpperAlphabet;
                            break;

                        case 65:
                            if ((this.excludeTypes & this.charType.SBCS_UpperAlphabet) == this.charType.SBCS_UpperAlphabet)
                                ;
                            else
                                this.excludeTypes |= this.charType.SBCS_UpperAlphabet;
                            break;

                        case 65345:
                            if ((this.excludeTypes & this.charType.DBCS_LowerAlphabet) == (this.charType.DBCS_LowerAlphabet | 0))
                                ;
                            else
                                this.excludeTypes |= this.charType.DBCS_LowerAlphabet;
                            break;

                        case 97:
                            if ((this.excludeTypes & this.charType.SBCS_LowerAlphabet) == this.charType.SBCS_LowerAlphabet)
                                ;
                            else
                                this.excludeTypes |= this.charType.SBCS_LowerAlphabet;
                            break;

                        case 65323:
                            if ((this.excludeTypes & this.charType.DBCS_Katakana) == (this.charType.DBCS_Katakana | 0))
                                ;
                            else
                                this.excludeTypes |= this.charType.DBCS_Katakana;
                            break;

                        case 75:
                            if ((this.excludeTypes & this.charType.SBCS_Katakana) == this.charType.SBCS_Katakana)
                                ;
                            else
                                this.excludeTypes |= this.charType.SBCS_Katakana;
                            break;

                        case 65305:
                            if ((this.excludeTypes & this.charType.DBCS_Number) == (this.charType.DBCS_Number | 0))
                                return;
                            else
                                this.excludeTypes |= this.charType.DBCS_Number;
                            break;

                        case 57:
                            if ((this.excludeTypes & this.charType.SBCS_Number) == this.charType.SBCS_Number)
                                ;
                            else
                                this.excludeTypes |= this.charType.SBCS_Number;
                            break;

                        case 65283:
                            if ((this.excludeTypes & this.charType.DBCS_NumberSymbol) == (this.charType.DBCS_NumberSymbol | 0))
                                ;
                            else
                                this.excludeTypes |= this.charType.DBCS_NumberSymbol;
                            break;

                        case 35:
                            if ((this.excludeTypes & this.charType.SBCS_NumberSymbol) == this.charType.SBCS_NumberSymbol)
                                ;
                            else
                                this.excludeTypes |= this.charType.SBCS_NumberSymbol;
                            break;

                        case 65312:
                            if ((this.excludeTypes & this.charType.DBCS_Symbol) == (this.charType.DBCS_Symbol | 0))
                                ;
                            else
                                this.excludeTypes |= this.charType.DBCS_Symbol;
                            break;

                        case 64:
                            if ((this.excludeTypes & this.charType.SBCS_Symbol) == this.charType.SBCS_Symbol)
                                ;
                            else
                                this.excludeTypes |= this.charType.SBCS_Symbol;
                            break;

                        case 65314:
                            if ((this.excludeTypes & this.charType.DBCS_Binary) == (this.charType.DBCS_Binary | 0))
                                ;
                            else
                                this.excludeTypes |= this.charType.DBCS_Binary;
                            break;

                        case 66:
                            if ((this.excludeTypes & this.charType.SBCS_Binary) == this.charType.SBCS_Binary)
                                ;
                            else
                                this.excludeTypes |= this.charType.SBCS_Binary;
                            break;

                        case 65336:
                            if ((this.excludeTypes & this.charType.DBCS_Hexadecimal) == (this.charType.DBCS_Hexadecimal | 0))
                                ;
                            else
                                this.excludeTypes |= this.charType.DBCS_Hexadecimal;
                            break;

                        case 88:
                            if ((this.excludeTypes & this.charType.SBCS_Hexadecimal) == this.charType.SBCS_Hexadecimal)
                                ;
                            else
                                this.excludeTypes |= this.charType.SBCS_Hexadecimal;
                            break;

                        case 65322:
                            if ((this.excludeTypes & this.charType.DBCS_Hiragana) == (this.charType.DBCS_Hiragana | 0))
                                ;
                            else
                                this.excludeTypes |= this.charType.DBCS_Hiragana;
                            break;

                        case 65338:
                            if ((this.excludeTypes & this.charType.DBCS_All) == (this.charType.DBCS_All | 0))
                                ;
                            else
                                this.excludeTypes |= this.charType.DBCS_All;
                            break;
                        case 65325:
                            if ((this.excludeTypes & this.charType.DBCS_ShiftJIS) == (this.charType.DBCS_ShiftJIS | 0))
                                ;
                            else
                                this.excludeTypes |= this.charType.DBCS_ShiftJIS;
                            break;
                        case 65321:
                            if ((this.excludeTypes & this.charType.DBCS_JISX0208) == (this.charType.DBCS_JISX0208 | 0))
                                ;
                            else
                                this.excludeTypes |= this.charType.DBCS_JISX0208;
                            break;
                        case 72:
                            if ((this.excludeTypes & this.charType.SBCS_All) == this.charType.SBCS_All)
                                ;
                            else
                                this.excludeTypes |= this.charType.SBCS_All;
                            break;
                        case 78:
                            if ((this.excludeTypes & this.charType.Upper_SBCS_Katakana) == this.charType.Upper_SBCS_Katakana)
                                ;
                            else
                                this.excludeTypes |= this.charType.Upper_SBCS_Katakana;
                            break;
                        case 65326:
                            if ((this.excludeTypes & this.charType.Upper_DBCS_Katakana) == this.charType.Upper_DBCS_Katakana)
                                ;
                            else
                                this.excludeTypes |= this.charType.Upper_DBCS_Katakana;
                            break;
                        case 65319:
                            if ((this.excludeTypes & this.charType.Upper_DBCS_Hiragana) == this.charType.Upper_DBCS_Hiragana)
                                ;
                            else
                                this.excludeTypes |= this.charType.Upper_DBCS_Hiragana;
                            break;
                        case 65331:
                            if ((this.excludeTypes & this.charType.DBCS_Space) == this.charType.DBCS_Space)
                                ;
                            else
                                this.excludeTypes |= this.charType.DBCS_Space;
                            break;
                        case 83:
                            if ((this.excludeTypes & this.charType.SBCS_Space) == this.charType.SBCS_Space)
                                ;
                            else
                                this.excludeTypes |= this.charType.SBCS_Space;
                            break;
                        case 65332:
                            if ((this.excludeTypes & this.charType.FourBytes) == this.charType.FourBytes)
                                ;
                            else
                                this.excludeTypes |= this.charType.FourBytes;
                            break;
                        case 65316:
                            if ((this.excludeTypes & this.charType.TwoBytes) == this.charType.TwoBytes)
                                ;
                            else
                                this.excludeTypes |= this.charType.TwoBytes;
                            break;
                        case 65317:
                            this.excludeTypes |= this.charType.Emoji;
                            break;
                        case 65334:
                            this.excludeTypes |= this.charType.IVS;
                            break;
                        default:
                            this.excludeNormalChar = this.excludeNormalChar + format.Substring(i, i + 1);
                            break;
                    }
                }
            };

            /**
            *Parses the format string and get a filter to check character.
            *@param format - The format string
            *@return  Return the text filter object
            */
            TextFilter.prototype.ParseFormat = function (format) {
                this.includeFormat = this.GetIncludeFormat(format);
                this.excludeFormat = this.GetExcludeFormat(format);

                this.ParseIncludeFormat(this.includeFormat);
                this.ParseExcludeFormat(this.excludeFormat);
            };

            TextFilter.prototype.IsValidProcess = function (c, charType, normalChar) {
                if (normalChar.IndexOf(c) != -1)
                    return true;

                if (c == '\x09' || c == '\x0D' || c == '\x0A')
                    return true;

                if (charType == 0)
                    return false;

                // Check the character type.
                var isValid = false;

                if (charType == this.charType.All)
                    return true;

                if ((charType & this.charType.Emoji) == (this.charType.Emoji | 0) && this.IsEmoji(c)) {
                    return true;
                }

                if ((charType & this.charType.IVS) == (this.charType.IVS | 0) && this.IsIVS(c)) {
                    return true;
                }
                if ((charType & this.charType.FourBytes) == (this.charType.FourBytes | 0) && this.IsFourBytes(c))
                    return true;

                if (c.GetLength() == 1 && c.length > 1) {
                    // DaryLuo 2013/04/28 fix bug 1061, 1062 in IM Web 7.1
                    return false;
                }

                if ((charType & this.charType.DBCS_ShiftJIS) == (this.charType.DBCS_ShiftJIS | 0) && this.IsShiftJIS(c))
                    return true;

                if (this.charExInstance.IsFullWidth(c)) {
                    if ((charType & this.charType.DBCS) != (this.charType.DBCS | 0))
                        return false;

                    if ((charType & this.charType.DBCS_All) == (this.charType.DBCS_All | 0) && c != '\u3000')
                        isValid = true;
                    else if ((charType & this.charType.DBCS_LowerAlphabet) == (this.charType.DBCS_LowerAlphabet | 0) && this.IsLower(c))
                        isValid = true;
                    else if ((charType & this.charType.DBCS_UpperAlphabet) == (this.charType.DBCS_UpperAlphabet | 0) && this.IsUpper(c))
                        isValid = true;
                    else if ((charType & this.charType.DBCS_Number) == (this.charType.DBCS_Number | 0) && this.IsNumber(c))
                        isValid = true;
                    else if ((charType & this.charType.DBCS_Binary) == (this.charType.DBCS_Binary | 0) && this.IsBinary(c))
                        isValid = true;
                    else if ((charType & this.charType.DBCS_Hexadecimal) == (this.charType.DBCS_Hexadecimal | 0) && this.IsHex(c))
                        isValid = true;
                    else if ((charType & this.charType.DBCS_Symbol) == (this.charType.DBCS_Symbol | 0) && this.IsSymbol(c))
                        isValid = true;
                    else if ((charType & this.charType.DBCS_NumberSymbol) == (this.charType.DBCS_NumberSymbol | 0) && this.IsNumberSymbol(c))
                        isValid = true;
                    else if ((charType & this.charType.DBCS_Katakana) == (this.charType.DBCS_Katakana | 0) && this.IsKatakana(c)) {
                        //2012/08/17, Robin Hotfix Bug#37.
                        // The char '\u30FC' is hiranaga while it is katakana type.
                        // So !Include will have some special logic for checking chars in the intersection.
                        //isValid = true;
                        var isMixedJPChar = this.IsHiragana(c);
                        if (isMixedJPChar) {
                            if (this.include) {
                                isValid = true;
                            } else {
                                isValid = ((charType & this.charType.DBCS_Hiragana) == (this.charType.DBCS_Hiragana | 0));
                            }
                        } else {
                            isValid = true;
                        }
                    } else if ((charType & this.charType.DBCS_Hiragana) == (this.charType.DBCS_Hiragana | 0) && this.IsHiragana(c)) {
                        //isValid = true;
                        var isMixedJPChar = this.IsKatakana(c);
                        if (isMixedJPChar) {
                            if (this.include) {
                                isValid = true;
                            } else {
                                isValid = ((charType & this.charType.DBCS_Katakana) == (this.charType.DBCS_Katakana | 0));
                            }
                        } else {
                            isValid = true;
                        }
                    } else if ((charType & this.charType.DBCS_JISX0208) == (this.charType.DBCS_JISX0208 | 0) && this.IsJISX0208(c))
                        isValid = true;
                    else if ((charType & this.charType.Upper_DBCS_Katakana) == (this.charType.Upper_DBCS_Katakana | 0) && this.IsKatakana(c) && this.IsUpperKana(c))
                        isValid = true;
                    else if ((charType & this.charType.Upper_DBCS_Hiragana) == (this.charType.Upper_DBCS_Hiragana | 0) && this.IsHiragana(c) && this.IsUpperKana(c))
                        isValid = true;
                    else if ((charType & this.charType.DBCS_Space) == (this.charType.DBCS_Space | 0) && this.IsFormatSpace(c))
                        isValid = true;
                    else if ((charType & this.charType.FourBytes) == (this.charType.FourBytes | 0) && this.IsFourBytes(c))
                        isValid = true;
                    else if ((charType & this.charType.TwoBytes) == (this.charType.TwoBytes | 0) && !this.IsFourBytes(c) && c != '\u3000')
                        isValid = true;
                } else {
                    if ((charType & this.charType.SBCS) != this.charType.SBCS)
                        return false;
                    if ((charType & this.charType.SBCS_All) == this.charType.SBCS_All && c != '\x20')
                        isValid = true;
                    else if ((charType & this.charType.SBCS_LowerAlphabet) == this.charType.SBCS_LowerAlphabet && this.IsLower(c))
                        isValid = true;
                    else if ((charType & this.charType.SBCS_UpperAlphabet) == this.charType.SBCS_UpperAlphabet && this.IsUpper(c))
                        isValid = true;
                    else if ((charType & this.charType.SBCS_Number) == this.charType.SBCS_Number && this.IsNumber(c))
                        isValid = true;
                    else if ((charType & this.charType.SBCS_Binary) == this.charType.SBCS_Binary && this.IsBinary(c))
                        isValid = true;
                    else if ((charType & this.charType.SBCS_Hexadecimal) == this.charType.SBCS_Hexadecimal && this.IsHex(c))
                        isValid = true;
                    else if ((charType & this.charType.SBCS_Symbol) == this.charType.SBCS_Symbol && this.IsSymbol(c))
                        isValid = true;
                    else if ((charType & this.charType.SBCS_NumberSymbol) == this.charType.SBCS_NumberSymbol && this.IsNumberSymbol(c))
                        isValid = true;
                    else if ((charType & this.charType.SBCS_Katakana) == this.charType.SBCS_Katakana && this.IsKatakana(c))
                        isValid = true;
                    else if ((charType & this.charType.Upper_SBCS_Katakana) == this.charType.Upper_SBCS_Katakana && this.IsKatakana(c) && this.IsUpperKana(c))
                        isValid = true;
                    else if ((charType & this.charType.SBCS_Space) == this.charType.SBCS_Space && this.IsFormatSpace(c))
                        isValid = true;
                }

                return isValid;
            };

            TextFilter.prototype.IsIncludeValid = function (c) {
                return this.IsValidProcess(c, this.allowTypes, this.includeNormalChar);
            };

            TextFilter.prototype.IsExcludeValid = function (c) {
                return this.IsValidProcess(c, this.excludeTypes, this.excludeNormalChar);
            };

            /**
            *Check whether the character is valid.
            *@param c - The character to be checked
            *@return Return the value indicating whether the character is valid
            */
            TextFilter.prototype.IsValid = function (c) {
                if (this.excludeFormat != "") {
                    if (!this.IsExcludeValid(c)) {
                        if (this.includeFormat != "") {
                            return this.IsIncludeValid(c);
                        }
                    } else {
                        return false;
                    }
                } else {
                    if (this.includeFormat != "") {
                        return this.IsIncludeValid(c);
                    }
                }

                return true;
            };

            TextFilter.prototype.IsFormatSpace = function (c) {
                if (c == '\x20' || c == '\u3000') {
                    return true;
                } else {
                    return false;
                }
            };

            TextFilter.prototype.IsFourBytes = function (c) {
                var charEx = input.CharProcess.CharEx;
                var textElement = c.Substring(0, 1);
                if (textElement.length > 1) {
                    for (var i = 0; i < textElement.length; i++) {
                        if (charEx.IsSurrogate(textElement[i])) {
                            return true;
                        }
                    }
                }
                return false;
            };

            TextFilter.prototype.IsUpper = function (c) {
                return this.charExInstance.IsUpper(c);
            };

            TextFilter.prototype.IsLower = function (c) {
                return this.charExInstance.IsLower(c);
            };

            TextFilter.prototype.IsNumber = function (c) {
                return this.charExInstance.IsDigit(c);
            };

            TextFilter.prototype.IsBinary = function (c) {
                c = this.IsFullWidth(c) ? this.ToHalfWidth(c) : c;
                return (c == '0' || c == '1');
            };

            TextFilter.prototype.IsHex = function (c) {
                c = this.IsFullWidth(c) ? this.ToHalfWidth(c) : c;
                return (c == 'A' || c == 'B' || c == 'C' || c == 'D' || c == 'E' || c == 'F' || c == 'a' || c == 'b' || c == 'c' || c == 'd' || c == 'e' || c == 'f' || this.IsDigit(c));
            };

            TextFilter.prototype.IsSymbol = function (c) {
                return this.charExInstance.IsHalfWidthSymbol(c) || this.charExInstance.IsFullWidthSymbol(c);
            };

            TextFilter.prototype.IsNumberSymbol = function (c) {
                c = this.IsFullWidth(c) ? this.ToHalfWidth(c) : c;
                return (this.IsDigit(c) || c == '+' || c == '-' || c == '$' || c == '%' || c == '\\' || c == ',' || c == '.');
            };

            TextFilter.prototype.IsKatakana = function (c) {
                return this.charExInstance.IsKatakana(c);
            };

            TextFilter.prototype.IsHiragana = function (c) {
                return this.charExInstance.IsHiragana(c);
            };

            TextFilter.prototype.IsShiftJIS = function (c) {
                return this.charExInstance.IsShiftJIS(c);
            };

            TextFilter.prototype.IsJISX0208 = function (c) {
                return this.charExInstance.IsJISX0208(c);
            };

            TextFilter.prototype.IsEmoji = function (c) {
                var ref = {};

                //return EmojiHelper.IsEmoji(c, 0, ref);
                return false;
            };

            TextFilter.prototype.IsIVS = function (c) {
                var ref = {};

                //return IVSCharHelper.IsIVSElement(c, 0, ref);
                return false;
            };

            TextFilter.prototype.IsDBCS = function (c) {
                return this.IsFullWidth(c);
            };

            TextFilter.prototype.IsSBCS = function (c) {
                return !this.IsFullWidth(c);
            };

            TextFilter.prototype.IsFullWidth = function (c) {
                return this.charExInstance.IsFullWidth(c);
            };

            //commented by Kevin, May 21, 2007
            //Bug#7960, JIS2004
            TextFilter.prototype.IsSurrogatePair = function (c) {
                return this.charExInstance.IsSurrogatePair(c);
            };

            //end by Kevin
            TextFilter.prototype.ToHalfWidth = function (c) {
                return this.charExInstance.ToHalfWidth(c);
            };

            TextFilter.prototype.IsDigit = function (c) {
                return this.charExInstance.IsDigit(c);
            };

            /// <summary>
            ///   Checks whether the speical character is a upper case katakana character.
            /// </summary>
            /// <param name="c">
            ///   A <b>char</b> indicates the character to be checked.
            /// </param>
            /// <returns>
            ///   If the character is a upper case katakana character, return <b>true</b>, otherwise, return <b>false</b>.
            /// </returns>
            TextFilter.prototype.IsUpperKana = function (c) {
                return this.charExInstance.IsUpperKana(c);
            };

            TextFilter.prototype.CheckValidSpace = function (character) {
                if ((character == '\x20') && ((this.allowTypes & this.charType.SBCS_Space) == (this.charType.SBCS_Space | 0))) {
                    return true;
                } else if ((character == '\u3000') && ((this.allowTypes & this.charType.DBCS_Space) == (this.charType.DBCS_Space | 0))) {
                    return true;
                }
                return false;
            };

            //	/// <summary>
            //	/// Check whether the character is valid.
            //	/// </summary>
            //	/// <param name="text">The string to be checked.</param>
            //	/// <param name="index">The character index in the string.</param>
            //	/// <returns>The convert string.</returns
            TextFilter.prototype.Check = function (text, index) {
                var character;

                if (index != null) {
                    character = text.Substring(index, index + 1);
                } else {
                    character = text;
                }

                var isValid = this.IsValid(character);
                if (isValid) {
                    return character;
                }

                //		}
                if (this.autoConvert) {
                    if (index != null) {
                        return this.Convert(text, index);
                    } else {
                        return this.Convert(character);
                    }
                }
                return "";
            };

            TextFilter.prototype.CheckText = function (text) {
                var length = text.GetLength();
                var ret = { IsInputValid: true, CheckedText: "" };
                for (var i = 0; i < length;) {
                    var c = text.Substring(i, i + 1);

                    if (c != "\t" && c != "\r" && c != "\n") {
                        var temp = this.Check(text, i);

                        if (temp.index != null) {
                            i = temp.index;
                            c = temp.strValue;
                        } else {
                            c = temp;
                            i++;
                        }

                        if (c == "") {
                            ret.IsInputValid = false;
                        }
                    } else {
                        i++;
                    }
                    ret.CheckedText += c;
                }

                return ret;
            };

            /// <summary>
            /// Convert the character in the special index.
            /// </summary>
            /// <param name="text">The string to be checked.</param>
            /// <param name="index">The character index in the string.</param>
            /// <returns>The convert string.</returns>
            TextFilter.prototype.Convert = function (text, index) {
                var c;
                if (index == null) {
                    c = text;
                } else {
                    c = text.Substring(index, index + 1);
                }

                var isValid = false;

                // Convert between upper and lower alphabet automatically.
                if (this.charExInstance.IsAlphabet(c)) {
                    var r = this.charExInstance.IsLower(c) ? c.toUpperCase() : c.toLowerCase();
                    isValid = this.IsValid(r);
                    if (isValid) {
                        return r;
                    }

                    c = this.charExInstance.IsFullWidth(c) ? this.charExInstance.ToHalfWidth(c) : this.charExInstance.ToFullWidth(c).text;
                    isValid = this.IsValid(c);
                    if (isValid) {
                        return c;
                    }

                    r = this.charExInstance.IsFullWidth(r) ? this.charExInstance.ToHalfWidth(r) : this.charExInstance.ToFullWidth(r).text;
                    isValid = this.IsValid(r);
                    if (isValid) {
                        return r;
                    }
                    return "";
                }

                // Convert from Hiragana to other styles automatically.
                if (this.charExInstance.IsHiragana(c)) {
                    // Large < - > Small
                    if (this.charExInstance.IsLowerKana(c)) {
                        var u = this.charExInstance.ToUpperKana(c);
                        isValid = this.IsValid(u);
                        if (isValid) {
                            return u;
                        }
                    } else if (this.charExInstance.HasLowerKana(c)) {
                        var l = this.charExInstance.ToLowerKana(c);
                        isValid = this.IsValid(l);
                        if (isValid) {
                            return l;
                        }
                    }

                    // Hiragana to DBCS Katakana
                    var r = this.charExInstance.ToKatakana(c);
                    isValid = this.IsValid(r);
                    if (isValid) {
                        return r;
                    }

                    if (this.charExInstance.IsLowerKana(r)) {
                        var u = this.charExInstance.ToUpperKana(r);
                        isValid = this.IsValid(u);
                        if (isValid) {
                            return u;
                        }
                    } else if (this.charExInstance.HasLowerKana(r)) {
                        var l = this.charExInstance.ToLowerKana(r);
                        isValid = this.IsValid(l);
                        if (isValid) {
                            return l;
                        }
                    }

                    // Hiragana to SBCS Katakana
                    var chars = this.charExInstance.ToHalfWidthEx(r);
                    isValid = this.IsValid(chars);
                    if (isValid) {
                        return chars;
                    }

                    if (this.charExInstance.IsLowerKana(chars)) {
                        chars = this.charExInstance.ToUpperKana(chars);
                        isValid = this.IsValid(chars);
                        if (isValid) {
                            return chars;
                        }
                    } else if (this.charExInstance.HasLowerKana(chars)) {
                        chars = this.charExInstance.ToLowerKana(chars);
                        isValid = this.IsValid(chars);
                        if (isValid) {
                            return chars;
                        }
                    }
                    return "";
                }

                // Convert from Katakana to Hiragana (or DBCS <-> SBCS)automatically.
                if (this.charExInstance.IsKatakana(c)) {
                    // Large < - > Small
                    if (this.charExInstance.IsLowerKana(c)) {
                        var u = this.charExInstance.ToUpperKana(c);
                        isValid = this.IsValid(u);
                        if (isValid) {
                            return u;
                        }
                    } else if (this.charExInstance.HasLowerKana(c)) {
                        var l = this.charExInstance.ToLowerKana(c);
                        isValid = this.IsValid(l);
                        if (isValid) {
                            return l;
                        }
                    }

                    // DBCS < - > SBCS
                    var processedAll = false;
                    var r = c;
                    if (this.charExInstance.IsFullWidth(c)) {
                        var newChars = this.charExInstance.ToHalfWidthEx(c);

                        if (newChars.GetLength() > 0) {
                            isValid = this.IsValid(newChars);
                            if (isValid) {
                                return newChars;
                            }
                        }
                        if (this.charExInstance.IsLowerKana(newChars)) {
                            newChars = this.charExInstance.ToUpperKana(newChars);
                            isValid = this.IsValid(newChars);
                            if (isValid) {
                                return newChars;
                            }
                        } else if (this.charExInstance.HasLowerKana(newChars)) {
                            newChars = this.charExInstance.ToLowerKana(newChars);
                            isValid = this.IsValid(newChars);
                            if (isValid) {
                                return newChars;
                            }
                        }
                    } else {
                        if (index == null) {
                            r = this.charExInstance.ToFullWidth(c).text;

                            if (!this.charExInstance.IsKatakana(r))
                                return "";

                            isValid = this.IsValid(r);
                            if (isValid) {
                                return r;
                            }
                        } else {
                            if ((index + 1) < text.GetLength()) {
                                var convertObj = this.charExInstance.ToFullWidth(text.Substring(index, index + 2));
                                r = convertObj.text;
                                processedAll = convertObj.processedAll;
                            } else {
                                r = this.charExInstance.ToFullWidth(c).text;
                            }

                            if (!this.charExInstance.IsKatakana(r)) {
                                return "";
                            }

                            isValid = this.IsValid(r);
                            if (isValid) {
                                index++;
                                if (processedAll)
                                    index++;
                                return { index: index, strValue: r };
                            }
                        }
                        if (this.charExInstance.IsLowerKana(r)) {
                            var u = this.charExInstance.ToUpperKana(r);
                            isValid = this.IsValid(u);
                            if (isValid) {
                                return u;
                            }
                        } else if (this.charExInstance.HasLowerKana(r)) {
                            var l = this.charExInstance.ToLowerKana(r);
                            isValid = this.IsValid(l);
                            if (isValid) {
                                return l;
                            }
                        }
                    }

                    r = this.charExInstance.ToHiragana(r);
                    isValid = this.IsValid(r);
                    if (isValid) {
                        if (index != null) {
                            index++;
                            if (processedAll)
                                index++;
                            var retObj = { index: index, strValue: r };

                            //add by sj for bug 2955
                            if (r == '\u3094') {
                                if (processedAll) {
                                    retObj.strValue = '\u3046' + '\u309B';
                                } else {
                                    retObj.strValue = "";
                                }
                            }

                            //end by sj
                            return retObj;
                        } else {
                            //add by sj for bug 2955
                            if (r == '\u3094') {
                                return "";
                            }

                            //end by sj
                            return r;
                        }
                    }
                    if (this.charExInstance.IsLowerKana(r)) {
                        var u = this.charExInstance.ToUpperKana(r);
                        isValid = this.IsValid(u);
                        if (isValid) {
                            return u;
                        }
                    } else if (this.charExInstance.HasLowerKana(r)) {
                        var l = this.charExInstance.ToLowerKana(r);
                        isValid = this.IsValid(l);
                        if (isValid) {
                            return l;
                        }
                    }
                }

                // Convert between DBCS and SBCS automatically.
                c = this.charExInstance.IsFullWidth(c) ? this.charExInstance.ToHalfWidth(c) : this.charExInstance.ToFullWidth(c).text;

                //		var ret = this.IsSpace(c);
                //		if (ret.IsSpace && this.CheckCharByAllowSpace(ret.Character, this.allowSpace))
                //		{
                //			return ret.Character;
                //		}
                isValid = this.IsValid(c);
                if (isValid) {
                    return c;
                }
                return "";
            };
            return TextFilter;
        })();
        input.TextFilter = TextFilter;
        ;
    })(wijmo.input || (wijmo.input = {}));
    var input = wijmo.input;
})(wijmo || (wijmo = {}));
$.wijinputcore = $.wijinputcore || {};
;

$.wijinputcore.validateText = $.wijinputcore.validateText || function (value, arg1, arg2) {
    if (arg2 === undefined) {
        //Check format.
        var filter = new wijmo.input.TextFilter(false, arg1);
        var ret = filter.CheckText(value);
        var formatedText = ret.CheckedText;
        if (formatedText === value) {
            return true;
        } else {
            return false;
        }
    } else {
        //Check length
        var length = value.length;
        if (length < arg1 || length > arg2) {
            return false;
        } else {
            return true;
        }
    }
};
;
/// <reference path="jquery.wijmo.wijstringinfo.ts"/>
/// <reference path="jquery.wijmo.wijinputcore.ts"/>
/// <reference path="jquery.wijmo.wijinpututility.ts"/>
/// <reference path="jquery.wijmo.wijinputtextformat.ts"/>
/// <reference path="../wijtooltip/jquery.wijmo.wijtooltip.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*globals jQuery */
    /*
    * Depends:
    *	jquery-1.4.2.js
    *	jquery.ui.core.js
    *	jquery.ui.widget.js
    *	jquery.wijmo.wijcharex.js
    *	jquery.wijmo.wijstringinfo.js
    *	jquery.wijmo.wijinputcore.js
    *
    */
    (function (_input) {
        var $ = jQuery, widgetName = "wijinputtext";

        var EllipsisMode = (function () {
            function EllipsisMode() {
            }
            EllipsisMode.None = "none";
            EllipsisMode.EllipsisEnd = "ellipsisEnd";
            EllipsisMode.EllipsisPath = "ellipsisPath";
            return EllipsisMode;
        })();

        var OutputMode;
        (function (OutputMode) {
            OutputMode[OutputMode["Append"] = 0] = "Append";
            OutputMode[OutputMode["Replace"] = 1] = "Replace";
        })(OutputMode || (OutputMode = {}));

        var ImeMode = (function () {
            function ImeMode() {
            }
            ImeMode.Auto = "auto";
            ImeMode.Active = "active";
            ImeMode.Disabled = "disabled";
            ImeMode.Inactive = "inactive";
            return ImeMode;
        })();

        /** @widget */
        var wijinputtext = (function (_super) {
            __extends(wijinputtext, _super);
            function wijinputtext() {
                _super.apply(this, arguments);
            }
            wijinputtext.prototype._getIMTextBox = function () {
                if (this.imtextbox === undefined) {
                    this.imtextbox = new IMTextBox(this.element[0], this.outerDiv);
                }
                return this.imtextbox;
            };

            wijinputtext.prototype._create = function () {
                _super.prototype._create.call(this);
                var self = this, element = self.element, multiline = element[0].nodeName.toLowerCase() === "textarea";
                self.imtextbox = self._getIMTextBox();
                element.attribute({
                    "role": "textbox",
                    "aria-label": "wijinputtext",
                    "aria-multiline": multiline
                });
            };

            wijinputtext.prototype._init = function () {
                _super.prototype._init.call(this);
                if (this.options.disableUserInput) {
                    this.imtextbox.SetReadOnly(true);
                }
                this.imtextbox.placeHolder = this.options.nullText ? this.options.nullText : "";
                var self = this;
                self.imtextbox.disabledClassName = self.widgetFullName + "-disabled";
                this.imtextbox.readingImeStringOutputEvent = function (e, data) {
                    self._trigger('readingImeStringOutput', null, data);
                };
                this.imtextbox.InvalidInputEvent = function (e, data) {
                    self._fireIvalidInputEvent(data);
                }; //this._trigger('invalidInput', { char: data, widget: this }); };
                this.imtextbox.SetAutoConvert(this.options.autoConvert);
                this.imtextbox.SetExitOnLastChar(this.options.blurOnLastChar);
                this.imtextbox.SetExitOnLeftRightKey(this.options.blurOnLeftRightKey);
                this.imtextbox.SetFormat(this.options.format);
                this.imtextbox.SetMaxLength(this.options.maxLength);
                this.imtextbox.SetHighlightText(this.options.highlightText);
                this.imtextbox.SetOverflowTip(this.options.showOverflowTip);

                this.imtextbox.SetMaxLineCount(this.options.maxLineCount);

                this.imtextbox.SetCountWrappedLine(this.options.countWrappedLine);

                //if (this.options.passwordChar === null) {
                //    this.options.passwordChar = this.imtextbox.SystemPasswordChar();
                //}
                //this.imtextbox.SetPasswordChar(this.options.passwordChar);
                if (this.options.invalidInput !== null) {
                    this.imtextbox.OnInvalidInput(this.options.invalidInput);
                }
                if (this.options.keyExit !== null) {
                    this.imtextbox.OnKeyExit(this.options.keyExit);
                }

                //if (this.options.textChanged !== null) {
                //    this.imtextbox.OnTextChanged(this.options.textChanged);
                //}
                this.imtextbox.TextChangedEvent = function (e, data) {
                    self.options.text = data;
                    if (self._hiddenInput) {
                        self._hiddenInput.val(self.getPostValue());
                    }
                    self.element.data('preText', data);
                    self.element.data('changed', true);
                    self._trigger('textChanged', null, { text: data });
                };

                var e = this.element, wijCSS = this.options.wijCSS, allowedNodes = { 'input': true, 'textarea': true }, allowedInputTypes = {
                    'text': true, 'password': true,
                    'email': true, 'url': true
                }, nodeName = e.get(0).nodeName.toLowerCase();

                //// enable touch support:
                //if (window.wijmoApplyWijTouchUtilEvents) {
                //    $ = window.wijmoApplyWijTouchUtilEvents($);
                //}
                if (!allowedNodes.hasOwnProperty(nodeName)) {
                    return;
                }
                if ((nodeName === 'input') && this.element.attr("type") && !allowedInputTypes.hasOwnProperty(this.element.attr("type").toLowerCase())) {
                    return;
                }
                if (nodeName === 'input') {
                    this.imtextbox.SetMultiLine(false);

                    if (this.element.attr('type') === 'password') {
                        var passwordChar;
                        if (this.options.passwordChar) {
                            passwordChar = this.options.passwordChar;
                        } else {
                            passwordChar = this.imtextbox.SystemPasswordChar();
                        }
                        this.imtextbox.SetPasswordChar(passwordChar);
                        //TODO. fisheye button.
                    }
                } else if (nodeName === 'textarea') {
                    this.imtextbox.SetMultiLine(true);
                }
                this.imtextbox.SetLengthAsByte(this.options.lengthAsByte);
                if (this.options.text === null) {
                    var text = this.getText();
                    if (text != this.imtextbox.placeHolder) {
                        this.options.text = text;
                    }
                }
                if (!(this.options.text === this.imtextbox.placeHolder && this.imtextbox.isNullText)) {
                    this.setText(this.options.text);
                }
                this.imtextbox.SetEllipsisString(this.options.ellipsisString);
                this.imtextbox.SetEllipsis(this.options.ellipsis);

                //for case 20899
                if (e.is(":disabled")) {
                    this._setOption("disabled", true);
                    e.addClass(wijCSS.stateDisabled);
                } else {
                    this._setOption("disabled", false);
                    e.removeClass(wijCSS.stateDisabled);
                }
                if (this.options.passwordChar) {
                    this.imtextbox.SetPasswordChar(this.options.passwordChar);
                }
                this.element.data('changed', false);
            };

            /**
            * Remove the functionality completely. This will return the element back to its pre-init state.
            */
            wijinputtext.prototype.destroy = function () {
                var self = this, wijCSS = self.options.wijCSS;
                self.element.removeClass(wijCSS.widget).removeClass(wijCSS.stateDefault).removeClass(wijCSS.cornerAll).removeClass(wijCSS.stateHover).removeClass(wijCSS.stateActive).off("." + self.widgetName);

                self.element.off('.imtextbox');
                _super.prototype.destroy.call(this);
            };

            /** Gets the selected text.
            */
            wijinputtext.prototype.getSelectedText = function () {
                return this.imtextbox.GetSelectedText();
            };

            wijinputtext.prototype._setOption = function (key, value) {
                switch (key) {
                    case 'nullText':
                    case 'placeholder':
                        this.imtextbox.placeHolder = value;
                        break;
                }

                _super.prototype._setOption.call(this, key, value);

                switch (key) {
                    case 'autoConvert':
                        this.imtextbox.SetAutoConvert(value);
                        break;

                    case 'blurOnLastChar':
                        this.imtextbox.SetExitOnLastChar(value);
                        break;

                    case 'blurOnLeftRightKey':
                        this.imtextbox.SetExitOnLeftRightKey(value);
                        break;

                    case 'showDropDownButton':
                        var ellipsis = this.imtextbox.GetEllipsis();
                        this.imtextbox.SetEllipsis(ellipsis);
                        this.imtextbox.AddWijmoControlEvent();
                        break;
                    case 'ellipsis':
                        this.imtextbox.SetEllipsis(value);
                        break;

                    case 'ellipsisString':
                        this.imtextbox.SetEllipsisString(value);
                        break;

                    case 'highlightText':
                        this.imtextbox.SetHighlightText(value);
                        break;

                    case 'showOverflowTip':
                        this.imtextbox.SetOverflowTip(value);
                        break;

                    case 'format':
                        this.imtextbox.SetFormat(value);
                        break;

                    case 'maxLineCount':
                        this.imtextbox.SetMaxLineCount(value);
                        break;

                    case 'countWrappedLine':
                        this.imtextbox.SetCountWrappedLine(value);
                        break;

                    case 'lengthAsByte':
                        this.imtextbox.SetLengthAsByte(value);
                        break;

                    case 'maxLength':
                        this.imtextbox.SetMaxLength(value);
                        break;

                    case 'readonly':
                    case 'disableUserInput':
                        this.imtextbox.SetReadOnly(value);
                        break;

                    case 'passwordChar':
                        this.imtextbox.SetPasswordChar(value);
                        break;

                    case 'text':
                        this.setText(value);
                        break;

                    case 'invalidInput':
                        this.imtextbox.OnInvalidInput(value);
                        break;

                    case 'keyExit':
                        this.imtextbox.OnKeyExit(value);
                        break;

                    case '':
                        break;
                }
            };

            // Stop binding event handler in wijinputcore
            //_onFocus(e) {
            //}
            //_onBlur(e) {
            //}
            wijinputtext.prototype._updateTextOnLostFocus = function () {
                if (this.imtextbox.PasswordMode) {
                    return;
                }
                _super.prototype._updateTextOnLostFocus.call(this);
            };
            wijinputtext.prototype._onMouseUp = function (e) {
            };
            wijinputtext.prototype._onCompositionStart = function () {
            };
            wijinputtext.prototype._onCompositionEnd = function () {
            };
            wijinputtext.prototype._onChange = function () {
            };
            wijinputtext.prototype._onPaste = function (e) {
            };
            wijinputtext.prototype._onDrop = function (e) {
            };
            wijinputtext.prototype._onKeyDown = function (e) {
                var k = this._getKeyCode(e);
                var jqKeyCode = wijmo.getKeyCodeEnum();
                if (this.options.disableUserInput) {
                    if (k === jqKeyCode.TAB) {
                        if (this._processTabKey(e)) {
                            this._stopEvent(e);
                        }
                    } else {
                        this._stopEvent(e);
                    }
                    return;
                }

                if (this._processKeyForDropDownList(e)) {
                    return;
                }

                if (k === jqKeyCode.ENTER) {
                    this._onEnterDown(e);
                    if (this.options.autoPostBack) {
                        this._stopEvent(e);
                    }
                }
            };
            wijinputtext.prototype._onKeyPress = function (e) {
                if (this.options.disableUserInput) {
                    return;
                }

                var k = this._getKeyCode(e);
                var jqKeyCode = wijmo.getKeyCodeEnum();

                if (k === jqKeyCode.ENTER) {
                    this._onEnterDown(e);
                }
            };
            wijinputtext.prototype._onKeyUp = function (e) {
                if (this.options.disableUserInput) {
                    this._raiseTextChanged();
                    this._raiseDataChanged();
                    return;
                }
            };

            wijinputtext.prototype._createTextProvider = function () {
                this._textProvider = new wijInputTextProvider(this);
            };

            /** Selects a range of text in the widget.
            * @param {Number} start Start of the range.
            * @param {Number} end End of the range.
            * @example
            * // Select first two symbols in a wijinputtext
            * $(".selector").wijinputtext("selectText", 0, 2);
            */
            wijinputtext.prototype.selectText = function (start, end) {
                if (typeof start === "undefined") { start = 0; }
                if (typeof end === "undefined") { end = this.getText().length; }
                if (isNaN(start)) {
                    start = 0;
                }
                if (isNaN(end)) {
                    end = 0;
                }
                if (this.element.is(':disabled')) {
                    return;
                }

                if (_input.CoreUtility.IsFireFox4OrLater()) {
                    this.focus();
                }

                this.imtextbox.SetSelection(start, end);
            };

            wijinputtext.prototype._updateText = function () {
                if (this.element.data("initialized")) {
                    _super.prototype._updateText.call(this);

                    // DaryLuo 2014/04/04 fix bug 50687.
                    // placeHolder value should never set to the option's text value.
                    if (this.imtextbox && this.options.text === this.imtextbox.placeHolder) {
                        this.options.text = "";
                    }
                }
            };
            return wijinputtext;
        })(_input.wijinputcore);
        _input.wijinputtext = wijinputtext;

        var wijinputtext_options = (function () {
            function wijinputtext_options() {
                /** Selector option for auto self initialization. This option is internal.
                * @ignore
                */
                this.initSelector = ":jqmData(role='wijinput')";
                /** wijtextbox css, extend from $.wijmo.wijCSS
                * @ignore
                */
                this.wijCSS = {};
                /** Gets whether the control automatically converts to the proper format according to the format setting.
                */
                this.autoConvert = true;
                /** Determines whether or not the next control in the tab order receives
                * the focus as soon as the control is filled at the last character.
                */
                this.blurOnLastChar = false;
                /** Gets or set whether the focus automatically moves to the next or previous
                * tab ordering control when pressing the left, right arrow keys.
                */
                this.blurOnLeftRightKey = 'none';
                /** Gets or sets how to display the Ellipsis string when the control's content is
                * longer than its Width.
                * @exluce
                */
                this.ellipsis = EllipsisMode.None;
                /** Gets or sets the Ellipsis string shows in the control.
                */
                this.ellipsisString = String.fromCharCode(8230);
                /** Gets or sets whether display the OverflowTip.
                */
                this.showOverflowTip = false;
                /**Gets or sets whether to highlight the control's Text on receiving input focus.
                */
                this.highlightText = false;
                /** Determines the format string that defines the type of text
                * allowed for input in the control.
                *
                * @remarks
                * The following key words are supported.
                * DBCS Keywords:
                *   Ａ Upper case DBCS alphabet (A-Z).
                *   ａ Lower case DBCS alphabet (a-z).
                *   Ｋ DBCS Katakana.
                *   ９ DBCS Numbers (0-9).
                *   ＃ DBCS numbers and number related symbols (0-9, +-$%\,.).
                *   ＠ DBCS symbols.
                *   Ｊ Hiragana.
                *   Ｚ All DBCS characters without Space.
                *   Ｎ Only DBCS large Katakanas.
                *   Ｇ Only DBCS large Hiragana.
                *   Ｔ Only allow surrogate char.
                *   Ｄ All DBCS characters, except for surrogates.
                *   Ｓ DBCS space.
                * SBCS Keywords:
                *   A Upper case alphabet (A-Z).
                *   a Lower case alphabet (a-z).
                *   K Katakana.
                *   9 Numbers (0-9).
                *   # Numbers and number related symbols (0-9, +-$%\,.).
                *   @ Symbols.
                *   H All SBCS characters without Space.
                *   N Only SBCS large Katakanas.
                *   S SBCS Space.
                *   ^ Any character not included in the specified format.
                *   \ Escape character.
                * For example, format = 'Ａ', then the wijinputtext can only input the upper case DBCS alphabet.
                * If you input the SBCS 'k', then it will be automatic conver to DBCS 'Ｋ' if the autoConvert is true,
                * But if the autoConvert is false, you can't input 'k'.
                */
                this.format = '';
                /** Sets the Ime Mode setting of widget.
                * Possible values are: 'auto', 'active', 'inactive', 'disabled'
                */
                this.imeMode = 'auto';
                /** Determines whether the maximum length constraint for
                * input is byte-based or character-based.
                */
                this.lengthAsByte = false;
                /**  Determines the maximum length of text that can be input
                *  in the control.
                */
                this.maxLength = 0;
                /**  Determines the max count of lines can be input into the Edit control.
                */
                this.maxLineCount = 0;
                /** Determines whether to treat the wrapped lines as one line or multiple lines
                * when counting the lines count.
                */
                this.countWrappedLine = false;
                /**  Determines the password char.
                */
                this.passwordChar = '';
                /** Determines the text of the wijinputtext.
                */
                this.text = null;
                /** @ignore */
                this.allowSpinLoop = false;
                /** @ignore */
                this.spinnerAlign = "verticalRight";
                /** @ignore */
                this.showSpinner = false;
                /** @ignore */
                this.culture = '';
                /** The readingImeStringOutput event handler.
                * A function called when the japanese reading ime string is generated.
                * @event
                * @dataKey {readingString} the generaged reading ime string.
                */
                this.readingImeStringOutput = null;
            }
            return wijinputtext_options;
        })();

        wijinputtext.prototype.options = $.extend(true, {}, _input.wijinputcore.prototype.options, new wijinputtext_options());

        $.wijmo.registerWidget(widgetName, wijinputtext.prototype);

        /** @ignore */
        var wijInputTextProvider = (function () {
            function wijInputTextProvider(owner) {
                this.inputWidget = owner;
            }
            //insertAt(strInput: string, position: number, rh?: wijInputResult) {
            //    return true;
            //}
            wijInputTextProvider.prototype.toString = function (ignorePasswordChar) {
                if (this.inputWidget._showNullText() && !this.inputWidget.isFocused() && this.isValueNull()) {
                    this.inputWidget.element.data('isShowNullText', true);
                    return this.inputWidget.options.nullText;
                } else if ((!this.inputWidget._showNullText() || this.inputWidget.isFocused()) && this.inputWidget.element.data('isShowNullText')) {
                    this.inputWidget.element.data('isShowNullText', false);
                    return '';
                } else if (this.inputWidget.imtextbox && this.inputWidget.imtextbox.GetPasswordChar()) {
                    if (ignorePasswordChar) {
                        return this.inputWidget.options.text;
                    } else {
                        return this.inputWidget.imtextbox._getInputValueWithPlaceHolder();
                    }
                } else if (this.inputWidget.imtextbox) {
                    return this.inputWidget.imtextbox._getInputValueWithPlaceHolder();
                } else if (this.inputWidget.options.text != null) {
                    return this.inputWidget.options.text;
                } else {
                    return this.inputWidget.element.val();
                }
            };

            wijInputTextProvider.prototype.isValueNull = function () {
                if (this.inputWidget.imtextbox) {
                    return this.inputWidget.imtextbox.isNullText;
                } else {
                    return true;
                }
            };

            wijInputTextProvider.prototype.setText = function (text) {
                this.inputWidget.imtextbox.SetText(text);
            };

            wijInputTextProvider.prototype.replaceWith = function (range, text) {
                var index = range.start;
                var result = new _input.wijInputResult();
                if (range.start < range.end) {
                    this.removeAt(range.start, range.end - 1, result, true);
                    index = result.testPosition;
                }
                return this.insertAt(text, index, result) ? result : null;
            };
            wijInputTextProvider.prototype.insertAt = function (char, index, rh) {
            };
            wijInputTextProvider.prototype.removeAt = function (start, end, rh, skipCheck) {
            };
            return wijInputTextProvider;
        })();
        _input.wijInputTextProvider = wijInputTextProvider;

        /** @ignore */
        var IMTextBox = (function () {
            function IMTextBox(element, container) {
                this.ToolTip = null;
                this.placeHolder = "";
                this.disabledClassName = "";
                //#endregion
                this.Focused = false;
                this.InputElement = element;
                this._container = container;

                // if the input element doesn't has an id, we'll set a temporary id to support history list cookie.
                if (this.InputElement.id === '') {
                    this.InputElement.id = 'wijmo_input_' + _input.Utility.IdCounter++;
                }

                //this.ID = this.GetId();
                //if (container === undefined || container === null) {
                //    throw "Container can't be null";
                //} else {
                //    this._container = container;
                //}
                this.ScrollBarMode = 1 /* Fixed */;
                this.IsControlInPreview = null;

                this.AddressObj = null;
                this.KeyActionList = null;
                this.UseSystemPasswordChar = false;
                this.Overwrite = false;
                this.Format = "";

                //this.AutoCompleteType = AutoCompleteType.None;
                this.ShowHistory = false;
                this.ReadOnly = false;
                this.AutoConvert = true;
                this.CausesValidation = false;
                this.ValidationGroup = "";
                this.LengthAsByte = false;
                this.MaxLength = 0;
                this.MaxHistoryCount = 10;

                //Add comments by RyanWu@20160510.
                //For fixing the issue#152226.
                //this.MultiLine = false;
                this.MultiLine = element && element.nodeName.toLowerCase() === "textarea";

                //end by RyanWu@20160510.
                this.AcceptsCrLf = 0 /* NoControl */;
                this.AcceptReturn = true;
                this.AcceptTab = false;
                this.HighlightText = false;
                this.Ellipsis = EllipsisMode.None;
                this.EllipsisString = String.fromCharCode(8230); //"...";
                this.ExitOnLastChar = false;
                if (_input.CoreUtility.IPadAndIPhone) {
                    // DaryLuo 2013/07/17 fix bug 1052 in IM HTML 5.
                    this.TouchDropDownScale = 1;
                } else {
                    this.TouchDropDownScale = 1.5;
                }
                this.ExitOnLeftRightKey = 0 /* None */;
                this.EditMode = 0 /* Insert */;
                this.__editModeInternal = 0 /* Insert */; // Frank Liu fixed bug 1029 at 2013/07/10.

                //this.Shortcuts = "DropDown,262162";
                this.AutoPostBack = false;
                this.PasswordMode = false;
                this.PasswordChar = "";
                this.OverflowTip = false;
                this.MaxLineCount = 0;
                this.CountWrappedLine = false;
                this.IsInUpdatePanelAndAsyncPostBack = false;
                this.UseClipboard = true;
                this.ReadingImeStringOutput = new Object();
                this.ReadingImeStringOutput.OutputMode = 0 /* Append */;
                this.ReadingImeStringOutput.TargetControl = null;

                this.ScrollBars = 0 /* None */;

                //this._xpTheme = XPTheme.Default;
                this.prevval = "";

                this.RubyText = "";

                this.FocusType = 0 /* None */;

                this.SelectionStart = 0;
                this.SelectionEnd = 0;
                this.SelectionLength = 0;

                this.OldSelectionStart = this.SelectionStart;
                this.OldSelectionEnd = this.SelectionEnd;

                var oldEditControl = this;
                var isHasIMControlObject = oldEditControl != null;

                if (!this.IsInUpdatePanelAndAsyncPostBack) {
                    this.OldText = this.Text;
                } else {
                    if (isHasIMControlObject) {
                        this.OldText = oldEditControl.GetOldValue();
                    }
                }

                this.LastStart = this.SelectionStart;
                this.LastEnd = this.SelectionEnd;
                this.Text = "";
                this.LastText = this.Text;

                // Modified by shenyuan at 2006-01-13 for new undo rules
                this.BuffText = "";

                // Added by shenyuan at 2006-01-17 for bug #4989
                this.IsUndoAfterDel = false;

                this.MouseButton = 0 /* Left */;

                this.EnableOnSelectStartEvent = true;
                this.isLeftMouseButtonPressed = false;

                //For ime mode:
                this.OrientText = "";
                this.ImeSelect = false;
                this.ImeSelectTimes = 0;

                //Edit type
                this.DragEdit = false;
                this.DropEdit = false;

                this.isFuncKeyPressed = false;

                //Change
                this.SystemChange = true;

                this.ImeMode = false;
                this.KeyDownAction = false;
                this.FocusExit = false;

                this.lastValue = "";
                this.truePosition = -1;

                this.mouseupTimes = 0;

                this.LastInputText = "";

                //Drag
                this.BeforeDragSelectionStart = 0;
                this.BeforeDragSelectionEnd = 0;
                this.IsMouseDown = false;

                //var name = "o" + this.GetId() + "IMControl.ContextMenu";
                //this.ContextMenu = new ContextMenu(name, this, this.PasswordMode);
                this.Type = "Edit";

                this.ToolTip = null;

                if ((!this.MultiLine) && this.OverflowTip) {
                    var self = this;

                    _input.Utility.AttachEvent(document, "mousemove", function (evt) {
                        _input.GlobalEventHandler.OnMouseMove(self, evt);
                    }, false);
                }

                this.HasFocus = false;

                // end of Add for OverflowTip
                var multidata = {
                    SelectionStart: this.SelectionStart,
                    SelectionEnd: this.SelectionEnd,
                    Text: this.Text,
                    OldSelectionStart: this.OldSelectionStart,
                    OldSelectionEnd: this.OldSelectionEnd,
                    OldText: this.OldText,
                    LastStart: this.LastStart,
                    LastEnd: this.LastEnd,
                    LastText: this.LastText,
                    BuffText: this.BuffText
                };
                this.DropDownEditData = multidata;

                this.IsChangedByDropDownEdit = false;

                // end
                // add for Drop
                this.DropText = "";

                // end
                this.isTextEllipsis = false;
                this.TextHeadLength = 0;

                this.IsJapanConvertKeyPress = false;
                this.NeedReCalCursorPos = true;

                if (!_input.CoreUtility.IsIE()) {
                    this.IsActive = false;
                }
                ;

                this.HasValidatedImeInput = true;

                this.IsFocusToDropDownEdit = false;

                this.IsCausedByClickingDropDownBt = false;

                this.IsCausedByImplementingDrop = false;

                // For in Firefox the properties MaxLineCount, Ellipsis and OverflowTip aren't supported.
                if (!_input.CoreUtility.IsIE()) {
                    this.MaxLineCount = 0;
                    this.Ellipsis = EllipsisMode.None;
                    this.OverflowTip = false;
                    this.IsImplementImeInput = false;
                }

                this.Create();
                this.AddAllEventsHandler();

                this.EditStatusChangedEvent = null;
                this.InvalidInputEvent = null;
                this.KeyExitEvent = null;
                this.TextChangedEvent = null;
                this.DropDownCloseEvent = null;
                this.DropDownOpenEvent = null;
                this.readingImeStringOutputEvent = null;

                this.IsjQueryControl = true;

                this.UIProcess = new GcTextBoxUIProcess(this.AutoConvert, this.Format, this.PasswordMode, this.PasswordChar, this.IsjQueryControl, this);

                this.Text = "";

                this.isPasting = false;

                this.WordWrap = true;
                this.Enabled = true;
                this.AutoCompleteType = "None";

                //this.DropDownObj = new DropDownEditControl(this.GetId(), this);
                //this._dropDown = this._render._dropDown;
                if (this.InputElement.style.imeMode === '') {
                    this.SetImeMode(ImeMode.Auto);
                }

                this._autoComplete = new AutoComplete(this);
                this.IsFromServer = false;
                this._historyList = [];
                if (this.IsFromServer) {
                    this.EnableAutoComplete = this.ShowHistory && (this.AutoCompleteType != "Disabled") && !this.ReadOnly && this.Enabled;
                } else {
                    this.EnableAutoComplete = this.ShowHistory && !this.ReadOnly && this.Enabled;
                }
                this._lines = [];

                // HelenLiu 2013/06/14 fix bug 692 in IM HTML5.
                //this.SetControlEffect(ControlEffect.NotSet);
                //this._controlEffect = ControlEffect.JQueryUI;
                // HelenLiu 2013/07/04 fix bug 943 in IM HTML5.
                this.tempIMEMode = 'auto';
                this.HeightChangedBySet = false;
                this.Width = "";
                this.Height = "";
                this.LastPassWordChar = "";
                _input.Utility.AttachFocusEventOfDocument();
                this.ShouldShowClearButton = true;
                this.switchPasswordChar = false;

                if (this.InputElement.value === "") {
                    this.isNullText = true;
                } else {
                    this.isNullText = false;
                }
            }
            IMTextBox.prototype.GetId = function () {
                return this.InputElement.id;
            };

            IMTextBox.prototype.GetContainer = function () {
                return this._container;
            };

            IMTextBox.prototype.GetJQueryInputElement = function () {
                return $(this.InputElement);
            };

            IMTextBox.prototype.GetInputElement = function () {
                return this.InputElement;
            };

            IMTextBox.prototype.Create = function () {
                if (_input.CoreUtility.IsIE10OrLater()) {
                    this.CreateHideMSClearButtonForIE10Class();
                }
            };

            IMTextBox.prototype.CreateHideMSClearButtonForIE10Class = function () {
                if (IMTextBox.HideMSClearButtonForIE10ClassName === undefined) {
                    IMTextBox.HideMSClearButtonForIE10ClassName = "gcsh_HideMSClearButtonForIE10";
                    var styleRule = _input.Utility.CreateClassStyle(IMTextBox.HideMSClearButtonForIE10ClassName + "::-ms-clear");
                    styleRule.style.display = "none";
                }
            };

            IMTextBox.prototype.IsNullFormat = function () {
                return false;
            };

            //#region FishEye and ClearButton
            IMTextBox.prototype.IsNeedFishEyeButton = function () {
                return _input.CoreUtility.IsIE10OrLater() && !this.MultiLine && this.PasswordMode;
            };

            IMTextBox.prototype.SetAddressObj = function (addressObj) {
                this.AddressObj = addressObj;
            };

            //OnFishEyeButtonDown(evt) {
            //    Utility.PreventDefault(evt);
            //    this.FishEyeButtonPressed = true;
            //    this.UpdateFishEyeButtonAppearanceState();
            //    this.FishEyeButton.setCapture(true);
            //    this.UIUpdate.SetText(this.Text);
            //}
            //OnFishEyeButtonUp(evt) {
            //    Utility.PreventDefault(evt);
            //    this.FishEyeButtonPressed = false;
            //    if (evt.offsetX < 0 || evt.offsetX > this.FishEyeButton.offsetWidth || evt.offsetY < 0 || evt.offsetY > this.FishEyeButton.offsetHeight) {
            //        this.FishEyeButtonHover = false;
            //    }
            //    this.UpdateFishEyeButtonAppearanceState();
            //    this.FishEyeButton.releaseCapture(true);
            //    this.UIUpdate.SetText(this.UIProcess.GetPasswordText(this.Text, this.PasswordChar, this.MultiLine));
            //};
            //OnFishEyeButtonMouseOver(evt) {
            //    this.FishEyeButtonHover = true;
            //    this.UpdateFishEyeButtonAppearanceState();
            //};
            //OnFishEyeButtonMouseOut(evt) {
            //    Utility.PreventDefault(evt);
            //    this.FishEyeButtonHover = false;
            //    this.UpdateFishEyeButtonAppearanceState();
            //};
            //ShowFishEyeButton() {
            //    if (this.IsNeedFishEyeButton()) {
            //        if (this.FishEyeButton == null) {
            //            var thisObj = this;
            //            this.FishEyeButton = Utility.CreateFishEyeButton(this.InputElement, this.IsjQueryControl);
            //            if (this.FishEyeButton == null) {
            //                return;
            //            }
            //            Utility.AttachEvent(this.FishEyeButton, "mousedown", function (evt) {
            //                thisObj.OnFishEyeButtonDown(evt);
            //            });
            //            Utility.AttachEvent(this.FishEyeButton, "mouseup", function (evt) {
            //                thisObj.OnFishEyeButtonUp(evt);
            //            });
            //            Utility.AttachEvent(this.FishEyeButton, "mouseover", function (evt) {
            //                thisObj.OnFishEyeButtonMouseOver(evt);
            //            });
            //            Utility.AttachEvent(this.FishEyeButton, "mouseout", function (evt) {
            //                thisObj.OnFishEyeButtonMouseOut(evt);
            //            });
            //            this._oldSetText = this.UIUpdate.SetText;
            //            this.UIUpdate.SetText(text) {
            //                thisObj.OnFishEyeSetText(text);
            //            };
            //        }
            //        if (!this.InputElement.parentElement.contains(this.FishEyeButton)) {
            //            this.InputElement.parentElement.appendChild(this.FishEyeButton);
            //        }
            //        this.UpdateFishEyeButtonPosition();
            //        this.UpdateFishEyeButtonAppearanceState("normal");
            //    }
            //};
            //UpdateFishEyeButtonPosition() {
            //    var textbox = this.GetInputElement();
            //    var fishEyeButtonDiv = this.FishEyeButton;
            //    var width = parseInt(textbox.currentStyle.width) + parseInt(textbox.currentStyle.paddingLeft) + parseInt(textbox.currentStyle.paddingRight);
            //    var height = parseInt(textbox.currentStyle.height);
            //    var paddingLeft = parseInt(textbox.currentStyle.paddingLeft);
            //    var paddingRight = parseInt(textbox.currentStyle.paddingRight);
            //    if (width - height + paddingLeft + paddingRight < Utility.GetClearButtonShowThreshold(textbox)) {
            //        return false;
            //    }
            //    var pos = { Left: 0, Top: 0 };
            //    width = textbox.offsetWidth;
            //    height = textbox.offsetHeight;
            //    var borderRect = Utility.GetBorderRectangle(textbox);
            //    var paddingRect = Utility.GetPaddingRectangle(textbox);
            //    var left = pos.Left + borderRect.Left + paddingRect.Left;
            //    var top = pos.Top + borderRect.Top + paddingRect.Top;
            //    width = width - borderRect.Horizontal - paddingRect.Horizontal;
            //    height = height - borderRect.Vertical - paddingRect.Vertical;
            //    fishEyeButtonDiv.style.height = height + "px";
            //    fishEyeButtonDiv.style.width = height + "px";
            //    fishEyeButtonDiv.style.left = left + width - height + "px";
            //    fishEyeButtonDiv.style.top = top + "px";
            //    fishEyeButtonDiv.style.display = "block";
            //    return true;
            //};
            //OnFishEyeSetText(text) {
            //    if (this.FishEyeButtonPressed && this.FishEyeButton.style.display != "none") {
            //        this._oldSetText.call(this.UIUpdate, this.Text);
            //    }
            //    else {
            //        this._oldSetText.call(this.UIUpdate, text);
            //    }
            //};
            //HideFishEyeButton(IsNeedRemove) {
            //    if (this.IsNeedFishEyeButton() && this.FishEyeButton != null) {
            //        if (IsNeedRemove) {
            //            if (this.FishEyeButton.parentElement !== null) {
            //                this.FishEyeButton.parentElement.removeChild(this.FishEyeButton);
            //            }
            //        } else {
            //            this.FishEyeButton.style.display = "none";
            //        }
            //        this.HideClearButton();
            //    }
            //};
            IMTextBox.prototype.ShowClearButton = function () {
                this.InputElement.className = this.InputElement.className.replace(IMTextBox.HideMSClearButtonForIE10ClassName, "");
            };

            IMTextBox.prototype.HideClearButton = function () {
                if (this.InputElement.className != null && this.InputElement.className.indexOf(IMTextBox.HideMSClearButtonForIE10ClassName) == -1) {
                    this.InputElement.className += " " + IMTextBox.HideMSClearButtonForIE10ClassName;
                }
            };

            IMTextBox.prototype.HandleClearButton = function (evt) {
                if (_input.CoreUtility.IsIE10OrLater() && this.FocusedWhenMouseDown && this.MouseDownOnClearButton) {
                    if (evt.target == this.InputElement && !this.MultiLine) {
                        var isFocused = document.activeElement == evt.target;
                        var hitTestResult = _input.CoreUtility.IsMouseDownOnClearButton(evt);

                        //if (this.MouseUpHasValue && isFocused && hitTestResult && !this.PasswordMode) {
                        if (this.MouseUpHasValue && isFocused && hitTestResult) {
                            var thisObj = this;
                            setTimeout(function (parameters) {
                                thisObj.Clear();
                            }, 0);
                        }
                    }
                }
            };

            //#endregion
            //#region Public Properties
            /**
            * Gets whether pressing the TAB key in a multiple line edit control types a TAB character in the control instead of moving the focus to the next control in the tab order.
            * @returns {boolean} A value indicates accept TAB or not.
            */
            IMTextBox.prototype.GetAcceptsTab = function () {
                return this.AcceptTab;
            };

            /**
            * Sets whether pressing the TAB key in a multiple line edit control types a TAB character in the control instead of moving the focus to the next control in the tab order.
            * @param {boolean} isAcceptsTab A value indicates accept TAB or not.
            */
            IMTextBox.prototype.SetAcceptsTab = function (isAcceptsTab) {
                isAcceptsTab = _input.Utility.CheckBool(isAcceptsTab);
                this.AcceptTab = isAcceptsTab;
            };

            /**
            * Gets a value that indicates how to process the CrLf characters when copying, cutting, or pasting the string.
            * @returns {CrLfMode} A value indicates the mode of accept Crlf.
            */
            IMTextBox.prototype.GetAcceptsCrlf = function () {
                return this.AcceptsCrLf;
            };

            /**
            * Sets a value that indicates how to process the CrLf characters when copying, cutting, or pasting the string.
            * @param {CrLfMode} acceptsCrlfMode  A value indicates the mode of accept Crlf.
            */
            IMTextBox.prototype.SetAcceptsCrlf = function (acceptsCrlfMode) {
                acceptsCrlfMode = _input.Utility.CheckEnum(_input.CrLfMode, acceptsCrlfMode);
                this.AcceptsCrLf = acceptsCrlfMode;
            };

            /**
            * Gets whether the control automatically converts to the proper format according to the format setting.
            * @returns {boolean} A value indicates support auto convert or not.
            */
            IMTextBox.prototype.GetAutoConvert = function () {
                return this.AutoConvert;
            };

            /**
            * Sets whether the control automatically converts to the proper format according to the format setting.
            * @param {boolean} isAutoConvert A value indicates support auto convert or not.
            */
            IMTextBox.prototype.SetAutoConvert = function (isAutoConvert) {
                isAutoConvert = _input.Utility.CheckBool(isAutoConvert);
                this.AutoConvert = isAutoConvert;
                this.UIProcess.Reset();
                //this.DropDownObj.UIProcess.Reset();
            };

            /**
            * Gets whether to treat the wrapped lines as one line or multiple lines when counting the lines count.
            * @returns {boolean} A value indicates count wrapper lines or not.
            */
            IMTextBox.prototype.GetCountWrappedLine = function () {
                return this.CountWrappedLine;
            };

            /**
            * Sets whether to treat the wrapped lines as one line or multiple lines when counting the lines count.
            * @param {boolean} isCountWrappedLine A value indicates count wrapper lines or not.
            */
            IMTextBox.prototype.SetCountWrappedLine = function (isCountWrappedLine) {
                isCountWrappedLine = _input.Utility.CheckBool(isCountWrappedLine);
                this.CountWrappedLine = isCountWrappedLine;
                this.InternalSetText(this.GetText());
                if (this.Ellipsis !== EllipsisMode.None) {
                    this.DealEllipsis(this.MultiLine, this.Ellipsis, this.EllipsisString, this.InputElement);
                }
            };

            /**
            * Gets the edit mode of the control.
            * @returns {EditMode} A value indicates edit mode setting.
            */
            IMTextBox.prototype.GetEditMode = function () {
                return this.EditMode;
            };

            /**
            * Sets the edit mode of the control.
            * @param {EditMode} editMode A value indicates edit mode setting.
            */
            IMTextBox.prototype.SetEditMode = function (editMode) {
                var value = editMode;
                value = _input.Utility.CheckEnum(_input.EditMode, value);

                if (value === 0 /* Insert */ || value === 2 /* FixedInsert */) {
                    this.Overwrite = false;
                } else {
                    this.Overwrite = true;
                }

                // HelenLiu 2013/06/09 fix bug 643 in IM HTML5.0.
                if (value !== this.EditMode) {
                    var shouldFireEvent = false;
                    if (this._isinsertGroup(value) && this._isOverwriteGroup(this.EditMode)) {
                        shouldFireEvent = true;
                    } else if (this._isinsertGroup(this.EditMode) && this._isOverwriteGroup(value)) {
                        shouldFireEvent = true;
                    }

                    this.EditMode = value;
                    this.__editModeInternal = value; // Frank Liu fixed bug 1029 at 2013/07/10.
                    if (shouldFireEvent) {
                        this.UIProcess.FireEvent(this, this.EditStatusChangedEvent, null, "EditStatusChanged");
                    }
                }
            };

            IMTextBox.prototype._getEditModeInternal = function () {
                return this.__editModeInternal;
            };
            IMTextBox.prototype._setEditModeInternal = function (value) {
                value = _input.Utility.CheckEnum(_input.EditMode, value);

                if (value === 0 /* Insert */ || value === 2 /* FixedInsert */) {
                    this.Overwrite = false;
                } else {
                    this.Overwrite = true;
                }

                // HelenLiu 2013/06/09 fix bug 643 in IM HTML5.0.
                if (value !== this.__editModeInternal) {
                    // HelenLiu 2013/07/17 fix bug 1080 in IM HTML5.
                    //var shouldFireEvent = false;
                    //if (this._isinsertGroup(value) && this._isOverwriteGroup(this.__editModeInternal)) {
                    //    shouldFireEvent = true;
                    //} else if (this._isinsertGroup(this.__editModeInternal) && this._isOverwriteGroup(value)) {
                    //    shouldFireEvent = true;
                    //}
                    this.__editModeInternal = value;
                    //if (shouldFireEvent) {
                    //    this.UIProcess.FireEvent(this, this.EditStatusChangedEvent, null, "EditStatusChanged");
                    //}
                }
            };

            /**
            * Gets how to display the ellipsis string when the the control's content is longer than its width.
            * @returns {EllipsisMode} A value indicates ellipsis mode setting.
            */
            IMTextBox.prototype.GetEllipsis = function () {
                return this.Ellipsis;
            };

            /**
            * Sets how to display the ellipsis string when the the control's content is longer than its width.
            * @param {EllipsisMode} ellipsisMode A value indicates ellipsis mode setting.
            */
            IMTextBox.prototype.SetEllipsis = function (ellipsisMode) {
                var value = ellipsisMode;
                value = _input.Utility.CheckEnum(EllipsisMode, value);
                this.Ellipsis = value;
                this.InternalDirectSetText(this.Text);
                this.DealEllipsis(this.MultiLine, this.Ellipsis, this.EllipsisString, this.InputElement);
            };

            /**
            * Gets the ellipsis string shows in the control.
            * @returns {string} A value indicates ellipsis string setting.
            */
            IMTextBox.prototype.GetEllipsisString = function () {
                return this.EllipsisString;
            };

            /**
            * Sets the ellipsis string shows in the control.
            * @param {string} ellipsisString A value indicates ellipsis string setting.
            */
            IMTextBox.prototype.SetEllipsisString = function (ellipsisString) {
                ellipsisString = _input.Utility.CheckString(ellipsisString);
                this.EllipsisString = ellipsisString;
                this.DealEllipsis(this.MultiLine, this.Ellipsis, this.EllipsisString, this.InputElement);
            };

            /**
            * Sets whether the control is enabled.
            * @param {boolean} isEnabled A value indicates control is enabled or not.
            */
            //SetEnabled(isEnabled) {
            //    BaseControl.prototype.SetEnabled.call(this, isEnabled);
            //    isEnabled = this.GetEnabled();
            //    this.Enabled = isEnabled;
            //    if (isEnabled) {
            //        this._removeBorderStatus(ControlStatus.Disabled);
            //    } else {
            //        this._addBorderStatus(ControlStatus.Disabled);
            //    }
            //    this._updateDropDownButtonStatus();
            //    this.UIUpdate.SetEnabled(isEnabled, this._render._dropDown.GetEnabled());
            //    if (this.IsFromServer) {
            //        this.EnableAutoComplete = this.ShowHistory && (this.AutoCompleteType != "Disabled") && !this.ReadOnly && isEnabled;
            //    } else {
            //        this.EnableAutoComplete = this.ShowHistory && !this.ReadOnly && isEnabled;
            //    }
            //};
            /**
            * Gets whether or not the next control in the tab order receives the focus as soon as the control is filled at the last character.
            * @returns {boolean} A value indicates whether move focus to next control when last char of control is filled.
            */
            IMTextBox.prototype.GetExitOnLastChar = function () {
                return this.ExitOnLastChar;
            };

            /**
            * Sets whether or not the next control in the tab order receives the focus as soon as the control is filled at the last character.
            * @param {boolean} isExitOnLastChar A value indicates whether move focus to next control when last char of control is filled.
            */
            IMTextBox.prototype.SetExitOnLastChar = function (isExitOnLastChar) {
                isExitOnLastChar = _input.Utility.CheckBool(isExitOnLastChar);
                this.ExitOnLastChar = isExitOnLastChar;
            };

            /**
            * Gets whether the focus automatically moves to the next or previous tab ordering control when pressing the left, right arrow keys.
            * @returns {ExitOnLeftRightKey} A value indicates ExitOnLeftRightKey setting.
            */
            IMTextBox.prototype.GetExitOnLeftRightKey = function () {
                switch (this.ExitOnLeftRightKey) {
                    case 0 /* None */:
                        return 'none';
                    case 3 /* Both */:
                        return 'both';
                    case 1 /* Left */:
                        return 'left';
                    case 2 /* Right */:
                        return 'right';
                    default:
                }
            };

            /**
            * Set whether the focus automatically moves to the next or previous tab ordering control when pressing the left, right arrow keys.
            * @param {ExitOnLeftRightKey} isExitOnLeftRightKey A value indicates ExitOnLeftRightKey setting.
            */
            IMTextBox.prototype.SetExitOnLeftRightKey = function (isExitOnLeftRightKey) {
                //isExitOnLeftRightKey = Utility.CheckEnum(ExitOnLeftRightKey, isExitOnLeftRightKey);
                _input.Utility.CheckString(isExitOnLeftRightKey);
                switch (isExitOnLeftRightKey.toLowerCase()) {
                    case 'none':
                        this.ExitOnLeftRightKey = 0 /* None */;
                        break;
                    case 'both':
                        this.ExitOnLeftRightKey = 3 /* Both */;
                        break;
                    case 'left':
                        this.ExitOnLeftRightKey = 1 /* Left */;
                        break;
                    case 'right':
                        this.ExitOnLeftRightKey = 2 /* Right */;
                        break;
                    default:
                }
            };

            /**
            * Sets font size of control.
            * @param {string|number} fontSize
            */
            //SetFontSize(fontSize) {
            //    BaseControl.prototype.SetFontSize.call(this, fontSize);
            //    if (this.MaxLineCount !== 0) {
            //        this.InternalSetText(this.GetText());
            //    }
            //    if (this.Ellipsis !== EllipsisMode.None) {
            //        this.DealEllipsis(this.MultiLine, this.Ellipsis, this.EllipsisString, this.InputElement);
            //    }
            //};
            /**
            * Gets the format string that defines the type of text allowed for input in the control.
            * @returns {string}
            */
            IMTextBox.prototype.GetFormat = function () {
                return this.Format;
            };

            /**
            * Sets the format string that defines the type of text allowed for input in the control.
            * @param {string} format
            */
            IMTextBox.prototype.SetFormat = function (format) {
                format = _input.Utility.CheckString(format);
                this.Format = format;
                this.UIProcess.Reset();

                //this.DropDownObj.UIProcess.Reset();
                //this.UIProcess.Filter = new TextFilter(this.AutoConvert, this.Format);
                // this.SetText(this.UIProcess.Filter.CheckText(this.GetText()).CheckedText);
                var txt = this.InternalSetText(this.GetText());

                // HelenLiu 2013/06/20 fix bug 812 in IM HTML5.
                this.Text = txt;
                this.DropDownEditData.Text = txt;

                // HelenLiu 2013/07/12 fix bug 1042 in IM HTML5.
                if (this.Ellipsis !== EllipsisMode.None) {
                    this.DealEllipsis(this.MultiLine, this.Ellipsis, this.EllipsisString, this.InputElement);
                }
            };

            /**
            * Gets whether to highlight the control's text on receiving input focus.
            * @returns {boolean}
            */
            IMTextBox.prototype.GetHighlightText = function () {
                return this.HighlightText;
            };

            /**
            * Sets whether to highlight the control's text on receiving input focus.
            * @param {boolean} isHighlightText
            */
            IMTextBox.prototype.SetHighlightText = function (isHighlightText) {
                isHighlightText = _input.Utility.CheckBool(isHighlightText);
                this.HighlightText = isHighlightText;
            };

            /**
            * Gets history list setting of control.
            * @returns {Array}
            */
            IMTextBox.prototype.GetHistoryList = function () {
                return this._historyList;
            };

            /**
            * Sets history list setting of control.
            * @param {Array} historyList
            * @example
            * <i>gcTextBox</i>.SetHistoryList(str1,str2);
            * <i>gcTextBox</i>.SetHistoryList([str1,str2]);
            */
            IMTextBox.prototype.SetHistoryList = function (historyList) {
                if (historyList === null) {
                    return;
                }
                var args;
                if (arguments[0] instanceof Array) {
                    args = arguments[0];
                } else {
                    args = Array.prototype.slice.call(arguments);
                }

                if (args.length === 0 || (args.length === 1 && args[0] === "")) {
                    return;
                }
                this.IsFromServer = false;
                this._historyList = [];
                for (var i = 0; i < args.length; i++) {
                    this._historyList.push(args[i]);
                }
            };

            /**
            * Gets the Ime Mode setting of control.
            * @returns {ImeMode}
            */
            IMTextBox.prototype.GetImeMode = function () {
                if (this.InputElement !== null) {
                    return this.InputElement.style.imeMode || "auto";
                }
                return "";
            };

            /**
            * Sets the Ime Mode setting of control.
            * @param {ImeMode} imeMode
            */
            IMTextBox.prototype.SetImeMode = function (imeMode) {
                //imeMode = Utility.CheckEnum(ImeMode, imeMode);
                _input.Utility.CheckString(imeMode);

                if (this.InputElement !== null) {
                    this.InputElement.style.imeMode = imeMode;
                }
            };

            /**
            * Gets whether the maximum length constraint for input is byte-based or character-based.
            * @returns {boolean}
            */
            IMTextBox.prototype.GetLengthAsByte = function () {
                return this.LengthAsByte;
            };

            /**
            * Sets whether the maximum length constraint for input is byte-based or character-based.
            * @param {boolean} isLengthAsByte
            */
            IMTextBox.prototype.SetLengthAsByte = function (isLengthAsByte) {
                isLengthAsByte = _input.Utility.CheckBool(isLengthAsByte);
                this.LengthAsByte = isLengthAsByte;
                this.SetText(this.UIProcess.Filter.CheckText(this.GetText()).CheckedText);
            };

            /**
            * Gets the lines of text in the control.
            * @returns {Array}
            */
            IMTextBox.prototype.GetLines = function () {
                // HelenLiu 2013/06/14 fix bug 691 in IM HTML5.
                var lines = new Array();
                var text = this.GetText();

                var sEnter = "\r\n";
                if (!_input.CoreUtility.IsIE() || _input.CoreUtility.IsIE9OrLater()) {
                    sEnter = "\n";
                }

                var index = text.IndexOf(sEnter);
                var i = 0;
                while (index != -1) {
                    lines[i++] = text.Substring(0, index);
                    text = text.Substring(index + sEnter.GetLength(), text.GetLength());
                    index = text.IndexOf(sEnter);
                }
                lines[i] = text;
                return lines;
            };

            /**
            * Sets the lines of text in the control.
            * @param {Array} lines
            * @example
            * <i>gcTextBox</i>.SetLines(str1,str2);
            * <i>gcTextBox</i>.SetLines([str1,str2]);
            */
            IMTextBox.prototype.SetLines = function (lines) {
                //if (this.GetReadOnly()) {
                //    return;
                //}
                if (lines === null) {
                    return;
                }
                var args;
                if (arguments[0] instanceof Array) {
                    args = arguments[0];
                } else {
                    args = Array.prototype.slice.call(arguments);
                }

                if (args.length === 0 || (args.length === 1 && args[0] === "")) {
                    return;
                }
                this._lines = [];
                for (var k = 0; k < args.length; k++) {
                    this._lines.push(args[k]);
                }
                var text = "";
                if (this.MultiLine) {
                    for (var i = 0; i < this._lines.length; i++) {
                        if (i > 0) {
                            if (!_input.CoreUtility.IsIE()) {
                                text += "\n";
                            } else {
                                text += "\r\n";
                            }
                        }
                        text += this._lines[i];
                    }
                } else {
                    for (var i = 0; i < this._lines.length; i++) {
                        text += this._lines[i];
                    }
                }

                this.SetText(text);
            };

            /**
            * Gets max history count of the history item.
            * @returns {number}
            */
            IMTextBox.prototype.GetMaxHistoryCount = function () {
                return this.MaxHistoryCount;
            };

            /**
            * Gets or sets max history count of the history item.
            * @param {number} maxHistoryCount
            */
            IMTextBox.prototype.SetMaxHistoryCount = function (maxHistoryCount) {
                maxHistoryCount = _input.Utility.CheckInt(maxHistoryCount);

                // HelenLiu 2013/07/10 fix bug 1036 in IM HTML5.0.
                if (maxHistoryCount < 0) {
                    throw "ArgumentOutOfRangeException";
                }
                this.MaxHistoryCount = maxHistoryCount;
            };

            /**
            * Gets the maximum length of text that can be input in the control.
            * @returns {number}
            */
            IMTextBox.prototype.GetMaxLength = function () {
                return this.MaxLength;
            };

            /**
            * Sets the maximum length of text that can be input in the control.
            * @param {number} maxLength
            */
            IMTextBox.prototype.SetMaxLength = function (maxLength) {
                maxLength = _input.Utility.CheckInt(maxLength);

                // HelenLiu 2013/06/09 fix bug 644 in IM HTML5.0.
                if (maxLength < 0) {
                    throw "ArgumentOutOfRangeException";
                }
                this.MaxLength = maxLength;
                this.InternalSetText(this.GetText());

                // HelenLiu 2013/07/12 fix bug 1042 in IM HTML5.
                if (this.Ellipsis !== EllipsisMode.None) {
                    this.DealEllipsis(this.MultiLine, this.Ellipsis, this.EllipsisString, this.InputElement);
                }

                // HelenLiu 2013/07/22 fix bug 1121 in IM HTML5.
                this.DropDownEditData.Text = this.GetText();
            };

            /**
            * Gets the max count of lines can be input into the control.
            * @returns {number}
            */
            IMTextBox.prototype.GetMaxLineCount = function () {
                return this.MaxLineCount;
            };

            /**
            * Sets the max count of lines can be input into the control.
            * @param {number} maxLineCount
            */
            IMTextBox.prototype.SetMaxLineCount = function (maxLineCount) {
                maxLineCount = _input.Utility.CheckInt(maxLineCount);

                if (maxLineCount < 0) {
                    throw "ArgumentOutOfRangeException";
                }
                this.MaxLineCount = maxLineCount;
                this.InternalSetText(this.GetText());
                if (this.Ellipsis !== EllipsisMode.None) {
                    this.DealEllipsis(this.MultiLine, this.Ellipsis, this.EllipsisString, this.InputElement);
                }
            };

            /**
            * Gets whether this is a multiline control.
            * @returns {boolean}
            */
            IMTextBox.prototype.GetMultiLine = function () {
                return this.MultiLine;
            };

            /**
            * Sets whether this is a multiline control.
            * @param {boolean} isMultiLine
            */
            IMTextBox.prototype.SetMultiLine = function (isMultiLine) {
                isMultiLine = _input.Utility.CheckBool(isMultiLine);
                if (isMultiLine === this.MultiLine) {
                    return;
                }
                this.MultiLine = isMultiLine;

                //this._render._reCreate();
                // HelenLiu 2013/06/19 fix bug 717 in IM HTML5.
                //this.AddAllEventsHandler();
                // HelenLiu 2013/06/19 fix bug 728 in IM HTML5.
                this.InternalDirectSetText(this.Text);
                this.DealEllipsis(this.MultiLine, this.Ellipsis, this.EllipsisString, this.InputElement);

                // Frank Liu comments at 2013/08/28.
                //if (this.MultiLine === true) {
                //    this._CheckScrollBar(this.GetScrollBars(), this.GetScrollBarMode());
                //}
                //this.ProcessFishEyeButtonOnLostFocus(true);
                this.DropDownEditData.Text = this.GetText();
            };

            //GcTextBox.DefaultMultiLineWidth = 178;
            //GcTextBox.DefaultMultiLineHeight = 36;
            /**
            * Gets whether display the overflow tip.
            * @returns {boolean}
            */
            IMTextBox.prototype.GetOverflowTip = function () {
                return this.OverflowTip;
            };

            /**
            * Sets whether display the overflow tip.
            * @param {boolean} isShowOverflowTip
            */
            IMTextBox.prototype.SetOverflowTip = function (isShowOverflowTip) {
                isShowOverflowTip = _input.Utility.CheckBool(isShowOverflowTip);
                this.OverflowTip = isShowOverflowTip;
            };

            /**
            * Gets whether the contents of the control are overwritten.
            * @returns {boolean}
            */
            IMTextBox.prototype.GetOverwrite = function () {
                return this.Overwrite;
            };

            /**
            * Gets the password char.
            * @returns {string}
            */
            IMTextBox.prototype.GetPasswordChar = function () {
                return this.PasswordChar;
            };

            /**
            * Sets the password char.
            * @param {string} passwordChar
            */
            IMTextBox.prototype.SetPasswordChar = function (passwordChar) {
                if (passwordChar !== "") {
                    passwordChar = _input.Utility.CheckChar(passwordChar);
                    if (this.PasswordChar === this.SystemPasswordChar() && this.GetUseSystemPasswordChar()) {
                        this.LastPassWordChar = passwordChar;
                        return;
                    }
                    this.LastPassWordChar = this.PasswordChar;
                    this.PasswordChar = passwordChar;
                    this.PasswordMode = true;

                    //this.SetText(this.UIProcess.Filter.CheckText(this.GetText()).CheckedText);
                    if (!this.isNullText) {
                        this.InternalSetText(this.GetText());
                    }
                    this.tempIMEMode = this.GetImeMode();
                    this.SetImeMode(ImeMode.Disabled);
                } else {
                    if (this.UseSystemPasswordChar === false) {
                        this.PasswordMode = false;

                        //this.switchPasswordChar = true;
                        this.SetText(this.hideText);

                        //this.InternalSetText(this.GetText());
                        if (this.tempIMEMode !== "") {
                            this.SetImeMode(this.tempIMEMode);
                        }
                    }
                    if (this.PasswordChar === this.SystemPasswordChar() && !this.GetUseSystemPasswordChar() && this.LastPassWordChar !== "") {
                        this.PasswordChar = _input.Utility.CheckChar(this.LastPassWordChar);
                        this.PasswordMode = true;
                        this.InternalSetText(this.GetText());
                        this.tempIMEMode = this.GetImeMode();
                        this.SetImeMode(ImeMode.Disabled);
                        if (this.Ellipsis !== EllipsisMode.None) {
                            this.DealEllipsis(this.MultiLine, this.Ellipsis, this.EllipsisString, this.InputElement);
                        }
                        return;
                    }
                    this.PasswordChar = passwordChar;
                }

                // HelenLiu 2013/07/26 fix bug 1105 in IM HTML5.
                this.switchPasswordChar = true;
                this.UIProcess.Reset();

                //this.DropDownObj.UIProcess.Reset();
                if (this.Ellipsis !== EllipsisMode.None) {
                    this.DealEllipsis(this.MultiLine, this.Ellipsis, this.EllipsisString, this.InputElement);
                }
            };

            /**
            * Gets whether the new result string is to append or replace the former text.
            * @returns {string}
            */
            IMTextBox.prototype.GetReadingImeStringOutputMode = function () {
                return this.ReadingImeStringOutput.OutputMode;
            };

            /**
            * Sets whether the new result string is to append or replace the former text.
            * @param {string} outputMode
            */
            IMTextBox.prototype.SetReadingImeStringOutputMode = function (outputMode) {
                outputMode = _input.Utility.CheckString(outputMode);
                this.ReadingImeStringOutput.OutputMode = outputMode;
            };

            /**
            * Gets in which control the result string will be shown.
            * @returns {string}
            */
            IMTextBox.prototype.GetReadingImeStringOutputTargetControl = function () {
                return this.ReadingImeStringOutput.TargetControl;
            };

            /**
            * Sets in which control the result string will be shown.
            * @param {string} targetControl
            */
            IMTextBox.prototype.SetReadingImeStringOutputTargetControl = function (targetControl) {
                targetControl = _input.Utility.CheckString(targetControl);
                this.ReadingImeStringOutput.TargetControl = targetControl;
            };

            /**
            * Gets whether the contents of the control can be changed.
            * @returns {boolean}
            */
            IMTextBox.prototype.GetReadOnly = function () {
                return this.ReadOnly;
            };

            /**
            * Sets whether the contents of the control can be changed.
            * @param {boolean} isReadOnly
            */
            IMTextBox.prototype.SetReadOnly = function (isReadOnly) {
                isReadOnly = _input.Utility.CheckBool(isReadOnly);
                if (this.InputElement != null) {
                    this.InputElement.readOnly = isReadOnly;
                }
                this.ReadOnly = isReadOnly;

                if (this.IsFromServer) {
                    this.EnableAutoComplete = this.ShowHistory && (this.AutoCompleteType != "Disabled") && !this.ReadOnly && isReadOnly;
                } else {
                    this.EnableAutoComplete = this.ShowHistory && !this.ReadOnly && isReadOnly;
                }
            };

            /**
            * Gets or sets whether scroll bars are always displayed or only when needed.
            * @returns {ScrollBarMode}
            */
            IMTextBox.prototype.GetScrollBarMode = function () {
                return this.ScrollBarMode;
            };

            /**
            * Gets or sets whether scroll bars are always displayed or only when needed.
            * @param {ScrollBarMode} scrollBarMode
            */
            IMTextBox.prototype.SetScrollBarMode = function (scrollBarMode) {
                scrollBarMode = _input.Utility.CheckEnum(_input.ScrollBarMode, scrollBarMode);
                this.ScrollBarMode = scrollBarMode;
                this._CheckScrollBar(this.GetScrollBars(), scrollBarMode);
            };

            /**
            * Gets which scroll bars should appear in a multiple line edit control.
            * @returns {ScrollBars}
            */
            IMTextBox.prototype.GetScrollBars = function () {
                return this.ScrollBars;
            };

            /**
            * Sets which scroll bars should appear in a multiple line edit control.
            * @param {ScrollBars} scrollBarType
            */
            IMTextBox.prototype.SetScrollBars = function (scrollBarType) {
                scrollBarType = _input.Utility.CheckEnum(_input.ScrollBars, scrollBarType);
                this.ScrollBars = scrollBarType;
                this._CheckScrollBar(scrollBarType, this.GetScrollBarMode());

                //Following code just for Re-Layout. Because WordWrap can't refersh correctly.
                var w = this.InputElement.style.width;
                this.InputElement.style.width = (parseInt(this.InputElement.style.width) - 5) + "px";
                var self = this;
                setTimeout(function () {
                    self.InputElement.style.width = w;
                }, 10);
            };

            /**
            * Gets the position in the text where the selection starts.
            * @returns {number}
            */
            IMTextBox.prototype.GetSelectionStart = function () {
                return Math.min(this.SelectionStart, this.SelectionEnd);
            };

            /**
            * Sets the position in the text where the selection starts.
            * @param {number} selectionStart
            */
            IMTextBox.prototype.SetSelectionStart = function (selectionStart) {
                selectionStart = _input.Utility.CheckInt(selectionStart);

                if (selectionStart < 0) {
                    throw "ArgumentOutOfRangeException";
                }
                if (selectionStart == null) {
                    return;
                }
                var sCursorPosition = selectionStart.toString();
                var cursorPosition = parseInt(sCursorPosition);
                if (_input.Utility.FilterText("0123456789", sCursorPosition) != sCursorPosition) {
                    //throw "Invalid Position";
                } else {
                    if (cursorPosition > this.GetText().GetLength()) {
                        this.SelectionStart = this.GetText().GetLength();
                        this.SelectionEnd = this.GetText().GetLength();

                        if (!this.MultiLine) {
                            this.DropDownEditData.SelectionStart = this.DropDownEditData.Text.GetLength();
                            this.DropDownEditData.SelectionEnd = this.DropDownEditData.Text.GetLength();
                        }
                    } else {
                        var selectionLength = this.GetSelectionLength();

                        this.SelectionStart = cursorPosition;
                        if (!this.MultiLine) {
                            this.DropDownEditData.SelectionStart = this.GetMultiPosition(this.DropDownEditData.Text, cursorPosition);
                        }
                        if ((cursorPosition - 0) + selectionLength <= this.GetText().GetLength()) {
                            this.SelectionEnd = (cursorPosition - 0) + selectionLength;
                            if (!this.MultiLine) {
                                this.DropDownEditData.SelectionEnd = this.GetMultiPosition(this.DropDownEditData.Text, cursorPosition + selectionLength);
                            }
                        } else {
                            this.SelectionEnd = this.GetText().GetLength();
                            if (!this.MultiLine) {
                                this.DropDownEditData.SelectionEnd = this.DropDownEditData.Text.GetLength();
                            }
                        }
                    }
                }
            };

            /**
            * Gets the selected text.
            * @returns {string}
            */
            IMTextBox.prototype.GetSelectedText = function () {
                return this.GetText().Substring(Math.min(this.SelectionStart, this.SelectionEnd), Math.max(this.SelectionStart, this.SelectionEnd));
            };

            /**
            * Sets the selected text.
            * @param {string} text
            */
            IMTextBox.prototype.SetSelectedText = function (text) {
                text = _input.Utility.CheckString(text);
                this.OldText = this.GetText();
                var start = this.SelectionStart;
                var end = this.SelectionEnd;
                var oldtext = this.GetText();

                if (!this.MultiLine) {
                    this.DropDownEditData.OldText = this.DropDownEditData.Text;
                    start = this.DropDownEditData.SelectionStart;
                    end = this.DropDownEditData.SelectionEnd;
                    oldtext = this.DropDownEditData.Text;
                }

                var retInfo = this.UIProcess.TextBoxPaste(start, end, oldtext, this.ExitOnLastChar, this.AcceptTab, this.AcceptReturn, this.MaxLength, this.LengthAsByte, this.MaxLineCount, this.CountWrappedLine, this.MultiLine, text, true);

                if (retInfo == null) {
                }

                if (retInfo.Text != null) {
                    // Add comments by Yang at 13:30 January 31th 2008
                    // For fix the bug 9623
                    //this.InternalSetText(retInfo.Text, true);
                    this.DirectSetText(retInfo.Text);
                    if (!this.MultiLine) {
                        this.DropDownEditData.Text = retInfo.Text;
                    }
                    // End by Yang
                }

                if (retInfo.SelectionStart != null) {
                    this.SelectionStart = retInfo.SelectionStart;
                    if (!this.MultiLine) {
                        this.DropDownEditData.SelectionStart = retInfo.SelectionStart;
                        this.SelectionStart = this.GetSingleCurPosition(this.DropDownEditData.Text, retInfo.SelectionStart);
                    }
                }

                if (retInfo.SelectionEnd != null) {
                    this.SelectionEnd = retInfo.SelectionEnd;
                    if (!this.MultiLine) {
                        this.DropDownEditData.SelectionEnd = retInfo.SelectionEnd;
                        this.SelectionEnd = this.GetSingleCurPosition(this.DropDownEditData.Text, retInfo.SelectionEnd);
                    }
                }

                var oldText = this.OldText;
                this.OldText = this.GetText();
                this.LastText = this.OldText;

                this.DropDownEditData.OldText = this.DropDownEditData.Text;
                this.DropDownEditData.LastText = this.DropDownEditData.OldText;

                //// Add comments by Yang at 10:24 October 12th 2007
                //// For fix the bug 9019
                //this.SetLastClientValues();
                //// End by Yang
                // Frank Liu removed, to fire 'textChanged' event in SetHideText(). 2013/09/1, for wijinputtext.
                //if (this.GetText() != oldText && this.TextChangedEvent != "" && this.TextChangedEvent != null) {
                //    //Add comments by Ryan Wu at 10:42 Apr. 5 2007.
                //    //For support Aspnet Ajax 1.0.
                //    //this.UIProcess.FireEvent(this, this.TextChanged, null);
                //    this.UIProcess.FireEvent(this, this.TextChangedEvent, null, "TextChanged");
                //    //end by Ryan Wu.
                //}
                // HelenLiu 2013/07/08 fix bug 998 in IM HTML5.
                if (this.Ellipsis !== EllipsisMode.None) {
                    this.DealEllipsis(this.MultiLine, this.Ellipsis, this.EllipsisString, this.InputElement);
                }
            };

            /**
            * Gets the length, the number of characters, of the selection.
            * @returns {number}
            */
            IMTextBox.prototype.GetSelectionLength = function () {
                return Math.abs(this.SelectionEnd - this.SelectionStart);
            };

            /**
            * Sets the length, the number of characters, of the selection.
            * @param {number} length
            */
            IMTextBox.prototype.SetSelectionLength = function (length) {
                length = _input.Utility.CheckInt(length);
                if (length < 0) {
                    throw "ArgumentOutOfRangeException";
                }
                if (length == null) {
                }
                length = length.toString();
                if (_input.Utility.FilterText("0123456789", length) != length) {
                    //throw "Invalid Length";
                } else {
                    var startCursorPosition = this.GetSelectionStart();
                    this.SelectionStart = startCursorPosition;

                    if (startCursorPosition + (length - 0) <= this.GetText().GetLength()) {
                        this.SelectionEnd = startCursorPosition + (length - 0);
                        if (!this.MultiLine) {
                            //modified by sj 2008.8.11 for bug 140
                            //this.DropDownEditData.SelectionEnd = this.GetMultiPosition(this.DropDownEditData.Text, startCursorPosition + length);
                            this.DropDownEditData.SelectionEnd = this.GetMultiPosition(this.DropDownEditData.Text, startCursorPosition + parseInt(length));
                            //end by sj
                        }
                    } else {
                        this.SelectionEnd = this.GetText().GetLength();
                        if (!this.MultiLine) {
                            this.DropDownEditData.SelectionEnd = this.DropDownEditData.Text.GetLength();
                        }
                    }
                }
            };

            /**
            * Gets whether show history of control.
            * @returns {boolean}
            */
            IMTextBox.prototype.GetShowHistory = function () {
                return this.ShowHistory;
            };

            /**
            * Sets whether show history of control.
            * @param {boolean} isShowHistory
            */
            IMTextBox.prototype.SetShowHistory = function (isShowHistory) {
                isShowHistory = _input.Utility.CheckBool(isShowHistory);
                this.ShowHistory = isShowHistory;
                if (this.IsFromServer) {
                    this.EnableAutoComplete = this.ShowHistory && (this.AutoCompleteType != "Disabled") && !this.ReadOnly && this.Enabled;
                } else {
                    this.EnableAutoComplete = this.ShowHistory && !this.ReadOnly && this.Enabled;
                }
            };

            /**
            * Gets the text.
            * @returns {string}
            */
            IMTextBox.prototype.GetText = function () {
                var strContent = this._getInputValueWithPlaceHolder();

                //modified by sj 2008.8.8 for bug 99
                if (this.isTextEllipsis && !this.DragEdit) {
                    strContent = this.Text;
                }

                //		if ((!this.UseSystemPasswordChar && this.PasswordMode) || (this.MultiLine && this.UseSystemPasswordChar))
                if (this.PasswordMode) {
                    var temp = this.hideText;
                    var index = temp.LastIndexOf(":true");
                    var strText;
                    if (index == -1) {
                        strText = temp;
                    } else {
                        strText = temp.Substring(0, index);
                    }

                    //modified by sj 2008.8.11 for bug 234
                    //if (strText.GetLength() == strContent.GetLength())
                    //{
                    return strText;
                    //}
                    //end by sj
                }

                //add by sj
                if (!_input.CoreUtility.IsIE() && this.FFDragFlag) {
                    strContent = this.Text;
                }

                //end by sj
                return strContent;
            };

            /**
            * Sets the text.
            * @param {string} text
            */
            IMTextBox.prototype.SetText = function (text) {
                text = _input.Utility.CheckString(text);
                this.OldText = this.GetText();

                // HelenLiu 2013/07/26 fix bug 1105 in IM HTML5.
                this.switchPasswordChar = false;
                this.InternalSetText(text, false);

                //modified by sj 2008.8.12 for bug 294
                //if enable is false and the text is invalid.
                //		if (!this.Enabled&&!this.UIProcess.isInputValid)
                //		{
                //			this.InternalSetText(this.OldText, false);
                //			return;
                //		}
                //end by sj.
                if (this.GetText() != this.OldText) {
                    // Add comments by Yang at 10:12 May 31st 2007
                    // For fix bug 8313
                    this.OldText = this.GetText();

                    // Add comments by Yang at 14:35 August 7th 2007
                    // For improve the performance for v2h1
                    this.SetHideText(this.GetText());
                    //this.UIUpdate.SetHideText(this.GetText() + ":true");
                    // End by Yang
                    // End by Yang
                    //Add comments by Ryan Wu at 10:42 Apr. 5 2007.
                    //For support Aspnet Ajax 1.0.
                    //this.UIProcess.FireEvent(this, this.TextChanged, null);
                    // HelenLiu 2013/07/26 fix bug 1105 in IM HTML5.
                    //if (!this.switchPasswordChar) {
                    //if ( this.TextChanged != "") {
                    //    this.UIProcess.FireEvent(this, this.TextChanged, null, "TextChanged");
                    // }
                    //    this.switchPasswordChar = false;
                    //}
                    //end by Ryan Wu.
                }

                //this.OldText = this.GetText();
                this.LastText = this.GetText();

                //modified by sj for bug NKOI-355DB4B2D from Japan(bug 2951)
                //this.SelectionStart = 0;
                //this.SelectionEnd = 0;
                var length = this.GetText().GetLength();
                this.SelectionStart = length;
                this.SelectionEnd = length;

                //end by sj
                //Modified by shenyuan at 2006-02-21 for bug #5303.
                this.BuffText = this.LastText;

                // Add for DropDown Edit
                this.DropDownEditData.Text = this.GetText();

                //this.DropDownEditData.OldText = this.DropDownEditData.Text;
                this.DropDownEditData.LastText = this.DropDownEditData.Text;

                //modified by sj for bug NKOI-355DB4B2D from Japan(bug 2951)
                //this.DropDownEditData.SelectionStart = 0;
                //this.DropDownEditData.SelectionEnd = 0;
                this.DropDownEditData.SelectionStart = length;
                this.DropDownEditData.SelectionEnd = length;

                //end by sj
                this.DropDownEditData.BuffText = this.DropDownEditData.Text;

                //// Add comments by Yang at 16:34 October 11th 2007
                //// For fix bug 9006
                //this.SetLastClientValues();
                // HelenLiu 2013/07/08 fix bug 998 in IM HTML5.
                if (this.Ellipsis !== EllipsisMode.None) {
                    this.DealEllipsis(this.MultiLine, this.Ellipsis, this.EllipsisString, this.InputElement);
                }
            };

            /**
            * Gets a value indicates the zoom factor of the drop-down control and history list when open them by touch device.
            * @returns {number} An integer between 1-4 indicates the four zoom levels.
            */
            IMTextBox.prototype.GetTouchDropDownScale = function () {
                return this.TouchDropDownScale;
            };

            /**
            * Sets a value indicates the zoom factor of the drop-down control and history list when open them by touch device.
            * @param {number} ScaleRate An integer between 1-4 indicates the four zoom levels.
            */
            IMTextBox.prototype.SetTouchDropDownScale = function (ScaleRate) {
                ScaleRate = _input.Utility.CheckFloat(ScaleRate, 0.25, 4);
                this.TouchDropDownScale = ScaleRate;
            };

            /**
            * Gets whether copy, cut or paste the data to or from the clipboard when control are selected.
            * @returns {boolean}
            */
            IMTextBox.prototype.GetUseClipboard = function () {
                //if (this.ContextMenu.IsShow()) {
                //    // When context menu is show on firefox and chrome, we don't use the clipboard do the cut/copy/paste.
                //    if (!Utility.IsIE()) {
                //        return false;
                //    }
                //}
                // HelenLiu 2013/06/19 fix bug 739 in IM HTML5.
                return this.UseClipboard;
            };

            /**
            * Sets whether copy, cut or paste the data to or from the clipboard when control are selected.
            * @param {boolean} isUseClipboard
            */
            IMTextBox.prototype.SetUseClipboard = function (isUseClipboard) {
                isUseClipboard = _input.Utility.CheckBool(isUseClipboard);

                // HelenLiu 2013/06/19 fix bug 739 in IM HTML5.
                this.UseClipboard = isUseClipboard;
            };

            /**
            * Gets whether to use system password character.
            * @returns {boolean}
            */
            IMTextBox.prototype.GetUseSystemPasswordChar = function () {
                return this.UseSystemPasswordChar;
            };

            /**
            * Sets whether to use system password character.
            * @param {boolean} isUseSystemPasswordChar
            */
            IMTextBox.prototype.SetUseSystemPasswordChar = function (isUseSystemPasswordChar) {
                isUseSystemPasswordChar = _input.Utility.CheckBool(isUseSystemPasswordChar);
                this.UseSystemPasswordChar = isUseSystemPasswordChar;
                if (isUseSystemPasswordChar === true) {
                    this.PasswordMode = true;
                    this.SetPasswordChar(this.SystemPasswordChar());
                } else {
                    this.SetPasswordChar("");
                }
                this.UIProcess.Reset();
                //this.DropDownObj.UIProcess.Reset();
            };

            /**
            * Gets whether the control automatically wraps words to the beginning of the next line when necessary.
            * @returns {boolean}
            */
            IMTextBox.prototype.GetWordWrap = function () {
                return this.WordWrap;
            };

            /**
            * Sets whether the control automatically wraps words to the beginning of the next line when necessary.
            * @param {boolean} isWordWrap
            */
            IMTextBox.prototype.SetWordWrap = function (isWordWrap) {
                isWordWrap = _input.Utility.CheckBool(isWordWrap);
                this.WordWrap = isWordWrap;
                if (isWordWrap === false) {
                    this.InputElement.style.wordWrap = "normal";
                } else {
                    this.InputElement.style.wordWrap = "break-word";
                }

                // HelenLiu 2013/06/09 fix bug 658 in IM HTML5.0.
                //Following code just for Re-Layout. Because WordWrap can't refersh correctly.
                var w = this.InputElement.style.width;
                this.InputElement.style.width = (parseInt(this.InputElement.style.width) - 5) + "px";
                var self = this;
                setTimeout(function () {
                    self.InputElement.style.width = w;
                }, 10);

                this._CheckScrollBar(this.GetScrollBars(), this.GetScrollBarMode());
            };

            //#endregion
            //#region Public Methods
            /**
            *  Displays the drop-down edit box.
            */
            IMTextBox.prototype.Drop = function () {
                //// HelenLiu 2013/07/26 fix bug 997 in IM HTML5.
                //if (this.GetDroppedDown()) {
                //    this.DropDownObj.Close(true, true);
                //} else {
                //    // Terry fix IM Web 7.0 bug 844 in 2012/10/31
                //    if (Utility.IsIE9OrLater()) {
                //        if (this.GetDropDownEnabled()) {
                //            this.SetInnerFocus();
                //        }
                //        var thisObj = this;
                //        // HelenLiu 2013/07/12 fix bug 1045 in IM HTML5.
                //        // setTimeout(function () {
                //        thisObj.DropReal();
                //        // }, 0);
                //    }
                //    else {
                //        this.DropReal();
                //    }
                //}
                ////return this;
            };

            /**
            *  Clears the content of the control.
            */
            IMTextBox.prototype.Clear = function () {
                this.SetText("");
            };

            /**
            * Set focus on the control.
            */
            IMTextBox.prototype.SetFocus = function () {
                //this.UIUpdate.SetFocus();
            };

            //#endregion
            //#region ClientEvents
            /**
            * Raises the DropDownClose event.
            * @param {function|string} callBack
            */
            IMTextBox.prototype.OnDropDownClose = function (callBack) {
                callBack = _input.Utility.CheckFunction(callBack);

                this.DropDownCloseEvent = callBack;
            };

            /**
            * Raises the DropDownOpen event.
            * @param {function|string} callBack
            */
            IMTextBox.prototype.OnDropDownOpen = function (callBack) {
                callBack = _input.Utility.CheckFunction(callBack);

                this.DropDownOpenEvent = callBack;
            };

            /**
            * Occurs when the edit status has changed.
            * @param {function|string} callBack
            */
            IMTextBox.prototype.OnEditStatusChanged = function (callBack) {
                callBack = _input.Utility.CheckFunction(callBack);

                this.EditStatusChangedEvent = callBack;
            };

            /**
            * Occurs when the input is invalid.
            * @param {function|string} callBack
            */
            IMTextBox.prototype.OnInvalidInput = function (callBack) {
                callBack = _input.Utility.CheckFunction(callBack);

                this.InvalidInputEvent = callBack;
                this.UIProcess.InvalidInputEvent = callBack;
            };

            /**
            * Occurs when the key exit.
            * @param {function|string} callBack
            */
            IMTextBox.prototype.OnKeyExit = function (callBack) {
                callBack = _input.Utility.CheckFunction(callBack);

                this.KeyExitEvent = callBack;
            };

            /**
            * Occurs when the text has changed.
            * @param {function|string} callBack
            */
            IMTextBox.prototype.OnTextChanged = function (callBack) {
                callBack = _input.Utility.CheckFunction(callBack);

                this.TextChangedEvent = callBack;
            };

            IMTextBox.prototype.Undo = function () {
                var text = this.GetText();
                var bufftext = this.BuffText;
                var lasttext = this.LastText;
                var lastselectionstart = this.LastSelectionStart;
                var lastselectionend = this.LastSelectionEnd;

                if (!this.MultiLine) {
                    //  selectionstart = this.DropDownEditData.SelectionStart;
                    //  selectionend = this.DropDownEditData.SelectionEnd;
                    text = this.DropDownEditData.Text;
                    bufftext = this.DropDownEditData.BuffText;
                    lasttext = this.DropDownEditData.LastText;
                    lastselectionstart = this.DropDownEditData.LastSelectionStart;
                    lastselectionend = this.DropDownEditData.LastSelectionEnd;
                }

                // Modified by shenyuan at 2006-01-16.
                // Add an argument this.BuffText for it.
                var retInfo = this.UIProcess.TextBoxUndo(text, bufftext, lasttext, lastselectionstart, lastselectionend);

                if (retInfo == null) {
                    return false;
                }

                if (retInfo.Text != null) {
                    // Modified by shenyuan at 2006-01-16.
                    if (retInfo.DelInclude) {
                        this.BuffText = this.Text;

                        // Added by shenyuan at 2006-01-17 for bug #4989
                        this.IsUndoAfterDel = true;
                        if (!this.MultiLine) {
                            this.DropDownEditData.BuffText = this.DropDownEditData.Text;
                        }
                    } else {
                        this.LastText = this.Text;
                        if (!this.MultiLine) {
                            this.DropDownEditData.LastText = this.DropDownEditData.Text;
                        }
                    }
                    this.InternalSetText(retInfo.Text, true);
                }

                if (retInfo.SelectionStart != null) {
                    this.LastSelectionStart = this.SelectionStart;
                    this.SelectionStart = retInfo.SelectionStart;
                    if (!this.MultiLine) {
                        this.DropDownEditData.LastSelectionStart = this.DropDownEditData.SelectionStart;
                        this.DropDownEditData.SelectionStart = this.SelectionStart;
                        this.SelectionStart = this.GetSingleCurPosition(retInfo.Text, retInfo.SelectionStart);
                    }
                }

                if (retInfo.SelectionEnd != null) {
                    this.LastSelectionEnd = this.SelectionEnd;
                    this.SelectionEnd = retInfo.SelectionEnd;
                    if (!this.MultiLine) {
                        this.DropDownEditData.LastSelectionEnd = this.DropDownEditData.SelectionEnd;
                        this.DropDownEditData.SelectionEnd = this.SelectionEnd;
                        this.SelectionEnd = this.GetSingleCurPosition(retInfo.Text, retInfo.SelectionEnd);
                    }
                }

                if (retInfo.SetSelection == true) {
                    this.SetSelection(this.SelectionStart, this.SelectionEnd);
                }
            };

            IMTextBox.prototype.Cut = function () {
                var selectionstart = this.SelectionStart;
                var selectionend = this.SelectionEnd;
                var text = this.GetText();
                if (!this.MultiLine) {
                    selectionstart = this.DropDownEditData.SelectionStart;
                    selectionend = this.DropDownEditData.SelectionEnd;
                    text = this.DropDownEditData.Text;
                }
                var retInfo = this.UIProcess.Cut(text, selectionstart, selectionend);

                if (retInfo == null) {
                    return false;
                }

                if (retInfo.SelectionStart != null) {
                    this.SelectionStart = retInfo.SelectionStart;
                    if (!this.MultiLine) {
                        this.DropDownEditData.SelectionStart = this.SelectionStart;
                        this.SelectionStart = this.GetSingleCurPosition(retInfo.Text, retInfo.SelectionStart);
                    }
                }

                if (retInfo.SelectionEnd != null) {
                    this.SelectionEnd = retInfo.SelectionEnd;
                    if (!this.MultiLine) {
                        this.DropDownEditData.SelectionEnd = this.SelectionEnd;
                        this.SelectionEnd = this.GetSingleCurPosition(retInfo.Text, retInfo.SelectionEnd);
                    }
                }

                // Added by shenyuan at 2006-02-27 for bug #5385.
                if (retInfo.DelInclude) {
                    this.IsUndoAfterDel = true;
                    this.BuffText = this.GetText();
                    if (!this.MultiLine) {
                        this.DropDownEditData.BuffText = this.DropDownEditData.Text;
                    }
                }

                // Ended.
                if (retInfo.Text != null) {
                    // Add comments by Yang at 13:31 January 31th 2008
                    // For fix the bug 9623
                    //this.InternalSetText(retInfo.Text, true);
                    this.DirectSetText(retInfo.Text);
                    if (!this.MultiLine) {
                        this.DropDownEditData.Text = retInfo.Text;
                    }
                    // End by Yang
                }

                if (retInfo.SetSelection == true) {
                    this.SetSelection(this.SelectionStart, this.SelectionEnd);
                }

                if (retInfo.EventInfo != null) {
                    //Add comments by Ryan Wu at 11:30 Apr. 5 2007.
                    //For support Aspnet Ajax 1.0.
                    //this.UIProcess.FireEvent(this, retInfo.EventInfo.Name, retInfo.EventInfo.Args);
                    this.UIProcess.FireEvent(this, retInfo.EventInfo.Name, retInfo.EventInfo.Args, retInfo.EventInfo.Type);
                    //end by Ryan Wu.
                }
            };

            IMTextBox.prototype.Copy = function () {
                //this.UIProcess.Copy(this.GetClipContent(), this.SelectionStart, this.SelectionEnd);
                if (!this.PasswordMode) {
                    this.UIProcess.Copy(this.GetText(), this.SelectionStart, this.SelectionEnd);
                }
            };

            IMTextBox.prototype.Delete = function () {
                var selectionstart = this.SelectionStart;
                var selectionend = this.SelectionEnd;
                var text = this.GetText();
                if (!this.MultiLine) {
                    selectionstart = this.DropDownEditData.SelectionStart;
                    selectionend = this.DropDownEditData.SelectionEnd;
                    text = this.DropDownEditData.Text;
                }
                var retInfo = this.UIProcess.Delete(this.MultiLine, text, selectionstart, selectionend);

                if (retInfo == null) {
                    return false;
                }

                // Added by shenyuan at 2006-02-27 for bug #5385.
                if (retInfo.DelInclude) {
                    this.BuffText = this.Text;
                    this.IsUndoAfterDel = true;
                    if (!this.MultiLine) {
                        this.DropDownEditData.BuffText = this.DropDownEditData.Text;
                    }
                }

                if (retInfo.SelectionStart != null) {
                    this.SelectionStart = retInfo.SelectionStart;
                    if (!this.MultiLine) {
                        this.DropDownEditData.SelectionStart = this.SelectionStart;
                        this.SelectionStart = this.GetSingleCurPosition(retInfo.Text, retInfo.SelectionStart);
                    }
                }

                if (retInfo.SelectionEnd != null) {
                    this.SelectionEnd = retInfo.SelectionEnd;
                    if (!this.MultiLine) {
                        this.DropDownEditData.SelectionEnd = this.SelectionEnd;
                        this.SelectionEnd = this.GetSingleCurPosition(retInfo.Text, retInfo.SelectionEnd);
                    }
                }

                if (retInfo.Text != null) {
                    // Add comments by Yang at 13:31 January 31th 2008
                    // For fix the bug 9623
                    //this.InternalSetText(retInfo.Text, true);
                    this.DirectSetText(retInfo.Text);
                    if (!this.MultiLine) {
                        this.DropDownEditData.Text = retInfo.Text;
                    }
                    // End by Yang
                }

                if (retInfo.SetSelection == true) {
                    this.SetSelection(this.SelectionStart, this.SelectionEnd);
                }
            };

            IMTextBox.prototype.Paste = function (clipboardtext) {
                var selectionstart = this.SelectionStart;
                var selectionend = this.SelectionEnd;
                var text = this.GetText();
                if (!this.MultiLine) {
                    selectionstart = this.DropDownEditData.SelectionStart;
                    selectionend = this.DropDownEditData.SelectionEnd;
                    text = this.DropDownEditData.Text;
                }
                var retInfo = this.UIProcess.TextBoxPaste(selectionstart, selectionend, text, this.ExitOnLastChar, this.AcceptTab, this.AcceptReturn, this.MaxLength, this.LengthAsByte, this.MaxLineCount, this.CountWrappedLine, this.MultiLine, clipboardtext, false);

                if (retInfo == null) {
                    return false;
                }

                if (retInfo.SelectionStart != null) {
                    this.SelectionStart = retInfo.SelectionStart;
                    if (!this.MultiLine) {
                        this.DropDownEditData.SelectionStart = this.SelectionStart;
                        this.SelectionStart = this.GetSingleCurPosition(retInfo.Text, retInfo.SelectionStart);
                    }
                }

                if (retInfo.SelectionEnd != null) {
                    this.SelectionEnd = retInfo.SelectionEnd;
                    if (!this.MultiLine) {
                        this.DropDownEditData.SelectionEnd = this.SelectionEnd;
                        this.SelectionEnd = this.GetSingleCurPosition(retInfo.Text, retInfo.SelectionEnd);
                    }
                }

                if (retInfo.Text != null) {
                    // Add comments by Yang at 13:29 January 31th 2008
                    // For fix the bug 9623
                    //this.InternalSetText(retInfo.Text, true);
                    this.DirectSetText(retInfo.Text);
                    if (!this.MultiLine) {
                        this.DropDownEditData.Text = retInfo.Text;
                    }
                    // End by Yang
                }

                if (retInfo.SetSelection == true) {
                    this.SetSelection(this.SelectionStart, this.SelectionEnd);
                }

                if (retInfo.EventInfo != null) {
                    for (var i = 0; i < retInfo.EventInfo.length; i++) {
                        if (retInfo.EventInfo[i] != null) {
                            //Add comments by Ryan Wu at 10:42 Apr. 5 2007.
                            //For support Aspnet Ajax 1.0.
                            //this.UIProcess.FireEvent(this, retInfo.EventInfo[i].Name, retInfo.EventInfo[i].Args);
                            this.UIProcess.FireEvent(this, retInfo.EventInfo[i].Name, retInfo.EventInfo[i].Args, retInfo.EventInfo[i].Type);
                            //end by Ryan Wu.
                        }
                    }
                }
            };

            IMTextBox.prototype.SelectAll = function () {
                var text = this.GetText();
                if (!this.MultiLine) {
                    text = this.DropDownEditData.Text;
                }
                var retInfo = this.UIProcess.TextBoxSelectAll(text);

                if (retInfo == null) {
                    return false;
                }

                if (retInfo.SelectionStart != null) {
                    this.SelectionStart = retInfo.SelectionStart;
                    if (!this.MultiLine) {
                        this.DropDownEditData.SelectionStart = this.SelectionStart;
                        this.SelectionStart = this.GetSingleCurPosition(text, retInfo.SelectionStart);
                    }
                }

                if (retInfo.SelectionEnd != null) {
                    this.SelectionEnd = retInfo.SelectionEnd;
                    if (!this.MultiLine) {
                        this.DropDownEditData.SelectionEnd = this.SelectionEnd;
                        this.SelectionEnd = this.GetSingleCurPosition(text, retInfo.SelectionEnd);
                    }
                }

                if (retInfo.SetSelection == true) {
                    this.SetSelection(this.SelectionStart, this.SelectionEnd);
                }
            };

            //#endregion
            //#region Private Methods
            IMTextBox.prototype._CheckScrollBar = function (scrollbars, scrollbarmode) {
                switch (scrollbars) {
                    case 3 /* Both */:
                        if (scrollbarmode == 0 /* Automatic */) {
                            //str_Style += "overflow-x: auto;overflow-y: auto;";
                            this.InputElement.style.overflowX = "auto";
                            this.InputElement.style.overflowY = "auto";
                        } else {
                            //str_Style += wordWrap ? "overflow-x: auto;" : "overflow-x: scroll;";
                            //str_Style += "overflow-y: scroll;";
                            this.InputElement.style.overflowX = this.GetWordWrap() ? "auto" : "scroll";
                            this.InputElement.style.overflowY = "scroll";
                        }
                        break;

                    case 0 /* None */:
                        //str_Style += "overflow-x: hidden;overflow-y: hidden;";
                        this.InputElement.style.overflowX = "hidden";
                        this.InputElement.style.overflowY = "hidden";
                        break;

                    case 2 /* Vertical */:
                        if (scrollbarmode == 0 /* Automatic */) {
                            this.InputElement.style.overflowX = "hidden";
                            this.InputElement.style.overflowY = "auto";
                        } else {
                            this.InputElement.style.overflowX = "hidden";
                            this.InputElement.style.overflowY = "scroll";
                        }
                        break;

                    case 1 /* Horizontal */:
                        //str_Style += "overflow-y: hidden;";
                        this.InputElement.style.overflowY = "hidden";
                        if (scrollbarmode == 0 /* Automatic */) {
                            //str_Style += "overflow-x: auto;";
                            this.InputElement.style.overflowX = "auto";
                        } else {
                            //str_Style += wordWrap ? "overflow-x: auto;" : "overflow-x: scroll;";
                            this.InputElement.style.overflowX = this.GetWordWrap() ? "auto" : "scroll";
                        }
                        break;
                }
                if (_input.CoreUtility.safari || _input.CoreUtility.chrome) {
                    //Following code just for Re-Layout. Because WordWrap can't refersh correctly.
                    var w = this.InputElement.style.width;
                    this.InputElement.style.width = (parseInt(this.InputElement.style.width) - 1) + "px";
                    var self = this;
                    setTimeout(function () {
                        self.InputElement.style.width = w;
                    }, 0);
                }

                // HelenLiu 2013/06/27 fix bug 789 in IM HTML5.
                if (_input.CoreUtility.IPadAndIPhone) {
                    this.InputElement.style.webkitOverflowScrolling = "touch";
                }
                this.InternalSetText(this.GetText());
            };

            IMTextBox.prototype.Select = function () {
                //Terry jQuery Control
                //var RealID = this.GetId() + Utility.EditFieldSuffix;
                //if (this.IsjQueryControl == true) {
                //    RealID = this.GetId();
                //}
                if (this._isInnerKeyPressCall) {
                    delete this._isInnerKeyPressCall;
                    return;
                }

                this.SelectionStart = _input.Utility.GetSelectionStartPosition(this.InputElement);

                // Add comments by Yang at 13:47 Aug. 28th 2007
                // For Firefox doesn't support the method document.selection.createRange()
                //this.SelectionEnd = this.SelectionStart + document.selection.createRange().text.GetLength();
                this.SelectionEnd = this.SelectionStart + _input.Utility.GetSelectionText(this.InputElement).GetLength();

                // End by Yang
                if (!this.MultiLine) {
                    this.DropDownEditData.SelectionStart = this.GetMultiPosition(this.DropDownEditData.Text, this.SelectionStart);
                    this.DropDownEditData.SelectionEnd = this.GetMultiPosition(this.DropDownEditData.Text, this.SelectionEnd);
                }
            };

            // Migrate from InputMan_HTML5 Utility.SetSelection().
            IMTextBox.prototype._IMSetSelection = function (obj, start, end, multiLine) {
                //because in IE the following select() function will invoke the onselectstart
                //event and onselectstart will result in getting cursor position again, I must
                //add the posInfo object to return the original cursor position after we use
                //this function.
                var posInfo = { start: start, end: end };

                if (start > end) {
                    var temp = start;
                    start = end;
                    end = temp;
                }

                if (_input.CoreUtility.IsIE()) {
                    try  {
                        var range = obj.createTextRange();
                        if (!multiLine) {
                            //if (start != end)
                            //{
                            //commented by Kevin, May 21, 2007
                            //bug#7960, JIS2004
                            //change to standard position
                            //var newStart = start;
                            //end = end;
                            var newStart = obj.value.GetStandardPosition(start);
                            end = obj.value.GetStandardPosition(end, newStart - start);
                            start = newStart;

                            //end by Kevin
                            end = obj.value.length - end;
                            range.moveEnd('character', -1 * parseInt(end));
                            range.moveStart('character', parseInt(start));

                            // add by Sean Huang at 2009.01.06, for bug 1454 -->
                            _input.Utility.InnerSelect = true;

                            // end of Sean Huang <--
                            range.select();

                            // add by Sean Huang at 2009.01.06, for bug 1454 -->
                            _input.Utility.InnerSelect = false;
                            // end of Sean Huang <--
                            //}
                            //else
                            //{
                            //moveStart is used to collapse the highlight
                            //when we multiple select and then input a char.
                            //	range.moveStart("character", obj.value.length);
                            //	range.moveEnd("character", parseInt(start - obj.value.length));
                            //	range.select();
                            //}
                        } else {
                            var text = obj.value;
                            var lines = 0;
                            var startLines = 0;
                            var endLines = 0;
                            var index = text.lastIndexOf("\r\n");

                            while (index != -1) {
                                lines++;
                                if (index >= start) {
                                    startLines++;
                                }

                                if (index >= end) {
                                    endLines++;
                                }

                                text = text.substring(0, index);
                                index = text.lastIndexOf("\r\n");
                                //if (index === -1) { // IE 9 or later.
                                //    index = text.lastIndexOf('\n');
                                //}
                            }

                            startLines = lines - startLines;

                            // Add comments by Yang at 10:11 May 30 2007
                            // For fix bug #7960, JIS2004
                            //			start = start - startLines;
                            //
                            //
                            //			//commented by Kevin, May 21, 2007
                            //		    //bug#7960, JIS2004
                            //            //change to standard position
                            //	        var newStart = obj.value.GetStandardPosition(start);
                            //            end = obj.value.GetStandardPosition(end, newStart - start);
                            //            start = newStart;
                            //            //end by Kevin
                            var newStart = start;
                            end = end;
                            start = newStart - startLines;

                            // End by Yang
                            end = obj.value.length - end - endLines;

                            range.moveEnd('character', -1 * parseInt(end));
                            range.moveStart('character', parseInt(start));

                            // add by Sean Huang at 2009.01.06, for bug 1454 -->
                            _input.Utility.InnerSelect = true;

                            // end of Sean Huang <--
                            range.select();

                            // add by Sean Huang at 2009.01.06, for bug 1454 -->
                            _input.Utility.InnerSelect = false;
                            // end of Sean Huang <--
                        }
                    } catch (e) {
                    }
                } else {
                    //commented by Kevin, May 21, 2007
                    //bug#7960, JIS2004
                    //change to standard position
                    var newStart = start;
                    end = end;
                    start = newStart;

                    try  {
                        //modified by sj for 12239
                        //obj.setSelectionRange(parseInt(start), parseInt(end));
                        var intStart = parseInt(start);
                        var intEnd = parseInt(end);
                        if (obj.selectionStart != intStart || obj.selectionEnd != intEnd) {
                            obj.setSelectionRange(intStart, intEnd);
                        }
                        //if (Utility.chrome || Utility.firefox || Utility.safari) {
                        //    // DaryLuo 2013/05/23 fix bug 383 in IM HTMl5.0.
                        //    var selStartValue = obj.value.substring(0, intStart);
                        //    var width = Utility.MeasureText(selStartValue, obj).Width;
                        //    var height = obj.scrollHeight;
                        //    // Scroll the caret into view.
                        //    var clientWidth = obj.clientWidth;
                        //    var currentStyle = obj.currentStyle || window.getComputedStyle(obj, null);
                        //    clientWidth -= (parseInt(currentStyle.paddingLeft) + parseInt(currentStyle.paddingRight));
                        //    var clientHeight = obj.clientHeight;
                        //    clientHeight -= (parseInt(currentStyle.paddingTop) + parseInt(currentStyle.paddingBottom));
                        //    if (obj.scrollLeft > width) {
                        //        obj.scrollLeft = width;
                        //    }
                        //    else if (width > obj.scrollLeft + clientWidth) {
                        //        obj.scrollLeft = width - clientWidth + parseInt(currentStyle.paddingLeft);
                        //    }
                        //    if (obj.scrollTop > height) {
                        //        obj.scrollTop = height;
                        //    }
                        //    else if (height > obj.scrollTop + clientHeight) {
                        //        obj.scrollTop = height - clientHeight + parseInt(currentStyle.paddingTop);
                        //    }
                        //}
                        //end by sj
                    } catch (e) {
                    }
                    // end of Sean Huang <--
                }

                // DaryLuo 2013/05/23 fix bug 383 in IM HTMl5.0.
                var selStartValue = obj.value.substring(0, intStart);
                var width = _input.CoreUtility.MeasureText(selStartValue, obj).Width;
                var height = obj.scrollHeight;

                // Scroll the caret into view.
                var clientWidth = obj.clientWidth;
                var currentStyle = obj.currentStyle || window.getComputedStyle(obj, null);
                clientWidth -= (parseInt(currentStyle.paddingLeft) + parseInt(currentStyle.paddingRight));

                var clientHeight = obj.clientHeight;
                clientHeight -= (parseInt(currentStyle.paddingTop) + parseInt(currentStyle.paddingBottom));

                if (_input.CoreUtility.IsIE10OrLater()) {
                    clientWidth -= clientHeight; // width of clear button.
                }

                if (obj.scrollLeft > width) {
                    obj.scrollLeft = width;
                } else if (width > obj.scrollLeft + clientWidth) {
                    obj.scrollLeft = width - clientWidth + parseInt(currentStyle.paddingLeft);
                }

                if (obj.scrollTop > height) {
                    obj.scrollTop = height;
                } else if (height > obj.scrollTop + clientHeight) {
                    //Calculate text line height.
                    var textHeight = _input.CoreUtility.MeasureText("WQH", obj).Height;
                    var pos = this._getCursorTop(obj, textHeight, clientHeight);

                    //If scrolling is necessary and not SelectAll action, scroll smoothly (not jumpt the whole viewport).
                    //Otherwise, keep the original scrollTop.
                    obj.scrollTop = pos > textHeight && this.Text !== this.GetSelectedText() ? pos - textHeight : obj.scrollTop;
                }

                return posInfo;
            };

            IMTextBox.prototype._getCursorTop = function (txt, textHeight, clientHeight) {
                // https://github.com/component/textarea-caret-position/blob/master/index.js
                var top;
                try  {
                    // The properties that we copy into a mirrored div.
                    // Note that some browsers, such as Firefox,
                    // do not concatenate properties, i.e. padding-top, bottom etc. -> padding,
                    // so we have to do every single property specifically.
                    var properties = [
                        'direction',
                        'boxSizing',
                        'width',
                        'height',
                        'overflowX',
                        'overflowY',
                        'borderTopWidth',
                        'borderRightWidth',
                        'borderBottomWidth',
                        'borderLeftWidth',
                        'borderStyle',
                        'paddingTop',
                        'paddingRight',
                        'paddingBottom',
                        'paddingLeft',
                        'fontStyle',
                        'fontVariant',
                        'fontWeight',
                        'fontStretch',
                        'fontSize',
                        'fontSizeAdjust',
                        'lineHeight',
                        'fontFamily',
                        'textAlign',
                        'textTransform',
                        'textIndent',
                        'textDecoration',
                        'letterSpacing',
                        'wordSpacing',
                        'tabSize',
                        'MozTabSize'
                    ];

                    // mirrored div
                    var div = document.createElement('div');
                    div.id = 'input-textarea-caret-position-mirror-div';
                    document.body.appendChild(div);

                    var style = div.style;
                    var computed = window.getComputedStyle ? getComputedStyle(txt) : txt.currentStyle;

                    // default textarea styles
                    style.whiteSpace = 'pre-wrap';
                    if (txt.nodeName !== 'INPUT') {
                        style.wordWrap = 'break-word'; // only for textarea-s
                    }

                    // position off-screen
                    style.position = 'absolute'; // required to return coordinates properly
                    style.visibility = 'hidden'; // not 'display: none' because we want rendering

                    // transfer the element's properties to the div
                    properties.forEach(function (prop) {
                        style[prop] = computed[prop];
                    });

                    // Firefox lies about the overflow property for textareas: https://bugzilla.mozilla.org/show_bug.cgi?id=984275
                    if ($.browser.mozilla && txt.scrollHeight > parseInt(computed.height)) {
                        style.overflowY = 'scroll';
                    } else {
                        style.overflow = 'hidden'; // for Chrome to not render a scrollbar; IE keeps overflowY = 'scroll'
                    }

                    div.textContent = txt.value.substring(0, txt.selectionEnd);

                    // the second special handling for input type="text" vs textarea: spaces need to be replaced with non-breaking spaces - http://stackoverflow.com/a/13402035/1269037
                    if (txt.nodeName === 'INPUT') {
                        div.textContent = div.textContent.replace(/\s/g, '\u00a0');
                    }

                    var span = document.createElement('span');

                    // Wrapping must be replicated *exactly*, including when a long word gets
                    // onto the next line, with whitespace at the end of the line before (#7).
                    // The  *only* reliable way to do that is to copy the *entire* rest of the
                    // textarea's content into the <span> created at the caret position.
                    // for inputs, just '.' would be enough, but why bother?
                    span.textContent = txt.value.substring(txt.selectionEnd) || '.'; // || because a completely empty faux span doesn't render at all
                    div.appendChild(span);

                    top = span.offsetTop + parseInt(computed['borderTopWidth']);
                    document.body.removeChild(div);
                } catch (e) {
                    top = txt.scrollTop;
                }

                //Scrolling is not necessary if cursor position is fully within textarea height.
                return top + textHeight > clientHeight ? top : 0;
            };

            IMTextBox.prototype.SetSelection = function (start, end) {
                if (this.MultiLine) {
                    this._IMSetSelection(this.InputElement, start, end, true);
                } else {
                    this._IMSetSelection(this.InputElement, start, end);
                }

                this.SelectionStart = start;
                this.SelectionEnd = end;

                this.DropDownEditData.SelectionStart = start;
                this.DropDownEditData.SelectionEnd = end;
            };
            IMTextBox.prototype.InternalSetSelection = function (start, end) {
                if (this.MultiLine) {
                    this._IMSetSelection(this.InputElement, start, end, true);
                } else {
                    this._IMSetSelection(this.InputElement, start, end);
                    this.DropDownEditData.SelectionStart = this.GetMultiPosition(this.DropDownEditData.Text, start);
                    this.DropDownEditData.SelectionEnd = this.GetMultiPosition(this.DropDownEditData.Text, end);
                }

                this.SelectionStart = start;
                this.SelectionEnd = end;
            };
            IMTextBox.prototype.SetInnerSelectionStart = function (start) {
                this.SelectionStart = start;
                this.DropDownEditData.SelectionStart = start;
                //this.SetLastClientValues();
            };
            IMTextBox.prototype.SetInnerSelectionEnd = function (end) {
                this.SelectionEnd = end;
                this.DropDownEditData.SelectionEnd = end;
                //this.SetLastClientValues();
            };

            // Get the real selection position after restoring from the ellipsis string.
            IMTextBox.prototype.GetTrueSelection = function (selectionstart, selectionend, newText, oldText) {
                var ret = new Object();
                ret.SelectionStart = selectionstart;
                ret.SelectionEnd = selectionend;

                if (this.isTextEllipsis) {
                    ret.SelectionStart = this.GetTruePosition(selectionstart, newText, oldText, this.TextHeadLength);
                    if (selectionstart == selectionend) {
                        ret.SelectionEnd = ret.SelectionStart;
                    } else {
                        ret.SelectionEnd = this.GetTruePosition(selectionend, newText, oldText, this.TextHeadLength);
                    }
                    return ret;
                }
                return ret;
            };

            IMTextBox.prototype.DropDownListValidate = function (values) {
                var temp = values;
                var vList = new Array();
                for (var i = 0, j = 0; i < temp.length; i++) {
                    var tempi = temp[i];
                    if (this.UIProcess.ListValidateCheck(temp[i])) {
                        if (this.MaxLength != 0) {
                            tempi = this.UIProcess.MaxLengthCheck(tempi, this.MaxLength, this.LengthAsByte);
                        }

                        if (this.MaxLineCount != 0 && this.MultiLine) {
                            //			        tempi = this.UIProcess.MaxLineCheck("", "", tempi, this.MaxLineCount, this.CountWrappedLine);
                            if (this.PasswordMode) {
                                var passwordText = this.UIProcess.GetPasswordText(tempi, this.PasswordChar, this.MultiLine);
                                passwordText = this.UIProcess.MaxLineCheck("", "", passwordText, this.MaxLineCount, this.CountWrappedLine);
                                tempi = tempi.Substring(0, passwordText.GetLength());
                            } else {
                                tempi = this.UIProcess.MaxLineCheck("", "", tempi, this.MaxLineCount, this.CountWrappedLine);
                            }
                        }

                        if (tempi == temp[i]) {
                            vList[j] = temp[i];
                            j++;
                        }
                    }
                }

                return vList;
            };

            IMTextBox.prototype.SystemPasswordChar = function () {
                // change by Sean Huang at 2010.03.04 -->
                // does not have permission on Medium trusted level.-->
                // string strMachineOs = Utility.GetMachineOS(true, null).ToLower();
                //modified by sj for bug 3006
                //string strMachineOs = Utility.GetMachineOS(this.DesignMode, null).ToLower();
                var strMachineOs = _input.CoreUtility.GetClientOS();

                switch (strMachineOs.toLowerCase()) {
                    case "win2000":
                        return '*';
                    case "win2003":
                    case "winxp":
                    case "vista":
                    case "win7":
                    case "win8":
                        return '\u25cf';

                    default:
                        return '*';
                }
            };

            IMTextBox.prototype.InternalSetText = function (text, setDropDownEditData, fromDragDrop) {
                var formatedText = this.UIProcess.FormatCheck(text, this.AcceptTab, this.AcceptReturn);
                var maxLengthCheckedText = formatedText;
                if (this.MaxLength != 0) {
                    maxLengthCheckedText = this.UIProcess.MaxLengthCheck(formatedText, this.MaxLength, this.LengthAsByte);
                }
                if (this.MaxLineCount != 0 && this.MultiLine) {
                    if (this.PasswordMode) {
                        var passwordText = this.UIProcess.GetPasswordText(maxLengthCheckedText, this.PasswordChar, this.MultiLine);
                        passwordText = this.UIProcess.MaxLineCheck("", "", passwordText, this.MaxLineCount, this.CountWrappedLine);
                        maxLengthCheckedText = maxLengthCheckedText.Substring(0, passwordText.GetLength());
                    } else {
                        maxLengthCheckedText = this.UIProcess.MaxLineCheck("", "", maxLengthCheckedText, this.MaxLineCount, this.CountWrappedLine);
                    }
                }

                // HelenLiu 2013/07/09 fix bug 1005 in IM HTML5.
                if (fromDragDrop && (_input.CoreUtility.firefox || _input.CoreUtility.chrome)) {
                    this.DirectSetText(maxLengthCheckedText, true);
                } else {
                    this.DirectSetText(maxLengthCheckedText);
                }
                if (!this.MultiLine && setDropDownEditData) {
                    this.DropDownEditData.Text = maxLengthCheckedText;
                }

                return maxLengthCheckedText;
            };
            IMTextBox.prototype.DirectSetText = function (text, NoUpdateDisplay) {
                this.SystemChange = false;
                var passwordText = text;

                //		if ((!this.UseSystemPasswordChar && this.PasswordMode) || (this.MultiLine && this.UseSystemPasswordChar))
                if (this.PasswordMode) {
                    passwordText = this.UIProcess.GetPasswordText(text, this.PasswordChar, this.MultiLine);
                }

                // Add comments by Yang at 9:08 Sep. 10th 2007
                // For fix the bug that Only the first line will be shown when paste a multiline string to singleline Edit.
                if (!this.MultiLine && !_input.CoreUtility.IsIE()) {
                    passwordText = passwordText.replace(/\r\n/g, "");
                    passwordText = passwordText.replace(/\n/g, "");
                    passwordText = passwordText.replace(/\r/g, "");
                }

                if (this.Text != text) {
                    this.Text = text;

                    // HelenLiu 2013/07/26 fix bug 1105 in IM HTML5.
                    if (!this.switchPasswordChar) {
                        // Frank Liu removed, to fire 'textChanged' event in SetHideText(). 2013/09/1, for wijinputtext.
                        //// HelenLiu 2013/07/17 fix bug 1075 in IM HTML5.
                        //if (this.TextChangedEvent != "" /*&& document.activeElement !== this.InputElement*/ && this.TextChangedEvent != null) {
                        //    this.UIProcess.FireEvent(this, this.TextChangedEvent, null, "TextChanged");
                        //}
                        this.switchPasswordChar = false;
                    }
                    // DaryLuo 2014/02/11 fix bug 50765.
                    //this.GetJQueryInputElement().data('preText', text);
                }

                // End by Yang
                // HelenLiu 2013/07/09 fix bug 1005 in IM HTML5.
                if (!NoUpdateDisplay) {
                    this._setInputValueWithPlaceHolder(passwordText);
                }

                //// Add comments by Yang at 14:35 August 7th 2007
                //// For improve the performance for v2h1
                this.SetHideText(text);
            };
            IMTextBox.prototype.InternalDirectSetText = function (text) {
                var passwordText = text;

                //		if ((!this.UseSystemPasswordChar && this.PasswordMode) || (this.MultiLine && this.UseSystemPasswordChar))
                if (this.PasswordMode) {
                    passwordText = this.UIProcess.GetPasswordText(text, this.PasswordChar, this.MultiLine);
                }
                this._setInputValueWithPlaceHolder(passwordText);
            };

            IMTextBox.prototype._setInputValueWithPlaceHolder = function (text) {
                if (text === "") {
                    this.isNullText = true;
                    if (this.Focused === false) {
                        text = this.placeHolder;
                    }
                } else if (!(text === this.placeHolder && this.isNullText)) {
                    this.isNullText = false;
                }

                this.InputElement.value = text;
            };
            IMTextBox.prototype._getInputValueWithPlaceHolder = function () {
                return this.isNullText ? "" : this.InputElement.value;
            };

            IMTextBox.prototype.SetHideText = function (text) {
                if (this.hideText !== text) {
                    if (this.TextChangedEvent != "" && this.TextChangedEvent != null) {
                        this.UIProcess.FireEvent(this, this.TextChangedEvent, text, "textChanged");
                    }
                }

                this.hideText = text;
            };

            // Transfer the position from multiline type to single line type
            IMTextBox.prototype.GetSingleCurPosition = function (text, curposition) {
                if (curposition < 0) {
                    return -1;
                }
                var tempPositon = curposition;
                if (curposition >= text.GetLength()) {
                    tempPositon = text.GetLength();
                }
                var temp = text.Substring(0, tempPositon);
                while (true) {
                    var tempLength = temp.GetLength();
                    temp = temp.replace(/\r/g, "");
                    temp = temp.replace(/\n/g, "");
                    if (tempLength == temp.GetLength()) {
                        break;
                    }
                }
                return temp.GetLength();
            };
            IMTextBox.prototype.GetSingleText = function (multiText) {
                var temp = multiText;
                while (true) {
                    var oldLength = temp.GetLength();
                    temp = temp.replace(/\r/g, "");
                    temp = temp.replace(/\n/g, "");
                    if (temp.GetLength() == oldLength) {
                        break;
                    }
                }
                return temp;
            };

            // Transfer the position from single line type to multiline type
            IMTextBox.prototype.GetMultiPosition = function (multiText, signlePosition) {
                if (signlePosition <= 0) {
                    return 0;
                }
                if (signlePosition >= multiText.GetLength()) {
                    return multiText.GetLength();
                }
                var end = signlePosition;
                while (end < multiText.GetLength()) {
                    var text = multiText.Substring(0, end);
                    text = this.GetSingleText(text);
                    if (text.GetLength() == signlePosition) {
                        break;
                    } else {
                        end = end + 1;
                    }
                }
                return end;
            };

            IMTextBox.prototype.GetOldValue = function () {
                return this.OldText;
            };
            IMTextBox.prototype.GetValue = function () {
                return this.GetText();
            };
            IMTextBox.prototype.SetInnerText = function (text) {
                this.SetText(text);
            };
            IMTextBox.prototype.GetDisPlayText = function (text) {
                var passwordText = text;
                if (this.PasswordMode) {
                    passwordText = this.UIProcess.GetPasswordText(text, this.PasswordChar, this.MultiLine);
                }
                return passwordText;
            };

            IMTextBox.prototype.Focus = function () {
                this._destoryOverflowTip();

                //Set the dropdown list value.
                //document.all.ttt1.value += isFocusOnList;
                //added by shen yuan for bug 4620.
                this.oldTextValue = this._getInputValueWithPlaceHolder();

                //this.ProcessFishEyeButtonOnFocus();
                var oldText = this.oldTextValue;

                //end.
                // Add comments by Yang at 13:41 Aug. 28th 2007
                // Because FF doesn't support document.activeElement
                if (!_input.CoreUtility.IsIE()) {
                    this.IsActive = true;
                    //// Add comments by Yang at 12:32 Sep. 15th 2007
                    //// For fix bug 8843
                    ////modified by sj for bug 2408, 2409 ,2977 Japan(NKOI-566BC9866)
                    ////this.DropDownObj.IsDropDownRaisePostBack = false;
                    //if (this.DropDownObj) {
                    //    this.DropDownObj.IsDropDownRaisePostBack = false;
                    //}
                    ////end by sj
                    //// End by Yang
                }

                // End by Yang
                // Add for OverflowTip
                this.HasFocus = true;

                //if (this.ToolTip != null) {
                //    this.ToolTip.Close();
                //    this.ToolTip = null;
                //}
                if (!this._autoComplete.GetIsFocusOnList()) {
                    this._autoComplete.HideDropdown();

                    // Modified by shenyuan at 2005-12-16
                    var items;
                    if (this.AutoCompleteType != "None") {
                        items = this.GetItem(this.AutoCompleteType);
                    } else {
                        items = this.GetItem(this.GetId(), "focus");
                    }

                    // Ended.
                    //modified by sj
                    //if (items != null)
                    //{
                    //data1 = items.sort();
                    var data1 = items != null ? items.sort() : null;

                    //end by sj
                    //// Modified by shenyuan at 2006-01-17 for bug #4987.
                    //// When the borderwidth is not default value, 2px,
                    //// should add it to the historylist's position.
                    //var borderwidth = 0;
                    //if (this.BorderWidth != null) {
                    //    borderwidth = parseInt(this.BorderWidth);
                    //}
                    // Added an argument IsVS2005 for bug #5174.
                    //if (document.readyState == "complete" || document.readyState == "interactive")
                    if (_input.Utility.LoadComplete == true) {
                        this._autoComplete.SetDataList(data1);
                        // End by Yang
                    }
                } else {
                    this._autoComplete.SetIsFocusOnList(false);
                }

                var retInfo = this.UIProcess.TextBoxFocus(this.FocusType, this.InputElement, this.GetText(), this.MultiLine, this.HighlightText, false);

                //Add comments by Ryan Wu at 15:18 Jan. 16 2007.
                //For fix bug#6447.
                _input.Utility.CurrentActiveControlId = this.GetId();

                //end by Ryan Wu.
                if (retInfo == null) {
                    return;
                }
                if (this.isTextEllipsis) {
                    this.InternalDirectSetText(this.Text);
                }
                if (retInfo.SelectionStart != null) {
                    this.SelectionStart = retInfo.SelectionStart;
                }

                if (retInfo.SelectionEnd != null) {
                    this.SelectionEnd = retInfo.SelectionEnd;
                    this.SelectionLength = Math.abs(this.SelectionEnd - this.SelectionStart);
                }
                if (retInfo.SelectionStart != null && retInfo.SelectionEnd != null) {
                    var retSelection = this.GetTrueSelection(this.SelectionStart, this.SelectionEnd, this.Text, oldText);
                    if (this.isTextEllipsis) {
                        this.SelectionStart = retSelection.SelectionStart;
                        this.SelectionEnd = retSelection.SelectionEnd;
                    }

                    //this.DropDownObj.SetInnerSelection(retSelection.SelectionStart, retSelection.SelectionEnd);
                    if (!this.MultiLine) {
                        this.DropDownEditData.SelectionStart = this.GetMultiPosition(this.DropDownEditData.Text, retSelection.SelectionStart);
                        this.DropDownEditData.SelectionEnd = this.GetMultiPosition(this.DropDownEditData.Text, retSelection.SelectionEnd);
                    }
                }
                if (this.UIProcess.japInput == true) {
                    if (this.truePosition != -1) {
                        this.SelectionStart = this.truePosition;
                        this.SelectionEnd = this.truePosition;
                        if (!this.MultiLine) {
                            this.DropDownEditData.SelectionStart = this.GetMultiPosition(this.DropDownEditData.Text, this.SelectionStart);
                            this.DropDownEditData.SelectionEnd = this.GetMultiPosition(this.DropDownEditData.Text, this.SelectionEnd);
                        }
                    }
                    this.UIProcess.japInput = false;
                } else {
                    //Update oldText, oldSelectionStart,oldSelectionEnd
                    if (this.FocusType != 2 /* ContextMenu */ && this.FocusType != 3 /* ClientEvent */ && this.FocusType != 7 /* DropDown */ && this.FocusType != 11 /* DragDrop */) {
                        this.OldText = this.GetText();
                        this.OldSelectionStart = this.SelectionStart;
                        this.OldSelectionEnd = this.SelectionEnd;

                        //Commented by shenyuan at 2006-01-16.
                        //when gets focus, the buff will not change.
                        //this.LastText = this.OldText;
                        this.LastSelectionStart = this.OldSelectionStart;
                        this.LastSelectionEnd = this.OldSelectionEnd;
                        if (!this.MultiLine) {
                            this.DropDownEditData.OldText = this.DropDownEditData.Text;
                            this.DropDownEditData.OldSelectionStart = this.DropDownEditData.SelectionStart;
                            this.DropDownEditData.OldSelectionEnd = this.DropDownEditData.SelectionEnd;
                            this.DropDownEditData.LastSelectionStart = this.DropDownEditData.OldSelectionStart;
                            this.DropDownEditData.LastSelectionEnd = this.DropDownEditData.OldSelectionEnd;
                            var thisObj = this;
                            setTimeout(function () {
                                // DaryLuo 2012/07/27 fix bug 277 in IM web 7.0.
                                thisObj.DropDownEditData.SelectionStart = thisObj.SelectionStart;
                                thisObj.DropDownEditData.SelectionEnd = thisObj.SelectionEnd;
                            }, 0);
                        }
                    }
                }

                // add by Sean Huang at 2008.11.06, for bug 10007 -->
                if (this.ReadOnly == true && this.FocusType == 0 /* None */) {
                    this.SelectionStart = 0;
                    this.SelectionEnd = this.Text.length;
                }

                // end of Sean Huang <--
                if (retInfo.SetSelection == true || this.isTextEllipsis) {
                    this.SetSelection(this.SelectionStart, this.SelectionEnd);
                }

                if (this.IsCausedByImplementingDrop) {
                    this.IsCausedByImplementingDrop = false;
                }

                //Added for KeyExit event when drag text to Edit
                if (this.FocusExit) {
                    this.UIProcess.MoveControl(this.InputElement, true);
                    this.FocusExit = false;
                }

                // Add comments by Yang at 14:12 Feb. 25th 2008
                // For fix the bug 9695
                if (this.isTextEllipsis) {
                    this.isTextEllipsis = false;
                }
                // End by Yang
                //if (Utility.safari && this._safariDropText) {
                //    this.Text = this.InputElement.value; //this.UIUpdate.GetText();
                //    this._safariDropText = null;
                //    this.InternalSetText(this.GetText());
                //}
            };
            IMTextBox.prototype.SetInnerFocus = function (focusType) {
                if (focusType !== null && focusType !== undefined) {
                    this.FocusType = focusType;
                } else {
                    this.FocusType = 3 /* ClientEvent */;
                }

                //this.UIUpdate.SetFocus();
                this.InputElement.focus();

                this.SetSelection(this.SelectionStart, this.SelectionEnd);
                if (!this.MultiLine) {
                    this.DropDownEditData.SelectionStart = this.GetMultiPosition(this.DropDownEditData.Text, this.SelectionStart);
                    this.DropDownEditData.SelectionEnd = this.GetMultiPosition(this.DropDownEditData.Text, this.SelectionEnd);
                }
            };
            IMTextBox.prototype.LoseFocus = function (evt) {
                //this.ProcessFishEyeButtonOnLostFocus(false);
                // Add comments by Yang at 13:49 Aug. 28th 2007
                // For Firefox doesn't support document.activeElement
                if (!_input.CoreUtility.IsIE()) {
                    this.IsActive = false;
                }

                //// add by Sean Huang at 2008.10.30, for bug 9908 -->
                this.FireKeyExit();

                //// end of Sean Huang <--
                //add by sj for readingImeStringOutput
                if (_input.CoreUtility.IsIE() && this.ImeMode) {
                    this.ReadingImeOperation();
                }

                //end by sj
                // Add comments by Yang at 18:12 May 28 2007
                // For fix bug 8230
                // Add Comments by Yang at 14:08 May 8 2007
                // For Japanese
                // For fix bug 7968
                //		if (this.ImeMode == true)
                //		{
                //			this.ImeInput("LoseFocusInput");
                //		}
                // End by Yang
                // Add comments by Yang at 9:42 Aug. 29th 2007
                // For Firefox doesn't support set a value in onblur event when IME opens.
                //this.ImeInput("LoseFocusInput");
                if (_input.CoreUtility.IsIE()) {
                    // Add comments by Yang at 13:55 Sep. 20th 2007
                    // For fix bug 8715 & 8716
                    //this.ImeInput("LoseFocusInput");
                    if (this.ImeMode) {
                        this.ImeInput("LoseFocusInput", undefined, evt);
                        this.ImeSelectTimes = 0;
                    } else if (this.Text != this.GetText()) {
                        this.InternalSetText(this.Text, true);
                    }
                    // End by Yang
                } else {
                    // Add comments by Yang at 13:55 Sep. 20th 2007
                    // For fix bug 8715 & 8716
                    //this.ImeInput("ReInput", true);
                    if (this.ImeMode) {
                        this.ImeInput("ReInput", true, evt);
                    }

                    // End by Yang
                    // Add comments by Yang at 9:42 Aug. 29th 2007
                    // For Firefox doesn't support set a value in onblur event when IME opens.
                    // Add comments by Yang at 11:07 October 12th 2007
                    // For fix the bug 9017
                    //if (this.Text != this.GetText())
                    if (this.GetDisPlayText(this.Text) != this._getInputValueWithPlaceHolder()) {
                        var tempText = this.Text;

                        // add by Sean Huang at 2009.02.17, for bug 1883 -->
                        tempText = tempText.replace(/\\/g, '\\\\');

                        // end of Sean Huang <--
                        if (!this.MultiLine) {
                            tempText = tempText.replace(/\r\n/g, "");
                            tempText = tempText.replace(/\r/g, "");
                            tempText = tempText.replace(/\n/g, "");
                        } else {
                            tempText = tempText.replace(/\r/g, "\\r");
                            tempText = tempText.replace(/\n/g, "\\n");
                        }

                        // change by Sean Huang at 2010.09.19, for bug 3020 -->
                        //window.setTimeout("FindIMControl('" + this.ID + "').InternalSetText('" + tempText + "', true)", 0);
                        //var id = this.GetId();
                        //var self = this;
                        //window.setTimeout(function () { self.InternalSetText(tempText, true); }, 0);
                        this.InternalSetText(tempText, true);
                        // end of Sean Huang <--
                    }
                    // End by Yang
                }

                // End by Yang
                // End by Yang
                this.HasFocus = false;

                if (this._autoComplete.IsVisible()) {
                    if (this._autoComplete.GetIsMouseOnList()) {
                        return;
                    } else {
                        this._autoComplete.HideDropdown();
                    }
                    // Ended.
                }

                //if (this.ContextMenu.IsShow()) {
                //    this.ContextMenu.Close();
                //}
                // Add comments by Yang at 13:34 June 1st 2007
                // For fix bug 8092
                //Add by YangYang at 21:39 Apr. 20 2007.
                //For support Aspnet Ajax 1.0.
                //this.SetLastClientValues();
                //end by YangYang.
                // End by Yang
                // Add Comments by Yang at 14:08 May 8 2007
                // For fix bug 7968
                //For Japanese
                //		if (this.ImeMode == true)
                //		{
                //			this.ImeInput("LoseFocusInput");
                //		}
                // End by Yang
                //The default FocusType is FocusType.None
                if (this.FocusType != 7 /* DropDown */) {
                    this.FocusType = 0 /* None */;
                }

                //		if (this.PasswordMode && !this.UseSystemPasswordChar)
                //		{
                //		    return;
                //		}
                // Add comments by Yang at 11:35 Aug. 28th 2007
                // In ie and firefox, we always implement the method ImeInput().
                // In the ime input handle method, the parameter <this.Text> is updated.
                // But sometimes the input's value isn't updated.
                // So we should use the parameter <this.Text>.
                var nowText;
                if (_input.CoreUtility.IsIE()) {
                    nowText = this.GetText();
                } else {
                    nowText = this.hideText;
                }

                // End by Yang
                //if (this.OldText != this.GetText() && !this.UIProcess.japInput && this.FocusType != FocusType.DropDown)
                // Add comments by Yang at 9:58 Sep. 13th 2007
                // For fix the bug that when press the droop-down button to close the drop-down window.
                // the textchanged event couldn't be fired.
                //if (this.OldText != nowText && !this.UIProcess.japInput && this.FocusType != FocusType.DropDown)
                if (this.OldText != nowText && !this.UIProcess.japInput) {
                    this.OldText = this.Text;

                    // Maybe the following codes should be deleted,
                    // because it is redundant.
                    if (_input.CoreUtility.IsIE()) {
                        this.Text = this.GetText();
                        this.SetHideText(this.GetText());
                    }

                    this.DealEllipsis(this.MultiLine, this.Ellipsis, this.EllipsisString, this.InputElement);

                    // Frank Liu removed as _onBlur() in wijinputcore fired this event.
                    //if (this.TextChangedEvent != null) {
                    //    var eventInfo: any = new Object();
                    //    eventInfo.Name = this.TextChangedEvent;
                    //    eventInfo.Args = null;
                    //    //Add comments by Ryan Wu at 10:42 Apr. 5 2007.
                    //    //For support Aspnet Ajax 1.0.
                    //    //this.UIProcess.FireEvent(this, eventInfo.Name, eventInfo.Args);
                    //    this.UIProcess.FireEvent(this, eventInfo.Name, eventInfo.Args, "TextChanged");
                    //    //end by Ryan Wu.
                    //}
                    if (!this.SystemChange || (this.oldTextValue != this.GetText())) {
                        this.SystemChange = true;
                        // Frank Liu removed at 2013/08/14.
                        //Utility.FireSystemEvent(this.InputElement, "onchange");
                        //if (this.ClientEvents.StandardClientEvents != null) {
                        //    var SystemEvent: any = new Object();
                        //    SystemEvent.Name = this.ClientEvents.StandardClientEvents.onchange;
                        //    SystemEvent.Args = null;
                        //    // change by Sean Huang at 2009.04.24, for bug 2241 -->
                        //    //this.UIProcess.FireEvent(null, SystemEvent.Name, SystemEvent.Args);
                        //    this.UIProcess.FireEvent(this.InputElement, SystemEvent.Name, SystemEvent.Args);
                        //    // end of Sean Huang <--
                        //}
                    }
                } else {
                    this.DealEllipsis(this.MultiLine, this.Ellipsis, this.EllipsisString, this.InputElement);

                    //this.SetLastClientValues();
                    // Terry fix IM Web SP3.5 bug 7 in 2011/12/22
                    if (this.hideText != this.GetText() && _input.CoreUtility.IsIE()) {
                        this.SetHideText(this.GetText());
                    }
                }
            };
            IMTextBox.prototype.FireKeyExit = function () {
                if (this.EventInfo != null && this.EventInfo.Type == "KeyExit") {
                    this.UIProcess.FireEvent(this, this.EventInfo.Name, this.EventInfo.Args, this.EventInfo.Type);

                    this.FocusType = 4 /* KeyExit */;
                    this.EventInfo = null;
                }
            };

            // Get the real position from the ellipsis string.
            IMTextBox.prototype.GetTruePosition = function (oldSelection, newText, oldText, textHeadLength) {
                var ellipsisStringLength = this.EllipsisString.GetLength();

                if (oldSelection <= textHeadLength) {
                    return oldSelection;
                } else if (oldSelection >= (textHeadLength + ellipsisStringLength)) {
                    return (newText.GetLength() - oldText.GetLength() + oldSelection);
                }

                var ellipsisTextLength = newText.GetLength() - oldText.GetLength() + ellipsisStringLength;
                var trueSelection = Math.floor((oldSelection - textHeadLength) * ellipsisTextLength / ellipsisStringLength) + textHeadLength;
                return trueSelection;
            };

            IMTextBox.prototype.DealEllipsis = function (Multiline, Ellipsis, EllipsisString, obj) {
                this.isTextEllipsis = false;
                if (Multiline || Ellipsis == EllipsisMode.None) {
                    return;
                }

                //modified by sj 2008.8.12 for bug 509
                this.InternalDirectSetText(this.Text);

                //end by sj
                var _ellipsisMode = Ellipsis;
                var i_length = 0;
                var i_onecharwidth = 0;
                var subwidth = 0;
                var ellipsisnum = 0;
                var tempstring = obj.value;
                var savestring = obj.value;
                var tempheadstring = "";
                var temptailstring = "";
                var headstringcount = 0;
                var isAddTail = true;

                obj.value = tempstring;

                if (_input.Utility.GetTextBoxScrollWidth(obj, this.IsControlInPreview) > obj.clientWidth) {
                    this.isTextEllipsis = true;
                    obj.value = EllipsisString;
                    var _EllipsisString = EllipsisString;
                    if (_input.Utility.GetTextBoxScrollWidth(obj, this.IsControlInPreview) > obj.clientWidth) {
                        _EllipsisString = "";
                        tempstring = EllipsisString;
                        savestring = EllipsisString;
                    } else if (_ellipsisMode == EllipsisMode.EllipsisPath) {
                        var iLastIndex = savestring.LastIndexOf("\\");
                        if (iLastIndex != -1) {
                            obj.value = _EllipsisString + savestring.substr(iLastIndex);
                            if (_input.Utility.GetTextBoxScrollWidth(obj, this.IsControlInPreview) <= obj.clientWidth) {
                                _EllipsisString = obj.value;
                                tempstring = savestring.Substring(0, iLastIndex);
                                _ellipsisMode = EllipsisMode.EllipsisEnd;
                            }
                        }
                    }

                    obj.value = tempstring + _EllipsisString;

                    do {
                        i_length = obj.value.GetLength();
                        i_onecharwidth = Math.ceil(_input.Utility.GetTextBoxScrollWidth(obj, this.IsControlInPreview) / i_length);
                        subwidth = _input.Utility.GetTextBoxScrollWidth(obj, this.IsControlInPreview) - obj.clientWidth;
                        ellipsisnum = Math.ceil(subwidth / i_onecharwidth);
                        if (_ellipsisMode == EllipsisMode.EllipsisEnd) {
                            obj.value = tempstring.Substring(0, tempstring.GetLength() - ellipsisnum) + _EllipsisString;
                            tempstring = tempstring.Substring(0, tempstring.GetLength() - ellipsisnum);
                        } else if (_ellipsisMode == EllipsisMode.EllipsisPath) {
                            headstringcount = Math.ceil((tempstring.GetLength() - ellipsisnum) / 2);
                            tempheadstring = tempstring.substr(0, headstringcount);
                            temptailstring = tempstring.substr(headstringcount + ellipsisnum);
                            obj.value = tempheadstring + _EllipsisString + temptailstring;
                            tempstring = tempheadstring + temptailstring;
                        }
                    } while(_input.Utility.GetTextBoxScrollWidth(obj, this.IsControlInPreview) > obj.clientWidth);

                    var i_tempstringlen = tempstring.GetLength();

                    do {
                        if (_ellipsisMode == EllipsisMode.EllipsisEnd) {
                            obj.value = savestring.Substring(0, i_tempstringlen + 1) + _EllipsisString;
                            i_tempstringlen = i_tempstringlen + 1;
                        } else if (_ellipsisMode == EllipsisMode.EllipsisPath) {
                            if (isAddTail) {
                                temptailstring = savestring.substr(savestring.GetLength() - temptailstring.GetLength() - 1);
                                isAddTail = false;
                            } else {
                                tempheadstring = savestring.substr(0, tempheadstring.GetLength() + 1);
                                isAddTail = true;
                            }
                            obj.value = tempheadstring + _EllipsisString + temptailstring;
                        }
                    } while(_input.Utility.GetTextBoxScrollWidth(obj, this.IsControlInPreview) == obj.clientWidth);

                    if (_ellipsisMode == EllipsisMode.EllipsisEnd) {
                        obj.value = savestring.Substring(0, i_tempstringlen - 1) + _EllipsisString;
                        this.TextHeadLength = i_tempstringlen - 1;
                    } else if (_ellipsisMode == EllipsisMode.EllipsisPath) {
                        if (isAddTail) {
                            tempheadstring = savestring.substr(0, tempheadstring.GetLength() - 1);
                        } else {
                            temptailstring = savestring.substr(savestring.GetLength() - temptailstring.GetLength() + 1);
                        }
                        obj.value = tempheadstring + _EllipsisString + temptailstring;
                        this.TextHeadLength = tempheadstring.GetLength();
                    }
                }
            };

            //ImeInput = function(operate, reInputType)
            IMTextBox.prototype.ImeInput = function (operate, reInputType, evt, fromContextMenuPaste) {
                if (fromContextMenuPaste) {
                    var oldText = this.Text;
                    var selEnd = this.SelectionEnd;
                    var selStart = this.SelectionStart;
                }

                //var newValue = this.InputElement.value;
                // Add comments by Yang at 10:02 June 1st 2007
                // For fix bug 8338
                //var newValue = this.UIUpdate.GetText();
                //var newValue = this.GetText();
                // End by Yang
                var newValue;

                //modified by sj 2008.8.8 for bug 33
                if (operate == "DirectInput" && !reInputType) {
                    newValue = this.InputElement.value;
                } else {
                    //modified by sj 2008.8.8 for bug 591
                    if (operate == "LoseFocusInput" && this._getInputValueWithPlaceHolder() != this.GetText()) {
                        newValue = this._getInputValueWithPlaceHolder();
                    } else {
                        newValue = this.GetText();
                    }
                }

                //end by sj
                //Add for Bug 3724
                if (newValue == this.Text) {
                    this.lastValue = this.Text;
                    if (evt != null) {
                        _input.Utility.PreventDefault(evt);
                    }

                    //update by Sean Huang 2008.08.13 for bug 97 (ttp) -->
                    this.ImeMode = false;

                    //end by Sean Huang <--
                    return false;
                }

                // Add comments by Yang at 17:09 Sep. 25th 2007
                // For fix bug 8715
                //
                // HelenLiu 2013/06/28 fix bug 781 in IM HTML5.
                if (_input.CoreUtility.IsIE() && this.HasValidatedImeInput) {
                    this.InternalSetText(newValue, true);

                    //this.InternalSetText(this.Text, true);
                    if (fromContextMenuPaste) {
                        var newText = this.Text;
                        if (oldText !== newText) {
                            var s = selStart + newText.length - (oldText.length - (selEnd - selStart));
                            this.SetSelection(s, s);
                        }
                    }
                    return false;
                }

                // End by Yang
                //Now get the input ime text;
                var imeInputText;
                if (this.Text != "") {
                    var start = Math.min(this.SelectionStart, this.SelectionEnd);
                    var end = Math.max(this.SelectionStart, this.SelectionEnd);

                    // Add comments by Yang at 14:02 October 12th 2007
                    // For fix the bug 9017
                    var thisText = this.Text;
                    if (!_input.CoreUtility.IsIE()) {
                        thisText = this.GetDisPlayText(this.Text);
                    }
                    if (end < thisText.GetLength()) {
                        // Add comments by Yang at 14:02 October 12th 2007
                        // For fix the bug 9017
                        //var lastText = this.Text.Substring(end, this.Text.GetLength());
                        var lastText = thisText.Substring(end, thisText.GetLength());

                        // End by Yang
                        var textIndex = newValue.IndexOf(lastText);

                        if (textIndex != -1) {
                            //imeInputText = newValue.Substring(start, textIndex);
                            imeInputText = newValue.Substring(start, newValue.GetLength() - lastText.GetLength());
                        } else {
                            imeInputText = "";
                        }
                    } else {
                        imeInputText = newValue.Substring(start, newValue.GetLength());
                    }
                } else {
                    imeInputText = newValue;
                }

                //For autocomplete dropdown.
                if (imeInputText != "" && !this.MultiLine && !this._autoComplete.IsDataListEmpty() && this.EnableAutoComplete) {
                    this._autoComplete.KeyUp(null, true);
                }

                //Discard the new input character.
                if (operate == "ReInput") {
                    // Add comments by Yang at 14:45 May 29 2007
                    // For fix bug 8230
                    //imeInputText = imeInputText.Substring(0, imeInputText.GetLength() - 1);
                    if (!reInputType) {
                        imeInputText = imeInputText.Substring(0, imeInputText.GetLength() - 1);
                    } else {
                        imeInputText = imeInputText.Substring(0, imeInputText.GetLength());
                    }
                    // End by Yang
                }

                if (operate == "Record")
                    return imeInputText;

                // Add comments by Yang at 14:12 May 8 2007
                // For fix bug 7968
                var isLoseFocusInput = false;

                // End by Yang
                if (operate == "LoseFocusInput") {
                    if (imeInputText == "") {
                        // Add comments by Yang at 14:45 May 29 2007
                        // For fix bug 8230
                        if (this.GetText() != this.Text) {
                            this._setInputValueWithPlaceHolder(this.Text);
                        }

                        // End by Yang
                        return;
                    }

                    //Mask_ImeResponse = true;
                    // Add comments by Yang at 14:12 May 8 2007
                    // For fix bug 7968
                    isLoseFocusInput = true;

                    // End by Yang
                    this.UIProcess.japInput = true;
                }

                //Call keypress function to process insert text with ime mode.
                this.UIProcess.keypressResponse = true;

                //Ensure this.Text is tha same as this.GetText(),before this.KeyPress called;
                //this.UIUpdate.SetText(this.Text);
                this.UIProcess.inputJap = true;

                // Add comments by Yang at 15:14 Sep. 24th 2007
                // For fix bug that Firefox doesn't support set a value in onblur event when IME opens.
                if (operate == "ReInput" || (!_input.CoreUtility.IsIE() && operate == "ClickInput")) {
                    // Add comments by Yang at 14:14 May 8 2007
                    // For separate the event handler and method of keypress.
                    //this.InnerKeyPress(imeInputText, true, isLoseFocusInput);
                    this.InnerKeyPress(imeInputText, true, isLoseFocusInput);
                    // End by Yang
                } else {
                    // Add comments by Yang at 14:14 May 8 2007
                    // For separate the event handler and method of keypress.
                    //this.InnerKeyPress(imeInputText, false, isLoseFocusInput);
                    this.InnerKeyPress(imeInputText, false, isLoseFocusInput);
                    // End by Yang
                }

                // Add comments by Yang at 17:10 Sep. 25th 2007
                // For fix bug 8715
                //if (Utility.IsIE()) {
                this.HasValidatedImeInput = true;

                //}
                // End by Yang
                this.UIProcess.inputJap = false;
                this.UIProcess.japInput = false;
                this.ImeMode = false;
                this.ImeSelect = false;

                //We can not control ime start and end,so if there are two times ime operation
                //in the same input case. We should check all the characters and close ime.
                if (operate == "ReInput" || operate == "ClickInput") {
                    //this.UIProcess.japInput = true;
                    this.truePosition = this.SelectionStart;
                    this.FocusType = 8 /* ImeInput */;
                    //this.InputElement.blur();
                    //this.UIUpdate.SetText(this.Text);
                    //this.InputElement.focus();
                }
                /*
                if (!this.MultiLine)
                {
                this.SetSelection(this.SelectionStart, this.SelectionEnd)
                }*/
            };

            IMTextBox.prototype.CanUndo = function () {
                if (this.IsChangedByDropDownEdit) {
                    if (this.IsUndoAfterDel) {
                        this.BuffText = this.GetText();
                    } else {
                        this.LastText = this.GetText();
                    }
                    this.IsChangedByDropDownEdit = false;
                    return true;
                }

                // Added by shenyuan at 2006-01-17 for bug #4989
                if (this.IsUndoAfterDel) {
                    return this.GetText() != this.BuffText;
                } else {
                    return this.GetText() != this.LastText;
                }
            };

            // Retrieve the value of the cookie with the specified name.
            IMTextBox.prototype.GetCookie = function (sName) {
                // cookies are separated by semicolons
                var aCookie = document.cookie.split("; ");
                for (var i = 0; i < aCookie.length; i++) {
                    // a name/value pair (a crumb) is separated by an equal sign
                    var aCrumb = aCookie[i].split("=");
                    if (sName == aCrumb[0]) {
                        if (aCrumb[1] != null) {
                            return window.unescape(aCrumb[1]);
                        }
                    }
                }

                // a cookie with the requested name does not exist
                return null;
            };
            IMTextBox.prototype.SetCookie = function (sName, sValue) {
                var date = new Date(2020, 8, 20);
                if (document.cookie.IndexOf(sName) == -1) {
                    // Modified by shenyuan at 2006-01-10 for bug 4544.
                    // the all commas of sValue should be replaced by "@#GCD#@".
                    if (sValue != "") {
                        while (sValue.IndexOf(",") != -1) {
                            sValue = sValue.replace(",", "@#GCD#@");
                        }
                    }
                    document.cookie = sName + "=" + window.escape(sValue) + "; expires=" + date.toGMTString();
                    //document.cookie = sName + "=" + escape(sValue.replace(",","@#GCD#@")) + "; expires=" + date.toGMTString();
                    // Ended.
                } else {
                    var aCookie = document.cookie.split("; ");
                    var tValue = "";
                    for (var i = 0; i < aCookie.length; i++) {
                        var aCrumb = aCookie[i].split("=");
                        if (sName == aCrumb[0]) {
                            if (aCrumb[1] != null) {
                                tValue = window.unescape(aCrumb[1]);
                                break;
                            } else {
                                document.cookie = sName + "=" + window.escape(sValue.replace(",", "@#GCD#@")) + "; expires=" + date.toGMTString();
                                return;
                            }
                        }
                    }
                    if (sValue != "") {
                        while (sValue.IndexOf(",") != -1) {
                            sValue = sValue.replace(",", "@#GCD#@");
                        }
                        var existItem = tValue.split(",");
                        var hasExist = false;
                        for (var p = 0; p < existItem.length; p++) {
                            if (existItem[p] == sValue)
                                hasExist = true;
                        }
                        if (!hasExist) {
                            tValue = sValue + "," + tValue;
                            var jValue = tValue.split(",");
                            if (jValue.length > this.MaxHistoryCount) {
                                var newValue = "";
                                for (var j = 0; j < this.MaxHistoryCount; j++) {
                                    if (j != this.MaxHistoryCount - 1) {
                                        newValue += jValue[j] + ",";
                                    } else {
                                        newValue += jValue[j];
                                    }
                                }
                                tValue = newValue;
                            }
                            document.cookie = sName + "=" + window.escape(tValue) + "; expires=" + date.toGMTString();
                        }
                    }
                }
            };
            IMTextBox.prototype.DelCookie = function (sName) {
                document.cookie = sName + "=" + window.escape("") + "; expires=Fri, 31 Dec 1999 23:59:59 GMT;";
            };

            IMTextBox.prototype.DeleteItem = function (sValue) {
                while (sValue.IndexOf("&nbsp;") != -1) {
                    sValue = sValue.replace("&nbsp;", " ");
                }
                var date = new Date(2020, 8, 20);

                // Modified by shenyuan at 2005-12-16
                var cookie;
                if (this.AutoCompleteType != "None") {
                    cookie = this.GetCookie(this.AutoCompleteType);
                } else {
                    cookie = this.GetCookie(this.GetId());
                }

                // Ended.
                if (cookie != null) {
                    try  {
                        var items = cookie.split(",");
                        var saveitems = cookie.split(",");
                        if (items.length > 0) {
                            var k;
                            for (k = 0; k < items.length; k++) {
                                while (items[k].IndexOf("@#GCD#@") != -1) {
                                    items[k] = items[k].replace("@#GCD#@", ",");
                                }

                                // Ended.
                                //Modified by shenyuan at 2006-02-10 for bug #5206.
                                if (items[k].IndexOf("&") != -1) {
                                    var tempText = items[k];
                                    var tempResult = "";
                                    while (tempText.IndexOf("&") != -1) {
                                        tempText = tempText.replace("&", "&amp;");
                                        var findPosition = tempText.IndexOf("&");
                                        tempResult += tempText.Substring(0, findPosition + 5);
                                        tempText = tempText.Substring(findPosition + 5, tempText.GetLength());
                                    }
                                    if (tempText.IndexOf("&") == -1 && tempText != "") {
                                        tempResult += tempText;
                                    }
                                    items[k] = tempResult;
                                }

                                while (items[k].IndexOf("<") != -1) {
                                    items[k] = items[k].replace("<", "&lt;");
                                }
                                while (items[k].IndexOf(">") != -1) {
                                    items[k] = items[k].replace(">", "&gt;");
                                }

                                // Ended.
                                if (items[k] == sValue) {
                                    break;
                                }
                            }
                            if (k < saveitems.length && saveitems.length > 1) {
                                var j;
                                for (j = k; j < saveitems.length - 1; j++) {
                                    saveitems[j] = saveitems[j + 1];
                                }
                                saveitems[items.length - 1] = null;
                                var newValue = "";
                                for (j = 0; j < saveitems.length - 1; j++) {
                                    if (j != saveitems.length - 2) {
                                        newValue += saveitems[j] + ",";
                                    } else {
                                        newValue += saveitems[j];
                                    }
                                }

                                // Modified by shenyuan at 2005-12-16
                                if (this.AutoCompleteType != "None") {
                                    document.cookie = this.AutoCompleteType + "=" + window.escape(newValue) + "; expires=" + date.toGMTString();
                                    var dataList = this.GetItem(this.AutoCompleteType).sort();
                                    for (k = 0; k < dataList.length; k++) {
                                        while (dataList[k].IndexOf("@#GCD#@") != -1)
                                            dataList[k] = dataList[k].replace("@#GCD#@", ",");
                                    }

                                    this._autoComplete.SetDataList(dataList);
                                } else {
                                    document.cookie = this.GetId() + "=" + window.escape(newValue) + "; expires=" + date.toGMTString();

                                    var dataList = this.GetItem(this.GetId()).sort();
                                    for (k = 0; k < dataList.length; k++) {
                                        while (dataList[k].IndexOf("@#GCD#@") != -1)
                                            dataList[k] = dataList[k].replace("@#GCD#@", ",");
                                    }

                                    this._autoComplete.SetDataList(dataList);
                                }
                                // Ended.
                            } else {
                                this._autoComplete.SetDataList([]);

                                // Modified by shenyuan at 2005-12-16
                                if (this.AutoCompleteType != "None") {
                                    document.cookie = this.AutoCompleteType + "=" + window.escape("") + "; expires=Fri, 31 Dec 1999 23:59:59 GMT;";
                                } else {
                                    document.cookie = this.GetId() + "=" + window.escape("") + "; expires=Fri, 31 Dec 1999 23:59:59 GMT;";
                                }
                                // Ended.
                            }
                        }
                    } catch (e) {
                    }
                }
            };
            IMTextBox.prototype.GetItem = function (id, focusFlag) {
                if (this.IsFromServer) {
                    var cookie;
                    if (this.AutoCompleteType != "None") {
                        cookie = this.GetCookie(this.AutoCompleteType);
                    } else {
                        //cookie = this.GetCookie(id);
                    }

                    if (cookie != null) {
                        try  {
                            var values = cookie.split(",");
                            var length = (values.length > this.MaxHistoryCount ? this.MaxHistoryCount : values.length);
                            for (var i = 0; i < length; i++) {
                                while (values[i].IndexOf("@#GCD#@") != -1) {
                                    values[i] = values[i].replace("@#GCD#@", ",");
                                }
                            }

                            if (length != values.length) {
                                var items = new Array();
                                for (var j = 0; j < length; j++) {
                                    items[j] = values[j];
                                }
                                while (j < values.length) {
                                    this.DeleteItem(values[j]);
                                    j++;
                                }
                                values = items;
                            }

                            if (values.length > 0) {
                                values = this.DropDownListValidate(values);
                            }
                            return values;
                        } catch (e) {
                        }
                    }

                    return null;
                } else {
                    var values = this._historyList;
                    values = values.sort();
                    if (values != null) {
                        try  {
                            var length = (values.length > this.MaxHistoryCount ? this.MaxHistoryCount : values.length);
                            if (focusFlag !== undefined) {
                                if (focusFlag === "focus") {
                                    length = values.length;
                                }
                            }

                            if (length != values.length) {
                                var items = new Array();
                                for (var j = 0; j < length; j++) {
                                    items[j] = values[j];
                                }
                                while (j < values.length) {
                                    this.DeleteItem(values[j]);
                                    j++;
                                }
                                values = items;
                            }

                            if (values.length > 0) {
                                values = this.DropDownListValidate(values);
                            }
                            return values;
                        } catch (e) {
                        }
                    }

                    return null;
                }
            };

            IMTextBox.prototype.ResetData = function (data) {
                this.SetText(data.ResetData);
            };

            //#region IME
            //add by sj for readingImeStringOutput
            IMTextBox.prototype.ReadingImeOperation = function () {
                //add by sj for bug 2985(NKOI-97C7D114D)
                if (this.RubyText == "") {
                    return;
                }

                //end by sj
                //this.owner._trigger('readingImeStringOutput', null, { readingString: this.RubyText });
                _input.Utility.FireEvent(this, this.readingImeStringOutputEvent, { readingString: this.RubyText }, 'readingImeStringOutput');

                //add by sj for bug 2650
                this.prevval = "";

                //end by sj
                this.RubyText = "";
            };

            IMTextBox.prototype.ReadingImeKeyUpProcess = function (k, CharEx, evt) {
                //modified by sj for bug 2650
                //var newval = this.GetValue();
                var nowText = this.ImeMode ? this.InputElement.value : this._getInputValueWithPlaceHolder();
                var inputText = nowText;
                if (this.SelectionEnd < this.Text.GetLength()) {
                    var lastLength = this.Text.GetLength() - this.SelectionEnd;
                    inputText = nowText.Substring(0, nowText.GetLength() - lastLength);
                }
                var newval = inputText.Substring(this.SelectionStart, inputText.GetLength());

                //end by sj
                //var addval = newval.substring(this.prevval.length, newval.length);
                var addval = newval;
                var i;
                for (i = this.prevval.length; i >= 0; i--) {
                    if (newval.substring(0, i) == this.prevval.substring(0, i)) {
                        addval = newval.substring(i);
                        break;
                    }
                }
                this.prevval = newval;

                //modified by sj for bug 1963 and 2020
                //modified by sj for bug 2650
                //if (newval == this.Text && k != 13 && !(event.altKey))
                if (nowText == this.Text && k != 13 && !(evt.altKey)) {
                    //add by sj for bug 2650
                    this.prevval = "";

                    //end by sj
                    this.RubyText = "";
                } else if (k != 32 && k != 229 && !(k >= 112 && k <= 123) && (k != 37 && k != 39 && k != 38 && k != 40) && k != 27 && k != 28 && k != 29 && k != 8) {
                    var addruby = this.ConvertReadingIMEString(addval, CharEx);

                    if (_input.CoreUtility.IsIE()) {
                        if (this.ImeMode) {
                            //add by sj for bug 2639
                            if ((k == 192 || k == 219 || k == 221) && addval.length == 1 && addruby.length == 2) {
                                if (this.RubyText.charAt(this.RubyText.length - 1) == addruby.charAt(0)) {
                                    addruby = addruby.charAt(1);
                                }
                            }

                            //end by sj
                            this.RubyText += addruby;
                        } else {
                            this.ReadingImeOperation();
                        }
                    } else {
                        //firefox
                    }
                }
            };

            IMTextBox.prototype.IsValidReadingString = function (s) {
                if (s === undefined || s === null || s.length === 0) {
                    return false;
                }

                for (var i = 0; i < s.length; i++) {
                    if (!this.IsValidCharacter(s[i])) {
                        return false;
                    }
                }
                return true;
            };

            IMTextBox.prototype.IsValidCharacter = function (c) {
                var charEx = _input.CharProcess.CharEx;
                if (charEx.IsSpace(c)) {
                    return true;
                }
                var charType = charEx.GetCharType(c);
                var sbcsCharType = charType & ~charEx.Ctype.FullWidth;

                if (sbcsCharType == charEx.Ctype.Hiragana || sbcsCharType == charEx.Ctype.Katakana || sbcsCharType == charEx.Ctype.UpperCase || sbcsCharType == charEx.Ctype.LowerCase || sbcsCharType == charEx.Ctype.Numeric || sbcsCharType == charEx.Ctype.Symbol || sbcsCharType == charEx.Ctype.MathSymbol || sbcsCharType == charEx.Ctype.Punctuation || charEx.CharCategory._jpnMixed.indexOf(c) !== -1) {
                    return true;
                }
                return false;
            };

            IMTextBox.prototype.UpdateReadingIME = function (str) {
                this.RubyText = this.ConvertReadingIMEString(str);
                this.ReadingImeOperation();
            };

            IMTextBox.prototype.ConvertReadingIMEString = function (str, charEx) {
                if (charEx === undefined) {
                    charEx = _input.CharProcess.CharEx;
                }
                var addruby = "";
                for (var i = 0; i < str.length; i++) {
                    //modified by sj for bug 2639
                    //addruby += CharEx.ToHalfKatakana(addval.charAt(i));
                    var addvalChar = str.charAt(i);
                    var toAdd = charEx.ToHalfKatakana(addvalChar);
                    if (addvalChar == "\u309b") {
                        toAdd = "\uff9e";
                    }
                    if (addvalChar == "\u309c") {
                        toAdd = "\uff9f";
                    }

                    //add by sj for bug 2717
                    if (toAdd == "\uff65") {
                        toAdd = "";
                    }

                    //end by sj
                    addruby += toAdd;
                    //end by sj
                }
                return addruby;
            };

            IMTextBox.prototype.AddWijmoControlEvent = function () {
                var self = this;
                if (this.GetInputElement() != null) {
                    var mouseoverHandler = function (evt) {
                        _input.GlobalEventHandler.OnMouseOver(self, evt);
                    };
                    $(this.GetJQueryInputElement()[0].parentElement).on("mouseover", mouseoverHandler);
                }
            };

            IMTextBox.prototype.AddAllEventsHandler = function () {
                var self = this;
                if (this.GetInputElement() != null) {
                    var mousedownHandler = function (evt) {
                        _input.GlobalEventHandler.OnMouseDown(self, evt);
                    };
                    var mouseupHandler = function (evt) {
                        _input.GlobalEventHandler.OnMouseUp(self, evt);
                    };
                    var selectstartHandler = function (evt) {
                        _input.GlobalEventHandler.OnSelectStart(self, evt);
                    };
                    var keydownHandler = function (evt) {
                        _input.GlobalEventHandler.OnKeyDown(self, evt);
                    };
                    var keypressHandler = function (evt) {
                        _input.GlobalEventHandler.OnKeyPress(self, evt);
                    };
                    var keyupHandler = function (evt) {
                        if (($.browser.chrome || $.browser.safari) && self.ImeMode && !(self.InputElement.value === self.placeHolder && self.isNullText)) {
                            self.isNullText = false;
                        }
                        _input.GlobalEventHandler.OnKeyUp(self, evt);
                    };
                    var dblclickHandler = function (evt) {
                        _input.GlobalEventHandler.OnDblClick(self, evt);
                    };
                    var beforecopyHandler = function (evt) {
                        _input.GlobalEventHandler.OnHTML5BeforeCopy(self, evt);
                    };
                    var cutHandler = function (evt) {
                        _input.GlobalEventHandler.OnHTML5Cut(self, evt);
                    };
                    var pasteHandler = function (evt) {
                        _input.GlobalEventHandler.OnHTML5Paste(self, evt);
                    };
                    var dragstartHandler = function (evt) {
                        _input.GlobalEventHandler.OnDragStart(self, evt);
                    };
                    var dragendHandler = function (evt) {
                        _input.GlobalEventHandler.OnDragEnd(self, evt);
                    };
                    var mouseoutHandler = function (evt) {
                        _input.GlobalEventHandler.OnMouseOut(self, evt);
                    };
                    var dropHandler = function (evt) {
                        _input.GlobalEventHandler.OnDrop(self, evt);
                    };
                    var touchstartHandler = function (evt) {
                        _input.GlobalEventHandler.OnTouchStart(self, evt);
                    };
                    var touchendHandler = function (evt) {
                        _input.GlobalEventHandler.OnTouchEnd(self, evt);
                    };
                    var selectHandler = function (evt) {
                        _input.GlobalEventHandler.OnSelect(self, evt);
                    };

                    // Frank Liu fixed bug 662 at 2013/07/10.
                    //safari
                    if (_input.CoreUtility.safari) {
                        var safari_dragenterHandler = function (evt) {
                            self._safariDropText = getSelection().toString();
                        };
                        var safari_dragleaveHandler = function (evt) {
                            self._safariDropText = null;
                        };
                        this.GetJQueryInputElement().on({
                            'dragenter.imtextbox': safari_dragenterHandler,
                            'dragleave.imtextbox': safari_dragleaveHandler
                        });
                    }
                    var dragenterHandler = function (evt) {
                        _input.GlobalEventHandler.OnDragEnter(self, evt);
                    };
                    var dragleaveHandler = function (evt) {
                        _input.GlobalEventHandler.OnDragLeave(self, evt);
                    };

                    //// HelenLiu 2013/06/13 fix bug 657 in IM HTML5.
                    ////IE9的问题在于：
                    ////1. 按键BackSpace / 按键Delete / 拖拽 / 剪切 / 删除，不会触发propertychange和input事件
                    //// 2. addEventListener绑定的propertychange事件任何情况都不会触发，但attachEvent绑定的propertychange事件则在除问题1之外的情况下能够触发。
                    ////3. 基于问题2的原因，使用jQuery绑定的propertychange事件在IE9下永远不会触发，因为它是调用addEventListener来绑定的
                    if (_input.CoreUtility.IsIE7OrLater() && (!_input.CoreUtility.IsIE11OrLater())) {
                        var onpropertychangeHandler = function (evt) {
                            _input.GlobalEventHandler.OnPropertyChanged(self, evt);
                        };
                        this.GetJQueryInputElement().on({
                            'onpropertychange.imtextbox': onpropertychangeHandler
                        });
                    } else {
                        var propertychangeHandler = function (evt) {
                            _input.GlobalEventHandler.OnPropertyChanged(self, evt);
                        };
                        this.GetJQueryInputElement().on({
                            'propertychange.imtextbox': propertychangeHandler
                        });
                    }
                    var compositionstartHandler = function (evt) {
                        _input.GlobalEventHandler.OnCompositionStart(self, evt);
                    };
                    var compositionupdateHandler = function (evt) {
                        _input.GlobalEventHandler.OnCompositionUpdate(self, evt);
                    };
                    var compositionendHandler = function (evt) {
                        _input.GlobalEventHandler.OnCompositionEnd(self, evt);
                    };
                    if (_input.CoreUtility.IsIE10OrLater()) {
                        var MSPointerUpHandler = function (evt) {
                            _input.GlobalEventHandler.OnMSPointerUp(self, evt);
                        };
                        var MSPointerDownHandler = function (evt) {
                            _input.GlobalEventHandler.OnMSPointerDown(self, evt);
                        };
                        var MSGestureTapHandler = function (evt) {
                            _input.GlobalEventHandler.OnMSGestureTap(self, evt);
                        };

                        this.GetJQueryInputElement().on({
                            'MSPointerUp.imtextbox': MSPointerUpHandler,
                            'MSPointerDown.imtextbox': MSPointerDownHandler,
                            'MSGestureTap.imtextbox': MSGestureTapHandler
                        });
                    }

                    var blurHandler = function (evt) {
                        _input.GlobalEventHandler.OnEditFieldLoseFocus(self, evt);
                    };
                    var focusoutHandler = function (evt) {
                        _input.GlobalEventHandler.OnFocusOut(self, evt);
                    };
                    var focusHandler = function (evt) {
                        _input.GlobalEventHandler.OnEditFieldFocus(self, evt);
                    };
                    var activateHandler = function (evt) {
                        _input.GlobalEventHandler.OnActivate(self, evt);
                    };
                    var deactivateHandler = function (evt) {
                        _input.GlobalEventHandler.OnDeActivate(self, evt);
                    };
                    if (_input.CoreUtility.IsPad()) {
                        var inputHandler = function (evt) {
                            _input.GlobalEventHandler.OnInput(self, evt);
                        };
                        this.GetJQueryInputElement().on({
                            'input.imtextbox': inputHandler
                        });
                    }

                    if (_input.CoreUtility.IsAndroid()) {
                        var textinputHandler = function (evt) {
                            _input.GlobalEventHandler.OnTextInput(self, evt);
                        };
                        this.GetJQueryInputElement().on({
                            'textInput.imtextbox': textinputHandler
                        });
                    }

                    this.GetJQueryInputElement().on({
                        'mousedown.imtextbox': mousedownHandler,
                        'mouseup.imtextbox': mouseupHandler,
                        'selectstart.imtextbox': selectstartHandler,
                        'keydown.imtextbox': keydownHandler,
                        'keypress.imtextbox': keypressHandler,
                        'keyup.imtextbox': keyupHandler,
                        'dblclick.imtextbox': dblclickHandler,
                        'beforecopy.imtextbox': beforecopyHandler,
                        'cut.imtextbox': cutHandler,
                        'paste.imtextbox': pasteHandler,
                        'dragstart.imtextbox': dragstartHandler,
                        'dragend.imtextbox': dragendHandler,
                        'mouseout.imtextbox': mouseoutHandler,
                        'drop.imtextbox': dropHandler,
                        'touchstart.imtextbox': touchstartHandler,
                        'touchend.imtextbox': touchendHandler,
                        'select.imtextbox': selectHandler,
                        'dragenter.imtextbox': dragenterHandler,
                        'dragleave.imtextbox': dragleaveHandler,
                        'compositionstart.imtextbox': compositionstartHandler,
                        'compositionupdate.imtextbox': compositionupdateHandler,
                        'compositionend.imtextbox': compositionendHandler,
                        'blur.imtextbox': blurHandler,
                        'focusout.imtextbox': focusoutHandler,
                        'focus.imtextbox': focusHandler,
                        'activate.imtextbox': activateHandler,
                        'deactivate.imtextbox': deactivateHandler
                    });

                    this.AddWijmoControlEvent();
                }
            };

            IMTextBox.prototype.Input = function (evt) {
                try  {
                    this.ImeInput("DirectInput");
                } finally {
                    this.ImeMode = false;
                }
            };

            // process the input text in textinput for android device.
            // the keycode is always 229 for chrome for mobile(the bug link: https://bugs.chromium.org/p/chromium/issues/detail?id=118639)
            // so we use the textinput event to process the input text for this problem.
            IMTextBox.prototype.TextInput = function (evt) {
                this.UIProcess.keypressResponse = true;
                var inputText = evt.originalEvent.data;
                this.InnerKeyPress(inputText);
            };

            IMTextBox.prototype.KeyDown = function (evt) {
                var _this = this;
                var k = evt.keyCode;
                var funcKeysPressed = new Object();
                funcKeysPressed.Shift = false;
                funcKeysPressed.Ctrl = false;
                funcKeysPressed.Alt = false;

                if (evt.shiftKey) {
                    funcKeysPressed.Shift = true;
                }
                if (evt.ctrlKey) {
                    funcKeysPressed.Ctrl = true;
                }
                if (evt.altKey) {
                    funcKeysPressed.Alt = true;
                }

                this.LastInputText = this.GetText();
                this.isFuncKeyPressed = false;

                if ((!this.PasswordMode) && (!this.MultiLine) && (this.EnableAutoComplete)) {
                    var retAC = this._autoComplete.KeyDown(evt);
                    if (retAC != null && retAC == false) {
                        return;
                    }
                }
                ;
                this.KeyDownAction = true;

                //Add for contextmenu shortcut
                //var ret;
                //if (this.ContextMenu.IsShow()) {
                //    // Added HotKeys by shenyuan at 2005-12-27
                //    // Up, Down, Enter, U(Undo), T(Cut), C(Copy), P(Paste), D(Delete), A(SelectAll)
                //    if (k == 38 || k == 40 || k == 13 || k == 85 || k == 84 || k == 67 || k == 80 || k == 68 || k == 65) {
                //        this.ContextMenu.KeyDown(evt);
                //    }
                //    if (k == 27 || k == 18) {
                //        this.ContextMenu.Close();
                //    }
                //    // Add comments by Yang at 9:37 Sep. 3th 2007
                //    // For event.keyCode is readonly in firefox.
                //    // BTW, i think the following codes is wrong in ie. It should be deleted.
                //    //if (k == 38 || k == 40 || k == 33 || k == 34)//For bug 3914
                //    if (Utility.IsIE() && (k == 38 || k == 40 || k == 33 || k == 34)) {
                //        ret = new Object();
                //        ret.KeyCode = 37;
                //        return ret;
                //    }
                //    // End by Yang
                //    return false;
                //}
                //bug#5599
                //this.ImeMode = false;
                if ((k == 229 && !this.IsJapanConvertKeyPress) || (k == 13 && this.GetText() != this.Text)) {
                    this.ImeMode = true;
                    return true;
                } else {
                    if (this.ImeMode) {
                        // Add comments by Yang at 10:40 May 14 2007
                        // For fix bug 7963
                        //var _conditions = funcKeysPressed.Shift || funcKeysPressed.Alt || funcKeysPressed.Ctrl || (k == 20) || ((k >= 112) && (k <= 123));
                        var _conditions = funcKeysPressed.Shift || funcKeysPressed.Ctrl || (k == 20) || ((k >= 112) && (k <= 123));

                        // End by Yang
                        //add by sj for bug 1430
                        _conditions = _conditions || (k == 8 && !_input.CoreUtility.IsIE());

                        //end by sj
                        if (!_conditions) {
                            // Add comments by Yang at 14:41 May 29 2007
                            // For fix bug 8230
                            this.ImeInput("ReInput", true, evt);

                            //this.ImeInput("DirectInput");
                            // End by Yang
                            this.ImeSelectTimes = 0;
                            this.ImeMode = false;
                        }
                    }
                    if (k == 229 && this.IsJapanConvertKeyPress) {
                        this.IsJapanConvertKeyPress = false;
                    }
                }

                var retInfo = new Object();
                if (funcKeysPressed.Shift) {
                    k |= 65536;
                }

                if (funcKeysPressed.Ctrl) {
                    k |= 131072;
                }

                if (funcKeysPressed.Alt && k === 40) {
                    var keyAction = "DropDown";
                }

                if (funcKeysPressed.Alt) {
                    k |= 262144;
                }

                // Modified by shenyuan at 2006-01-04 for bug 4756.
                // The priority sequence in multiline mode will be AcceptReturn &gt shortcut &gt post back.
                //if (!(k == 13) || (!this.MultiLine) || (!this.AcceptReturn)) {
                //    var keyAction = this.UIProcess.GetKeyActionName(k, this.Shortcuts);
                //}
                // Add by Jiang at Oct. 28 2008
                // for fixed bug10160
                var isBlockByShortcut = false;
                var i;
                if (this.KeyActionList != null) {
                    for (i = 0; i < this.KeyActionList.length; i++) {
                        if (this.KeyActionList[i] == k.toString()) {
                            isBlockByShortcut = true;
                            break;
                        }
                    }
                }

                // end by Jiang
                // Add for DropDown Edit
                if ((keyAction == "DropDown") || (k == 262182 || k == 262184) && !isBlockByShortcut) {
                    return false;
                }

                // end by yangyang
                if ((95 < k) && (k < 106)) {
                    k = k - 48;
                }

                var selectionstart = this.SelectionStart;
                var selectionend = this.SelectionEnd;
                var text = this.GetText();
                var bufftext = this.BuffText;
                var lasttext = this.LastText;
                var lastselectionstart = this.LastSelectionStart;
                var lastselectionend = this.LastSelectionEnd;

                if (!this.MultiLine) {
                    selectionstart = this.DropDownEditData.SelectionStart;
                    selectionend = this.DropDownEditData.SelectionEnd;
                    text = this.DropDownEditData.Text;
                    bufftext = this.DropDownEditData.BuffText;
                    lasttext = this.DropDownEditData.LastText;
                    lastselectionstart = this.DropDownEditData.LastSelectionStart;
                    lastselectionend = this.DropDownEditData.LastSelectionEnd;
                }

                retInfo = this.UIProcess.TextBoxKeyDown(k, funcKeysPressed, this._getEditModeInternal(), this.Overwrite, selectionstart, selectionend, this.ReadOnly, this.MaxLength, this.LengthAsByte, this.MaxLineCount, this.CountWrappedLine, this.ExitOnLastChar, this.ExitOnLeftRightKey, this.MultiLine, this.PasswordMode, text, this.AcceptTab, this.AcceptReturn, bufftext, lasttext, lastselectionstart, lastselectionend, keyAction, evt);

                if (retInfo == null) {
                    return false;
                }

                if (retInfo.inputChar != null) {
                    return true;
                }

                if (retInfo.InputTab == true) {
                    //bug#5528
                    this.Text = this.GetText();

                    // Add comments by Yang at 8:32 Sep. 10th 2007
                    // For now the keypress function is the event handler.
                    // We should use the internal method innerkeypress.
                    //this.KeyPress("\t");
                    this.InnerKeyPress("\t");
                    // End by Yang
                }

                // Modified by shenyuan at 2006-01-13 for new undo rules
                if (retInfo.DelInclude) {
                    // Added by shenyuan at 2006-02-27 for reopened bug #5385.
                    this.IsUndoAfterDel = true;

                    if (!retInfo.SerialDel) {
                        this.BuffText = this.GetText();
                        this.LastSelectionStart = this.BuffText.GetLength();
                        this.LastSelectionEnd = this.BuffText.GetLength();
                        if (!this.MultiLine) {
                            this.DropDownEditData.BuffText = this.DropDownEditData.Text;
                            this.DropDownEditData.LastSelectionStart = this.DropDownEditData.BuffText.GetLength();
                            this.DropDownEditData.LastSelectionEnd = this.DropDownEditData.BuffText.GetLength();
                        }
                    }
                }

                if (retInfo.Text != null) {
                    if (retInfo.Undo == true) {
                        this.LastText = this.Text;

                        // Modified by shenyuan at 2006-01-13 for new undo rules
                        this.BuffText = this.LastText;
                        if (!this.MultiLine) {
                            this.DropDownEditData.LastText = this.DropDownEditData.Text;
                            this.DropDownEditData.BuffText = this.DropDownEditData.LastText;
                        }
                    }

                    // Add comments by Yang at 14:56 January 30th 2008
                    // For fix the bug 9623
                    //this.InternalSetText(retInfo.Text, true);
                    this.DirectSetText(retInfo.Text);
                    if (!this.MultiLine) {
                        this.DropDownEditData.Text = retInfo.Text;
                    }
                    // End by Yang
                }

                // add by Sean Huang at 2009.01.06, for bug 1454 -->
                var oldLength = this.GetSelectionLength();

                // end of Sean Huang <--
                if (retInfo.SelectionStart != null) {
                    if (retInfo.Undo == true) {
                        this.isFuncKeyPressed = true;
                        this.LastSelectionStart = this.SelectionStart;
                        if (!this.MultiLine) {
                            this.DropDownEditData.LastSelectionStart = this.DropDownEditData.SelectionStart;
                        }
                    }
                    this.SelectionStart = retInfo.SelectionStart;
                    if (!this.MultiLine) {
                        this.DropDownEditData.SelectionStart = this.SelectionStart;
                        this.SelectionStart = this.GetSingleCurPosition(this.DropDownEditData.Text, retInfo.SelectionStart);
                    }
                }

                if (retInfo.SelectionEnd != null) {
                    if (retInfo.Undo == true) {
                        this.LastSelectionEnd = this.SelectionEnd;
                        if (!this.MultiLine) {
                            this.DropDownEditData.LastSelectionEnd = this.DropDownEditData.SelectionEnd;
                        }
                    }
                    this.SelectionEnd = retInfo.SelectionEnd;
                    if (!this.MultiLine) {
                        this.DropDownEditData.SelectionEnd = this.SelectionEnd;
                        this.SelectionEnd = this.GetSingleCurPosition(this.DropDownEditData.Text, retInfo.SelectionEnd);
                    }
                }

                // add by Sean Huang at 2009.01.06, for bug 1454 -->
                var newLength = this.GetSelectionLength();

                // end of Sean Huang <--
                if (retInfo.KeyCode != null) {
                    var ret = new Object();
                    ret.KeyCode = retInfo.KeyCode;
                    return ret;
                }

                if (retInfo.FocusType != null) {
                    this.FocusType = retInfo.FocusType;
                }

                if (retInfo.Overwrite != null) {
                    if (this.GetOverwrite() != retInfo.Overwrite) {
                        if (this._getEditModeInternal() == 0 /* Insert */) {
                            this._setEditModeInternal(1 /* Overwrite */);
                        } else if (this._getEditModeInternal() == 1 /* Overwrite */) {
                            this._setEditModeInternal(0 /* Insert */);
                        }
                    }
                    // Frank Liu fixed bug 1029 at 2013/07/10.
                    //this.Overwrite = retInfo.Overwrite;
                }

                if (retInfo.EventInfo != null) {
                    for (i = 0; i < retInfo.EventInfo.length; i++) {
                        if (retInfo.EventInfo[i] != null) {
                            // change by Sean Huang at 2008.10.30, for bug 9908 -->
                            ////Add comments by Ryan Wu at 11:30 Apr. 5 2007.
                            ////For support Aspnet Ajax 1.0.
                            ////this.UIProcess.FireEvent(this, retInfo.EventInfo[i].Name, retInfo.EventInfo[i].Args);
                            //this.UIProcess.FireEvent(this, retInfo.EventInfo[i].Name, retInfo.EventInfo[i].Args, retInfo.EventInfo[i].Type);
                            ////end by Ryan Wu.
                            if (retInfo.EventInfo[i].Type == "KeyExit") {
                                this.EventInfo = retInfo.EventInfo[i];
                            } else {
                                //Add comments by Ryan Wu at 11:30 Apr. 5 2007.
                                //For support Aspnet Ajax 1.0.
                                //this.UIProcess.FireEvent(this, retInfo.EventInfo[i].Name, retInfo.EventInfo[i].Args);
                                this.UIProcess.FireEvent(this, retInfo.EventInfo[i].Name, retInfo.EventInfo[i].Args, retInfo.EventInfo[i].Type);
                                //end by Ryan Wu.
                            }
                            // end of Sean Huang <--
                        }
                    }
                }

                if (retInfo.System != null) {
                    setTimeout(function () {
                        if (retInfo.System && _this.InputElement.value === "") {
                            _this.Clear();
                        }
                    }, 0);

                    return retInfo.System;
                } else {
                    if (retInfo.SetSelection == true) {
                        if (oldLength == 0 && newLength != 0) {
                            _input.Utility.ShouldFireOnSelectStart = true;
                        } else {
                            _input.Utility.ShouldFireOnSelectStart = false;
                        }
                        this.SetSelection(this.SelectionStart, this.SelectionEnd);

                        _input.Utility.ShouldFireOnSelectStart = false;
                    }
                    return false;
                }
            };

            IMTextBox.prototype.KeyPress = function (text, evt, NoUpdateDisplay) {
                var inputText = text;

                if (!_input.CoreUtility.IsIE() && this.ImeMode) {
                    var _conditions = (evt.keyCode == 192) && evt.altKey;
                    if (_conditions) {
                        this.ImeInput("ReInput", true, evt);
                        this.ImeSelectTimes = 0;
                        this.ImeMode = false;
                        return;
                    }
                }
                if (!_input.CoreUtility.IsIE() && evt.charCode == 0) {
                    // Add comments by Yang at 16:08 Sep. 12th 2007
                    // For fix the bug 8805
                    //if (!event.ctrlKey || event.which != 13)
                    var keycode = evt.keyCode || evt.charCode;
                    if (keycode = 13 && (!this.MultiLine || (!this.AcceptReturn && this.MultiLine && !evt.ctrlKey))) {
                        return true;
                    }
                }
                return this.InnerKeyPress(inputText, NoUpdateDisplay);
            };

            IMTextBox.prototype.KeyUp = function (evt) {
                if (!this.PasswordMode && !this.MultiLine && this.EnableAutoComplete) {
                    // Add comments by Owen Xu at 11:49 June 20 2007
                    // For fix the bug 8519
                    // 8519 Bug Reason:
                    // If Edit1 have not added a history in history list, __AutoComplete["Edit1"] will not exist.
                    // So code "__AutoComplete[this.ID]['isVisible']" will cause an exception and the following key process will never be executed.
                    // Solution:
                    // Add judgement code:
                    // if (__AutoComplete[this.ID] != null)
                    // {
                    // }
                    //to check if __AutoComplete["Edit1"] exists.  If it doesn't exist, it is not necessary to execute the code of historylist(AutoComplete).
                    // Thus the following key process will be executed anyway, no matter __AutoComplete["Edit1"] exists or not.
                    if ((evt.keyCode == 8 || evt.keyCode == 46 || evt.keyCode == 9) && this.GetText() == "") {
                        if (!this._autoComplete.GetIsDeleteItem()) {
                            this._autoComplete.HideDropdown();
                        }
                        //moved by sj
                        //isDeleteItem = false;
                        //end by sj
                    } else if (this.isFuncKeyPressed) {
                        this._autoComplete.HideDropdown();
                    } else {
                        if (this.LastInputText != this.GetText() && this.GetText() != "") {
                            this._autoComplete.KeyUp(evt);
                        }
                    }

                    //moved by sj
                    this._autoComplete.SetIsDeleteItem(false);
                    //end by sj
                }

                // End by Owen Xu
                this.KeyDownAction = false;

                var k = evt.keyCode;
                var CharEx = _input.CharProcess.CharEx;

                //modified by sj for bug 869
                //only occur when using hand writing
                if (k == 13 && this._getInputValueWithPlaceHolder() != this.Text) {
                    if (_input.CoreUtility.IsIE() && this.ImeMode) {
                        this.HasValidatedImeInput = false;
                    } else if (!_input.CoreUtility.IsIE()) {
                        this.ImeMode = true;
                    }
                }

                //end by sj
                if (this.ImeMode == true) {
                    //// if input from ime mode, close the context menu.
                    //if (this.ContextMenu.IsShow()) {
                    //    this.ContextMenu.Close();
                    //}
                    //var k = event.keyCode;
                    //var CharEx = new CharProcess();
                    var nowText = this._getInputValueWithPlaceHolder();
                    var inputText = nowText;
                    if (this.SelectionEnd < this.Text.GetLength()) {
                        var lastLength = this.Text.GetLength() - this.SelectionEnd;
                        inputText = nowText.Substring(0, nowText.GetLength() - lastLength);
                    }

                    inputText = inputText.Substring(inputText.GetLength() - 1, inputText.GetLength());
                    if (k == 13) {
                        this.ImeInput("DirectInput", undefined, evt);
                        this.ImeSelectTimes = 0;
                        //this.OrientText = "";
                    } else if ((k >= 48 && k <= 57) || (k >= 96 && k <= 105)) {
                        if (k >= 96) {
                            k = k - 48;
                        }

                        inputText = CharEx.ToHalfWidth(inputText);

                        if (inputText != String.fromCharCode(k) && !this.ImeSelect) {
                            this.HasValidatedImeInput = false;
                        } else if (inputText == String.fromCharCode(k) && this.ImeSelectTimes < 1) {
                            // Add comments by Yang at 16:59 Sep. 25th 2007
                            // For fix bug 8715
                            this.HasValidatedImeInput = false;
                            // End by Yang
                        } else if (this.ImeSelect) {
                        } else {
                            this.ImeInput("ReInput", undefined, evt);

                            // Add comments by Yang at 16:59 Sep. 25th 2007
                            // For fix bug 8715
                            this.HasValidatedImeInput = false;

                            // End by Yang
                            this.ImeMode = true;
                        }
                        this.ImeSelectTimes = 0;
                    } else if (k == 32) {
                        if (this.ImeSelect == false) {
                            if (this.ImeSelectTimes == 1) {
                                this.ImeSelect = true;
                            } else {
                                //For bug 3442
                                if (CharEx.ToHalfWidth(inputText) != String.fromCharCode(k)) {
                                    this.ImeSelectTimes++;
                                } else {
                                    //add by sj for bug NKOI-2CFFC8879
                                    if (this.HasValidatedImeInput) {
                                        //end by sj
                                        this.UIProcess.inputJap = true;

                                        // Add comments by Yang at 14:10 October 24th 2007
                                        // For fix the bug from Japan.
                                        // We can not input space in Edit when IME mode is on.
                                        if (_input.CoreUtility.IsIE()) {
                                            this.HasValidatedImeInput = false;
                                        }

                                        // End by Yang
                                        // Add for bug 6677
                                        this.ImeInput("DirectInput", undefined, evt);
                                        this.ImeSelectTimes = 0;
                                        // end
                                        //add by sj for bug NKOI-2CFFC8879
                                    }
                                    //end by sj
                                }
                            }
                        }
                        //this.OrientText = this.ImeInput("Record");
                    } else if (k >= 65 && k <= 90) {
                        this.ImeSelectTimes = 0;

                        // Add comments by Yang at 16:59 Sep. 25th 2007
                        // For fix bug 8715
                        this.HasValidatedImeInput = false;
                        // End by Yang
                    } else if (k == 32 || k == 106 || k == 107 || k == 109 || (k == 173 && _input.CoreUtility.IsFireFox4OrLater()) || k == 110 || k == 111 || k == 219 || k == 220 || k == 221 || k == 222 || (k >= 186 && k <= 192) || k == 226) {
                        if (this.ImeSelectTimes >= 1) {
                            this.ImeInput("ReInput", undefined, evt);
                        }
                        this.ImeSelectTimes = 0;

                        // Add comments by Yang at 17:07 Sep. 25th 2007
                        // For fix bug 8715
                        if (_input.CoreUtility.IsIE()) {
                            this.HasValidatedImeInput = false;
                        }
                        // End by Yang
                    } else if (k == 40 || k == 38) {
                        if (this.ImeSelect == false) {
                            if (this.ImeSelectTimes == 1) {
                                this.ImeSelect = true;
                            }
                        }
                    } else if (k == 8 || k == 46) {
                        this.ImeSelectTimes = 0;
                    } else if (k == 27) {
                        this.ImeSelectTimes = 0;
                    } else if (k == 244) {
                        this.IsJapanConvertKeyPress = true;
                    } else if (!_input.CoreUtility.IsIE() && k == 243) {
                        this.ImeInput("ReInput", true, evt);
                        this.ImeSelectTimes = 0;
                        this.ImeMode = false;
                    } else if (_input.CoreUtility.IsIE() && k == 229) {
                        this.HasValidatedImeInput = false;
                    } else {
                    }
                }

                //return false;
                //2012/08/17, Robin, Hotfix Bug#33.(IME mode is changed by Caps lock key, the text is cleared.)
                // shift+CapsLock on US Keyboard or CapsLocak on JP Keyboard, a key up 242 will fired
                if (k == 242) {
                    this.ImeInput("ReInput", true, evt);
                }

                //End Hotfix Bug#33
                //add by sj for readingimestringoutput
                this.ReadingImeKeyUpProcess(k, CharEx, evt);

                //end by sj
                if (this.UIProcess.keyupResponse == true) {
                    this.UIProcess.keyupResponse = false;
                    var retInfo = this.UIProcess.TextBoxKeyUp(this.InputElement, this.MultiLine, this.SelectionStart, this.SelectionEnd, this.GetText());
                    var oldstart = this.SelectionStart;
                    var oldend = this.SelectionEnd;
                    var isStartChanged = false;
                    var isEndChanged = false;
                    if (!this.MultiLine) {
                        oldstart = this.DropDownEditData.SelectionStart;
                        oldend = this.DropDownEditData.SelectionEnd;
                    }
                    if (retInfo.SelectionStart != null) {
                        if (this.SelectionStart != retInfo.SelectionStart) {
                            isStartChanged = true;
                            this.SelectionStart = retInfo.SelectionStart;
                            if (!this.MultiLine) {
                                this.DropDownEditData.SelectionStart = this.GetMultiPosition(this.DropDownEditData.Text, this.SelectionStart);
                            }
                        }
                    }

                    if (retInfo.SelectionEnd != null) {
                        if (this.SelectionEnd != retInfo.SelectionEnd) {
                            this.SelectionEnd = retInfo.SelectionEnd;
                            this.SelectionLength = Math.abs(this.SelectionEnd - this.SelectionStart);
                            isEndChanged = true;
                            if (!this.MultiLine) {
                                this.DropDownEditData.SelectionEnd = this.GetMultiPosition(this.DropDownEditData.Text, this.SelectionEnd);
                            }
                        }
                    }

                    var onText = this._getInputValueWithPlaceHolder();
                    var temp = this.MultiLine ? this.Text : this.GetSingleText(this.Text);
                    var count = temp.GetLength() - onText.GetLength();
                    var temptext;
                    if (!this.MultiLine) {
                        if (count != 0) {
                            temptext = this.DropDownEditData.Text;
                            if (isStartChanged && isEndChanged) {
                                this.DropDownEditData.Text = temptext.Substring(0, this.DropDownEditData.SelectionStart) + temptext.Substring(oldend, temptext.GetLength());
                            } else if (!isStartChanged) {
                                oldend = this.GetMultiPosition(temptext, this.SelectionStart + count);
                                this.DropDownEditData.Text = temptext.Substring(0, oldstart) + temptext.Substring(oldend, temptext.GetLength());
                            }
                        }
                        temp = this.GetSingleText(this.DropDownEditData.Text);
                    } else if (this.PasswordMode) {
                        if (count != 0) {
                            temptext = this.Text;
                            if (isStartChanged && isEndChanged) {
                                temp = temptext.Substring(0, this.SelectionStart) + temptext.Substring(oldend, temptext.GetLength());
                            } else if (!isStartChanged) {
                                oldend = this.SelectionStart + count;
                                temp = temptext.Substring(0, oldstart) + temptext.Substring(oldend, temptext.GetLength());
                            }
                        }
                    } else {
                        temp = this.GetText();
                    }

                    if (retInfo.SystemEdit == true) {
                        //		        this.Text = this.GetText();
                        //				this.UIUpdate.SetHideText(this.GetText() + ":true");
                        this.Text = temp;

                        // Add comments by Yang at 14:35 August 7th 2007
                        // For improve the performance for v2h1
                        this.SetHideText(temp);
                        //this.UIUpdate.SetHideText(temp + ":true");
                        // End by Yang
                    }

                    if (retInfo.Text != null) {
                        this.InternalSetText(retInfo.Text, true);
                    }

                    if (retInfo.SetSelection == true) {
                        this.SetSelection(this.SelectionStart, this.SelectionEnd);
                    }
                }
                //this.KeyboardAction = false;
            };

            IMTextBox.prototype.PropertyChange = function (evt) {
                if (evt != null && _input.CoreUtility.IsIE10OrLater()) {
                    if (evt.propertyName == "value") {
                        //this.UpdateFishEyeButtonStatus();
                        //if (this.AddressObj != null) {
                        //    this.AddressObj.SearchByAutocomplete(this.ID, this.GetText());
                        //}
                    }
                }
                if (this.DragEdit) {
                    this.DragEdit = false;

                    if (!this.MultiLine) {
                        if (this.Text != this.GetText()) {
                            this.DropDownEditData.OldText = this.DropDownEditData.Text;
                            this.DropDownEditData.Text = this.DropDownEditData.Text.Substring(0, this.DropDownEditData.SelectionStart) + this.DropDownEditData.Text.Substring(this.DropDownEditData.SelectionEnd, this.DropDownEditData.Text.GetLength());
                            this.DropDownEditData.LastText = this.DropDownEditData.OldText;
                            this.DropDownEditData.SelectionEnd = this.DropDownEditData.SelectionStart;
                        }
                    }
                    this.OldText = this.Text;
                    this.Text = this.GetText();

                    // Add comments by Yang at 14:35 August 7th 2007
                    // For improve the performance for v2h1
                    this.SetHideText(this.GetText());

                    //this.UIUpdate.SetHideText(this.GetText() + ":true");
                    // End by Yang
                    this.SystemChange = true;
                    this.LastText = this.OldText;
                    this.SetSelectionLength(0);
                } else if (this.DropEdit) {
                    this.DropEdit = false;
                    this.FocusType = 11 /* DragDrop */; //For bug 4245
                    this.SelectionStart = _input.Utility.GetSelectionStartPosition(this.InputElement);

                    this.SelectionEnd = this.SelectionStart + _input.Utility.GetSelectionText(this.InputElement).GetLength();

                    var nowText = this._getInputValueWithPlaceHolder();
                    if (!this.MultiLine) {
                        var insertText;

                        var oldText = this.GetSingleText(this.DropDownEditData.Text);
                        var insertTextLength = nowText.GetLength() - oldText.GetLength();

                        //			    if (this.PasswordMode && !this.UseSystemPasswordChar)
                        if (this.PasswordMode) {
                            insertText = this.DropText;
                        } else {
                            insertText = nowText.Substring(this.SelectionEnd - insertTextLength, this.SelectionEnd);
                        }

                        if (insertTextLength != 0) {
                            this.DropDownEditData.OldText = this.DropDownEditData.Text;
                            this.DropDownEditData.SelectionStart = this.GetMultiPosition(this.DropDownEditData.Text, this.SelectionEnd - insertTextLength);
                            this.DropDownEditData.Text = this.DropDownEditData.Text.Substring(0, this.DropDownEditData.SelectionStart) + insertText + this.DropDownEditData.Text.Substring(this.DropDownEditData.SelectionStart, this.DropDownEditData.Text.GetLength());
                            this.DropDownEditData.LastText = this.DropDownEditData.OldText;
                            this.DropDownEditData.SelectionEnd = this.DropDownEditData.SelectionStart + insertTextLength;
                        }

                        //			    if (this.PasswordMode && !this.UseSystemPasswordChar)
                        if (this.PasswordMode) {
                            nowText = this.GetSingleText(this.DropDownEditData.Text);
                        }
                    } else if (this.PasswordMode) {
                        var start = this.SelectionEnd - this.DropText.GetLength();
                        nowText = this.Text.Substring(0, start) + this.DropText + this.Text.Substring(start, this.Text.GetLength());
                    }
                    this.OldText = this.Text; //Added for Bug 3636
                    this.Text = nowText;

                    // Add comments by Yang at 14:35 August 7th 2007
                    // For improve the performance for v2h1
                    this.SetHideText(nowText);

                    //this.UIUpdate.SetHideText(nowText + ":true");
                    // End by Yang
                    this.SystemChange = true;
                    this.LastText = this.OldText;
                } else {
                    //			if(!this.MultiLine && !this.isTextEllipsis && (!this.PasswordMode || this.UseSystemPasswordChar))
                    if (!this.MultiLine && !this.isTextEllipsis && !this.PasswordMode) {
                        // Add comments by Yang at 14:35 August 7th 2007
                        // For improve the performance for v2h1
                        this.SetHideText(this.GetText());
                        //this.UIUpdate.SetHideText(this.GetText() + ":true");
                        // End by Yang
                    }
                }
                return false;
            };

            IMTextBox.prototype.MouseDown = function (evt) {
                this._isInnerKeyPressCall = false;
                var mouseButton = _input.Utility.GetMouseButton(evt);
                this.FocusedWhenMouseDown = document.activeElement == evt.target;
                this.MouseDownOnClearButton = _input.CoreUtility.IsMouseDownOnClearButton(evt);

                // Add comments by Yang at 13:47 Aug. 28th 2007
                // For Firefox doesn't support document.activeElement
                if (!_input.CoreUtility.IsIE()) {
                    this.IsActive = true;

                    // Add comments by Yang at 12:28 Sep. 15th 2007
                    // For fix the bug 8843
                    //modified by sj for bug 2408, 2409, 2977 Japan(NKOI-566BC9866)
                    //this.DropDownObj.IsDropDownRaisePostBack = false;
                    //if (this.DropDownObj) {
                    //    this.DropDownObj.IsDropDownRaisePostBack = false;
                    //}
                    //end by sj
                    // End by Yang
                    // Add comments by Yang at 15:58 Sep. 24th 2007
                    // For fix bug 8794 comment #2
                    if (this.ImeMode && mouseButton == 0 /* Left */) {
                        this.IsImplementImeInput = true;
                    }
                    // End by Yang
                }

                // End by Yang
                this.MouseButton = mouseButton;
                this.BeforeDragSelectionStart = this.SelectionStart;
                this.BeforeDragSelectionEnd = this.SelectionEnd;

                if (this.MouseButton == 2 /* Right */) {
                    // change by Sean Huang at 2009.02.09, for bug 1791 -->
                    //this.FocusType = FocusType.Click;
                    if (this.FocusType != 3 /* ClientEvent */) {
                        this.FocusType = 1 /* Click */;
                    }
                    // end of Sean Huang <--
                    // Add comments by Yang at 16:03 Sep.14th 2007
                    // For fix bug 8675
                    //if (this.ContextMenu.IsShow()) {
                    //    this.ContextMenu.Close();
                    //}
                    // End by Yang
                } else {
                    this.isLeftMouseButtonPressed = true;

                    // change by Sean Huang at 2009.02.09, for bug 1791 -->
                    //this.FocusType = FocusType.Click;
                    if (this.FocusType != 3 /* ClientEvent */) {
                        this.FocusType = 1 /* Click */;
                    }

                    try  {
                        // Add comments by Yang at 10:46 Aug.15th 2007
                        // For firefox doesn't support document.selection and its' methods.
                        //Terry jQuery Control
                        //var RealID = this.ID + Utility.EditFieldSuffix;
                        //if (this.IsjQueryControl == true) {
                        //    RealID = this.ID;
                        //}
                        var stext = _input.Utility.GetSelectionText(this.InputElement);
                        if (stext != "") {
                            this.IsMouseDown = true;

                            // Add comments by Yang at 9:51 Aug. 15th 2007
                            // For support the selection emtpy in Firefox.
                            _input.Utility.ClearSelection(this.InputElement);
                            //document.selection.empty();
                            // End by Yang
                        }
                    } catch (e) {
                    }
                }

                var retInfo = this.UIProcess.TextBoxMouseDown(this.InputElement, mouseButton);

                //this.UIProcess.isDblClick = false;
                if (retInfo == null) {
                    return;
                }

                if (retInfo.SelectionStart != null) {
                    this.SelectionStart = retInfo.SelectionStart;
                }

                if (retInfo.SelectionEnd != null) {
                    this.SelectionEnd = retInfo.SelectionEnd;
                }
            };

            IMTextBox.prototype.MouseUp = function (evt) {
                var funcKeysPressed = null;

                // Add comments by Yang at 13:48 Aug. 28th 2007
                // For Firefox doesn't support document.activeElement
                //if (!Utility.IsIE()) {
                //delete by sj for bug 870 & 1159 on ttp
                //this.IsActive = true;
                //end by sj
                // Add comments by Yang at 12:28 Sep. 15th 2007
                // For fix the bug 8843
                //this.DropDownObj.IsDropDownRaisePostBack = false;
                // End by Yang
                // }
                // End by Yang
                //add by sj for readingImeStringOutput
                if (_input.CoreUtility.IsIE() && this.ImeMode) {
                    this.ReadingImeOperation();
                }

                //end by sj
                this.IsMouseDown = false;
                if (_input.CoreUtility.IsIE() && (this.ImeMode || _input.CoreUtility.CompareTextWithUnifiedNewline(this.Text, this.GetText()))) {
                    if (this.ImeMode) {
                        this.ImeInput("ClickInput", undefined, evt);
                        this.ImeSelectTimes = 0;
                    } else {
                        this.InternalSetText(this.Text, true);
                    }
                } else if (!_input.CoreUtility.IsIE() && (this.ImeMode || this.GetDisPlayText(this.Text) != this._getInputValueWithPlaceHolder())) {
                    // Add comments by Yang at 15:58 Sep. 24th 2007
                    // For fix bug 8794 comment #2
                    if (!this.IsImplementImeInput) {
                        return;
                    }

                    // End by Yang
                    this.ImeInput("ClickInput", undefined, evt);
                    this.ImeSelectTimes = 0;

                    // Add comments by Yang at 9:42 Aug. 29th 2007
                    // For Firefox doesn't support set a value in onblur event when IME opens.
                    // Add comments by Yang at 11:07 October 12th 2007
                    // For fix the bug 9017
                    //if (this.Text != this.GetText())
                    if (this.GetDisPlayText(this.Text) != this._getInputValueWithPlaceHolder()) {
                        // Add comments by Yang at 15:58 Sep. 24th 2007
                        // For fix bug 8794 comment #2
                        this.IsImplementImeInput = false;

                        // End by Yang
                        var tempText = this.Text;
                        if (!this.MultiLine) {
                            tempText = tempText.replace(/\r\n/g, "");
                            tempText = tempText.replace(/\r/g, "");
                            tempText = tempText.replace(/\n/g, "");
                        } else {
                            tempText = tempText.replace(/\r/g, "\\r");
                            tempText = tempText.replace(/\n/g, "\\n");
                        }

                        //window.setTimeout("FindIMControl('" + this.ID + "').InternalSetText('" + tempText + "', true)", 0);
                        var self = this;
                        window.setTimeout(function () {
                            self.InternalSetText(tempText, true);
                        }, 0);

                        // Add comments by Yang at 19:03 October 11th 2007
                        // For fix the bug 9008
                        this.Select();
                        // End by Yang
                    }
                    // End by Yang
                } else {
                    this.isLeftMouseButtonPressed = false;

                    //this.EnableOnSelectStartEvent = false;
                    this.LastStart = this.SelectionStart;
                    this.LastEnd = this.SelectionEnd;
                    var start = this.SelectionStart;
                    var end = this.SelectionEnd;
                    var text = this.GetText();

                    //			if (!this.MultiLine)
                    //			{
                    //			    this.DropDownEditData.LastStart = this.DropDownEditData.SelectionStart;
                    //			    this.DropDownEditData.LastEnd   = this.DropDownEditData.SelectionEnd;
                    //			    start = this.DropDownEditData.SelectionStart;
                    //			    end = this.DropDownEditData.SelectionEnd;
                    //			    text = this.DropDownEditData.Text;
                    //			}
                    // Add comments by Yang at 16:18 Sep. 13th 2007
                    // For sometimes the parameter funcKeysPressed is null,
                    // then an exception would be thrown.
                    // fix bug 8847
                    var isCtrlPress = null;
                    if (funcKeysPressed != null && funcKeysPressed.Ctrl != null) {
                        isCtrlPress = funcKeysPressed.Ctrl;
                    }

                    // End by Yang
                    var retInfo = this.UIProcess.TextBoxMouseUp(this.InputElement, start, end, this.MouseButton, this.MultiLine, text, isCtrlPress, this.HighlightText, evt);

                    if (retInfo == null) {
                        return;
                    }

                    if (retInfo.SelectionStart != null) {
                        this.SelectionStart = retInfo.SelectionStart;
                        if (!this.MultiLine) {
                            this.DropDownEditData.SelectionStart = this.GetMultiPosition(this.DropDownEditData.Text, this.SelectionStart);
                        }
                    }

                    if (retInfo.SelectionEnd != null) {
                        this.SelectionEnd = retInfo.SelectionEnd;
                        this.SelectionLength = Math.abs(this.SelectionEnd - this.SelectionStart);
                        if (!this.MultiLine) {
                            this.DropDownEditData.SelectionEnd = this.GetMultiPosition(this.DropDownEditData.Text, this.SelectionEnd);
                        }
                    }

                    if (retInfo.SetSelection == true) {
                        this.SetSelection(this.SelectionStart, this.SelectionEnd);
                    }
                }

                this.MouseButton = 0 /* Left */;

                if (this.MouseUpPointerType == undefined) {
                    // DaryLuo 2012/11/19 fix bug 899 in IM Web 7.0.
                    this.MouseUpHasValue = evt.target.value.length > 0;
                }
                this.HandleClearButton(evt);
            };

            IMTextBox.prototype.MouseWheel = function (evt) {
            };

            IMTextBox.prototype.ShouldCancelMouseWheelDefaultBehavior = function () {
                return false;
            };

            IMTextBox.prototype.MouseOut = function () {
                if (this.IsMouseDown != true) {
                    return;
                }

                // DaryLuo 2012/12/04 fix bug 927 in IM Web 7.0.
                if (this.MouseUpPointerType !== 4 && this.MouseUpPointerType != undefined && this.MouseUpPointerType !== "mouse") {
                    // DaryLuo 2012/10/31 fix bug 785 in IM Web 7.0.
                    return;
                }

                var start = Math.min(this.BeforeDragSelectionStart, this.BeforeDragSelectionEnd);
                var end = Math.max(this.BeforeDragSelectionStart, this.BeforeDragSelectionEnd);
                var data = this.GetText().Substring(start, end);

                if (data != "") {
                    this.SetSelection(this.BeforeDragSelectionStart, this.BeforeDragSelectionEnd);
                    _input.Utility.DragDrop(this.InputElement);
                }

                this.IsMouseDown = false;
            };

            IMTextBox.prototype.DoubleClick = function () {
                if (!this.PasswordMode && !this.MultiLine && this.EnableAutoComplete && !this.ReadOnly) {
                    this._autoComplete.ShowDropdown();
                }
                var retInfo = this.UIProcess.TextBoxDoubleClick(this.InputElement, this.SelectionStart, this.GetText());

                if (retInfo.SelectionStart != null) {
                    this.SelectionStart = retInfo.SelectionStart;
                    if (!this.MultiLine) {
                        this.DropDownEditData.SelectionStart = this.GetMultiPosition(this.DropDownEditData.Text, this.SelectionStart);
                    }
                }

                if (retInfo.SelectionEnd != null) {
                    this.SelectionEnd = retInfo.SelectionEnd;
                    if (!this.MultiLine) {
                        this.DropDownEditData.SelectionEnd = this.GetMultiPosition(this.DropDownEditData.Text, this.SelectionEnd);
                    }
                    this.SelectionLength = Math.abs(this.SelectionEnd - this.SelectionStart);
                }

                if (retInfo.SetSelection == true) {
                    this.SetSelection(this.SelectionStart, this.SelectionEnd);
                }
                return true;
            };

            IMTextBox.prototype.DragStart = function (evt) {
                if (this.PasswordMode) {
                    evt.dataTransfer.effectAllowed = "none";
                } else {
                    this.DragEdit = true;
                }
            };

            IMTextBox.prototype.DragEnd = function () {
                this.DragEdit = true;
            };

            // Add comments by Yang at 10:23 May 18 2007
            // For fix bug 7870
            IMTextBox.prototype.DragEnter = function () {
                if (this.isTextEllipsis) {
                    this.InternalDirectSetText(this.GetText());
                }
            };

            IMTextBox.prototype.DragLeave = function () {
                this.DealEllipsis(this.MultiLine, this.Ellipsis, this.EllipsisString, this.InputElement);
            };

            // Add for OverFlowTip
            IMTextBox.prototype.MouseMove = function (evt) {
            };

            IMTextBox.prototype.MouseOver = function () {
                var shouldShowOverFlowTip = !(this.HasFocus || this.MultiLine || !this.OverflowTip || $(this.InputElement).hasClass(this.disabledClassName));
                if (shouldShowOverFlowTip) {
                    var obj = this.InputElement;
                    var text = this.GetText();
                    if (this.isTextEllipsis) {
                        text = this.Text;
                    }
                    if (this.PasswordMode) {
                        var temptext = "";
                        for (var i = 0; i < text.GetLength(); i++) {
                            temptext += this.PasswordChar;
                        }
                        text = temptext;
                    }
                    var scrollwidth = _input.CoreUtility.MeasureText(text, obj).Width;

                    if (scrollwidth > obj.clientWidth) {
                        this.ToolTip = $(this.InputElement.parentElement).wijtooltip({
                            content: text,
                            position: { my: "left bottom", at: "left+1 top" }
                        });
                        $(this.InputElement.parentElement).wijtooltip("show");
                    } else {
                        shouldShowOverFlowTip = false;
                    }
                }
                if (!shouldShowOverFlowTip) {
                    this._destoryOverflowTip();
                }
            };

            IMTextBox.prototype._destoryOverflowTip = function () {
                if (this.ToolTip != null) {
                    this.ToolTip = null;
                    $(this.InputElement.parentElement).wijtooltip("destroy");
                }
            };

            IMTextBox.prototype._isinsertGroup = function (editMode) {
                return editMode == 0 /* Insert */ || editMode == 2 /* FixedInsert */;
            };

            IMTextBox.prototype._isOverwriteGroup = function (editMode) {
                return editMode == 1 /* Overwrite */ || editMode == 3 /* FixedOverwrite */;
            };

            IMTextBox.prototype.InnerKeyPress = function (text, NoUpdateDisplay, isLoseFocusInput) {
                var inputChar = text;
                var oldtext;
                if (this.ImeMode || this.isPasting) {
                    oldtext = this.Text;
                } else {
                    oldtext = this._getInputValueWithPlaceHolder();
                    if (oldtext != "") {
                        oldtext = this.GetText();
                    }
                }
                this.isPasting = false;
                var selectionstart = this.SelectionStart;
                var selectionend = this.SelectionEnd;
                if (!this.MultiLine) {
                    selectionstart = this.DropDownEditData.SelectionStart;
                    selectionend = this.DropDownEditData.SelectionEnd;
                    //Helen
                    //oldtext = this.DropDownEditData.Text;
                }

                var retInfo = this.UIProcess.TextBoxKeyPress(selectionstart, selectionend, inputChar, oldtext, this.MaxLength, this.LengthAsByte, this.ExitOnLastChar, this.Overwrite, this.MultiLine, this.MaxLineCount, this.CountWrappedLine);

                if (retInfo.Text != null) {
                    if (retInfo.DelInclude) {
                        this.BuffText = this.GetText();
                        if (!this.MultiLine) {
                            this.DropDownEditData.BuffText = this.DropDownEditData.Text;
                        }
                    }
                    this.DirectSetText(retInfo.Text, NoUpdateDisplay);
                    if (!this.MultiLine) {
                        this.DropDownEditData.Text = retInfo.Text;
                    }
                }

                if (retInfo.SelectionStart != null) {
                    this.SelectionStart = retInfo.SelectionStart;
                    if (!this.MultiLine) {
                        this.DropDownEditData.SelectionStart = this.SelectionStart;
                        this.SelectionStart = this.GetSingleCurPosition(retInfo.Text, retInfo.SelectionStart);
                    }
                }

                if (retInfo.SelectionEnd != null) {
                    this.SelectionEnd = retInfo.SelectionEnd;
                    if (!this.MultiLine) {
                        this.DropDownEditData.SelectionEnd = this.SelectionEnd;
                        this.SelectionEnd = this.GetSingleCurPosition(retInfo.Text, retInfo.SelectionEnd);
                    }
                }

                if (retInfo.SetSelection == true && !NoUpdateDisplay && !isLoseFocusInput) {
                    this._isInnerKeyPressCall = true;
                    this.SetSelection(this.SelectionStart, this.SelectionEnd);
                }

                if (retInfo.EventInfo != null) {
                    for (var i = 0; i < retInfo.EventInfo.length; i++) {
                        if (retInfo.EventInfo[i] != null) {
                            //Add comments by Ryan Wu at 11:30 Apr. 5 2007.
                            //For support Aspnet Ajax 1.0.
                            //this.UIProcess.FireEvent(this, retInfo.EventInfo[i].Name, retInfo.EventInfo[i].Args);
                            this.UIProcess.FireEvent(this, retInfo.EventInfo[i].Name, retInfo.EventInfo[i].Args, retInfo.EventInfo[i].Type);
                            //end by Ryan Wu.
                        }
                    }
                }

                if (retInfo.SystemEdit == true) {
                    return true;
                } else {
                    return false;
                }
            };

            IMTextBox.prototype._isSupportClipBoard = function () {
                if (!this.GetUseClipboard()) {
                    return true;
                }

                if (_input.CoreUtility.IsIE()) {
                    return true;
                }

                if (_input.CoreUtility.IsFireFox4OrLater()) {
                    try  {
                        netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
                        var clip = Components.classes['@mozilla.org/widget/clipboard;1'].createInstance(Components.interfaces.nsIClipboard);

                        if (!clip) {
                            return;
                        }

                        var trans = Components.classes['@mozilla.org/widget/transferable;1'].createInstance(Components.interfaces.nsITransferable);

                        if (!trans) {
                            return;
                        }

                        trans.addDataFlavor('text/unicode');
                        clip.getData(trans, clip.kGlobalClipboard);

                        var str = new Object();
                        var len = new Object();

                        try  {
                            trans.getTransferData('text/unicode', str, len);
                        } catch (error) {
                            return null;
                        }

                        if (str) {
                            if (Components.interfaces.nsISupportsWString) {
                                str = str.value.QueryInterface(Components.interfaces.nsISupportsWString);
                            } else if (Components.interfaces.nsISupportsString) {
                                str = str.value.QueryInterface(Components.interfaces.nsISupportsString);
                            } else {
                                str = null;
                            }
                        }
                        if (str) {
                            return (str.data.substring(0, len.value / 2));
                        }
                    } catch (e) {
                        return false;
                    }
                }

                return false;
            };

            IMTextBox.prototype.MSPointerUp = function (evt) {
                if (evt != null) {
                    this.MouseUpPointerType = evt.pointerType;
                    this.MouseUpHasValue = (evt.srcElement || evt.target).value.length > 0;
                }
            };

            IMTextBox.prototype.CompositionStart = function (evt) {
                this.ImeMode = true;

                this._lastCompositionText = "";
                this._lastCompositionOffset = 0;
                this._convertedOnLastUpdate = false;
                this._cachedReadingString = "";
                this._readingString = "";
                this._compositionUpdateFired = false;
                this._compositionStarted = true;
                this._compositionEndFired = false;
            };

            IMTextBox.prototype.CompositionUpdate = function (evt) {
                this._compositionUpdateFired = true;
                if (evt.originalEvent.data === undefined || evt.originalEvent.data.length === 0) {
                    return;
                }

                var compositionOffset = this.InputElement.selectionStart - evt.originalEvent.data.length;
                if (compositionOffset > this._lastCompositionOffset) {
                    if (!this._convertedOnLastUpdate) {
                        var newText = this._lastCompositionText.substring(0, compositionOffset - this._lastCompositionOffset);
                        if (!this.IsValidReadingString(newText)) {
                            this._cachedReadingString += this._readingString;
                        } else {
                            this._cachedReadingString += newText;
                        }
                        this._readingString = "";
                        this._convertedOnLastUpdate = true;
                    }
                } else {
                    if (this._convertedOnLastUpdate) {
                        this._convertedOnLastUpdate = false;
                    }
                }
                if (!this.IsValidReadingString(evt.originalEvent.data)) {
                    return;
                }
                this._readingString = evt.originalEvent.data;
            };

            IMTextBox.prototype.CompositionEnd = function (evt) {
                //// This means that User is input by IME, but the input source is not keyboard, may be touch keyboard.
                //if (Utility.GetClientOS() === "Android"||Utility.IPadAndIPhone) {
                //    return;
                //}
                var imeInput = this.HasValidatedImeInput;
                this.ImeMode = true;
                this.HasValidatedImeInput = false;

                var self = this;
                var iMeHandler = function () {
                    try  {
                        self.ImeInput("DirectInput", undefined, evt);
                    } finally {
                        self.ImeMode = false;
                    }
                };

                var chromeIMEHandler = function () {
                    try  {
                        if (self._compositionStarted) {
                            return;
                        }
                        self.ImeMode = true;
                        self.ImeInput("DirectInput", undefined, evt);
                    } finally {
                        self.ImeMode = false;
                    }
                };

                this._compositionStarted = false;
                this._compositionEndFired = true;

                if (_input.CoreUtility.IsIE9OrLater()) {
                    iMeHandler();
                } else {
                    // DaryLuo 2013/05/15 fix bug 382 in IM HTML5.
                    setTimeout(chromeIMEHandler, 0);
                }

                if (!this._compositionUpdateFired) {
                    this.CompositionUpdate(evt);
                }

                this._convertedOnLastUpdate = false;
                var resultString = this._cachedReadingString + this._readingString;
                this._cachedReadingString = "";
                this._readingString = "";
                if (evt.originalEvent.data.length === 0 || resultString.length === 0) {
                    return;
                }
                this.UpdateReadingIME(resultString);

                // HelenLiu 2013/06/28 fix bug 792 in IM HTML5.
                // HelenLiu 2013/07/01 fix bug 818 in IM HTML5.
                if ((_input.CoreUtility.IPadAndIPhone && _input.CoreUtility.safari) || (_input.CoreUtility.chrome && _input.CoreUtility.IsAndroid())) {
                    this.HasValidatedImeInput = imeInput;
                    this.ImeMode = false;
                }
            };

            //#endregion
            //#region Handle events and actions
            IMTextBox.prototype.SelectStart = function (selText) {
                if (this.ImeMode) {
                    return false;
                }
                if (this.isLeftMouseButtonPressed) {
                    var retInfo = this.UIProcess.SelectStart(this.InputElement, selText, this.MultiLine);

                    if (retInfo.SelectionStart != null) {
                        this.SelectionStart = retInfo.SelectionStart;
                        if (!this.MultiLine) {
                            this.DropDownEditData.SelectionStart = this.GetMultiPosition(this.DropDownEditData.Text, retInfo.SelectionStart);
                        }
                    }

                    if (retInfo.SelectionEnd != null) {
                        this.SelectionEnd = retInfo.SelectionEnd;
                        if (!this.MultiLine) {
                            this.DropDownEditData.SelectionEnd = this.GetMultiPosition(this.DropDownEditData.Text, retInfo.SelectionEnd);
                        }
                    }
                }
            };

            IMTextBox.prototype.DragDrop = function (dragText) {
                // add by Sean Huang at 2008.11.06, for bug 10298 -->
                if (!_input.CoreUtility.IsIE() && this.ReadOnly) {
                    return false;
                }

                // end of Sean Huang <--
                // Add comments by Yang at 15:26 August 28th 2007
                // For the parameter "dragText" should be tranfered from the function
                // which called this function
                //dragText = event.dataTransfer.getData('Text');
                // End by a
                //add by sj for support firefox drop
                this.FFDragFlag = false;
                if (!_input.CoreUtility.IsIE()) {
                    this.FFDragFlag = true;
                }

                //end by sj
                // HelenLiu 2013/07/19 fix bug 1058 in IM HTML5.
                if (!_input.CoreUtility.IsIE() && !_input.CoreUtility.safari) {
                    this.SetInnerFocus();
                }

                var dragSelectionStart = _input.Utility.GetSelectionStartPosition(this.InputElement);
                var dragSelectionEnd = dragSelectionStart;

                var retInfo = this.UIProcess.DragDrop(dragText, this.ExitOnLastChar, dragSelectionStart, dragSelectionEnd, this.MaxLength, this.LengthAsByte, this.MaxLineCount, this.CountWrappedLine, this.MultiLine, this.GetText());

                //end by sj
                if (retInfo == null) {
                    return;
                }

                if (retInfo.DropText != null) {
                    //			if ((!this.UseSystemPasswordChar && this.PasswordMode) || (this.MultiLine && this.UseSystemPasswordChar))
                    var previousText;
                    var realText;
                    if (this.PasswordMode) {
                        var passwordText = this.UIProcess.GetPasswordText(retInfo.DropText, this.PasswordChar, this.MultiLine);
                        if (_input.CoreUtility.IsIE()) {
                            window.event.dataTransfer.setData('Text', passwordText);
                            if (passwordText != window.event.dataTransfer.getData('Text')) {
                                previousText = this.GetText();
                                realText = previousText + retInfo.DropText;
                                this.InternalSetText(realText, true);
                                _input.Utility.PreventDefault(window.event);
                            }
                        } else {
                            previousText = this.GetText();
                            realText = previousText + retInfo.DropText;
                            this.InternalSetText(realText, true, true);
                        }
                        this.DropText = retInfo.DropText;
                    } else {
                        if (_input.CoreUtility.IsIE()) {
                            event.dataTransfer.setData('Text', retInfo.DropText);
                            if (retInfo.DropText != event.dataTransfer.getData('Text')) {
                                previousText = this.GetText();
                                realText = previousText + retInfo.DropText;
                                this.InternalSetText(realText, true);
                                _input.Utility.PreventDefault(event);
                            } else {
                                // DaryLuo 2012/10/30 fix bug 845 in IM Web 7.0.
                                var thisObj = this;
                                setTimeout(function () {
                                    var realText = thisObj.GetText();
                                    thisObj.InternalSetText(realText, true);
                                }, 0);
                            }
                        } else {
                            previousText = this.GetText();
                            realText = previousText + retInfo.DropText;
                            this.InternalSetText(realText, true, true);
                        }
                    }

                    this.DropEdit = true;
                }

                if (retInfo.EventInfo != null) {
                    for (var i = 0; i < retInfo.EventInfo.length; i++) {
                        //modified by sj for bug 1683
                        //if (retInfo.EventInfo[i] != null)
                        if (retInfo.EventInfo[i] != null && retInfo.EventInfo[i].Name != null) {
                            //Add comments by Ryan Wu at 10:42 Apr. 5 2007.
                            //For support Aspnet Ajax 1.0.
                            //this.UIProcess.FireEvent(this, retInfo.EventInfo[i].Name, retInfo.EventInfo[i].Args);
                            this.UIProcess.FireEvent(this, retInfo.EventInfo[i].Name, retInfo.EventInfo[i].Args, retInfo.EventInfo[i].Type);

                            //end by Ryan Wu.
                            if (retInfo.EventInfo[i].Name == this.KeyExitEvent) {
                                this.FocusExit = true;
                            }
                        }
                    }
                }

                //add by sj
                this.FFDragFlag = false;

                //end by sj
                var self = this;
                var m = this.MultiLine;
                var e = this.Ellipsis;
                var es = this.EllipsisString;
                var inputElement = this.InputElement;
                setTimeout(function () {
                    // HelenLiu 2013/07/19 fix bug 1059 in IM HTML5.
                    self.InternalSetText(self.GetText());
                    self.DealEllipsis(m, e, es, inputElement);
                }, 0);
                return true;
            };

            IMTextBox.prototype.MSGestureTap = function (evt) {
                if (this.Focused) {
                    if (!this.PasswordMode && !this.MultiLine && this.EnableAutoComplete && !this.ReadOnly) {
                        var self = this;
                        setTimeout(function () {
                            if (self.Focused) {
                                self._autoComplete.ShowDropdown();
                            }
                        }, 400);
                    }
                }
            };

            IMTextBox.prototype.MSPointerDown = function (evt) {
                if (this.Focused && (evt.pointerType === evt.MSPOINTER_TYPE_TOUCH || evt.pointerType === "touch")) {
                    if (!this.PasswordMode && !this.MultiLine && this.EnableAutoComplete && !this.ReadOnly) {
                        var myGesture = new MSGesture();
                        myGesture.target = evt.target;
                        myGesture.addPointer(evt.pointerId);
                    }
                }
            };

            IMTextBox.prototype.GetShowLiterals = function () {
                return 1 /* Always */;
            };
            return IMTextBox;
        })();
        _input.IMTextBox = IMTextBox;

        /** @ignore */
        var GcTextBoxUIProcess = (function (_super) {
            __extends(GcTextBoxUIProcess, _super);
            function GcTextBoxUIProcess(autoConvert, format, /*elementID,*/ passwordMode, passwordChar, isjQueryControl, owner) {
                //Initial the base class Field
                _super.call(this);
                this.isMulSelected = false;
                this.isOverWrite = false;
                this.ForwardSelection = "None";
                this.isCtrlPress = false;
                this.isCtrlClick = false;
                this.isDblClick = false;
                this.isTriClick = false;
                this.isInputValid = true;
                this.ctrlDelete = false;
                this.ctrlBackspace = false;
                this.IsDelInclude = false;
                this.IsSerialDel = false;
                this.StartPos = null;
                this.LastKey = null;
                this.keypressResponse = false;
                this.systemEdit = false;
                this.keyupResponse = false;
                this.japInput = false;
                this.inputJap = false;
                this.IsKeyDown = false;
                this.CurStart = 0;
                this.CurEnd = 0;
                this.control = owner;
                this.Owner = owner; // to compatibilize with BaseUIProcess.

                //Properties
                //this.ClientEvents = clientEvents;
                //this.InvalidInputEvent = owner.InvalidInputEvent;
                //this.EditStatusChangedEvent = owner.EditStatusChangedEvent;
                //this.KeyExitEvent = owner.KeyExitEvent;
                //this.TextChangedEvent = owner.TextChangedEvent;
                //this.DropDownCloseEvent = owner.DropDownCloseEvent;
                //this.DropDownOpenEvent = owner.DropDownOpenEvent;
                this.Filter = new _input.TextFilter(autoConvert, format);
                this.IsjQueryControl = isjQueryControl;

                this.PasswordMode = passwordMode;
                this.PasswordChar = passwordChar;
                //if (elementID != null) {
                //    this.ElementID = elementID;
                //    if (isjQueryControl) {
                //        this.RealEditID = elementID;
                //    }
                //    else {
                //        this.RealEditID = elementID + "_EditField";
                //    }
                //}
            }
            GcTextBoxUIProcess.prototype.Reset = function () {
                this.Filter = new _input.TextFilter(this.control.AutoConvert, this.control.Format);
                this.PasswordMode = this.control.PasswordMode;
                this.PasswordChar = this.control.GetPasswordChar();
            };

            GcTextBoxUIProcess.prototype.TextBoxKeyDown = function (k, funcKeysPressed, editMode, overwrite, start, end, readOnly, maxLength, lengthAsByte, maxLine, isCountWrappedLine, exitOnLastChar, exitOnLeftRightKey, multiLine, passwordMode, text, acceptTab, acceptReturn, buffText, undoText, oldStart, oldEnd, keyAction, evt) {
                if (funcKeysPressed.Ctrl) {
                    this.isCtrlPress = true;
                } else {
                    this.isCtrlPress = false;
                }

                var retInfo = new Object();

                switch (editMode) {
                    case 0 /* Insert */:
                        this.isOverWrite = false;
                        break;
                    case 1 /* Overwrite */:
                        this.isOverWrite = true;
                        break;
                    case 2 /* FixedInsert */:
                        this.isOverWrite = false;
                        break;
                    case 3 /* FixedOverwrite */:
                        this.isOverWrite = true;
                        break;
                }

                if (start != end) {
                    this.isMulSelected = true;
                } else {
                    this.isMulSelected = false;
                }

                //ShortCuts
                var ret;
                switch (keyAction) {
                    case "Clear":
                        if (!readOnly) {
                            retInfo.SelectionStart = 0;
                            retInfo.SelectionEnd = 0;
                            retInfo.Text = "";

                            //fix bug#4940, KevinHuang, 2006-04-30
                            retInfo.DelInclude = true;
                            this.IsDelInclude = true;
                        }
                        return retInfo;

                    case "NextControl":
                        ret = this.MoveControl(this.control.InputElement, true, false, "NextControl"); //01-20

                        // Modified by shenyuan at 2006-01-20.
                        if (ret != null) {
                            retInfo.EventInfo = new Array();
                            retInfo.EventInfo[0] = ret.EventInfo;
                            retInfo.FocusType = ret.FocusType;
                            retInfo.FocusExit = true;
                        }
                        return retInfo;

                    case "PreviousControl":
                        ret = this.MoveControl(this.control.InputElement, false, false, "PreviousControl"); //01-20

                        // Modified by shenyuan at 2006-01-20.
                        if (ret != null) {
                            retInfo.EventInfo = new Array();
                            retInfo.EventInfo[0] = ret.EventInfo;
                            retInfo.FocusType = ret.FocusType;
                            retInfo.FocusExit = true;
                        }
                        return retInfo;
                }

                //The ReadOnly property is set to true
                if (readOnly) {
                    //we only let the Ctrl+C and Ctrl+Insert and ShortCut and Tab and Shift+ Tab
                    //work when we set readOnly property to true.
                    if (k != 131117 && k != 131139 && k != 9 && k != 65545 && k != 131081 && k != 196617 && k != 131137 && k != 37 && k != 39 && k != 38 && k != 40) {
                        return retInfo;
                    }
                }
                var isPressContinuousely;
                switch (k) {
                    case 131138:
                    case 131140:
                    case 131141:
                    case 131144:
                    case 131145:
                    case 131148:
                    case 131150:
                    case 131154:
                    case 131159:
                    case 131188:
                    case 262181:
                    case 262183:
                    case 117:
                    case 65657:
                    case 116:
                    case 121:
                    case 123:
                        retInfo.System = true;
                        break;

                    case 45:
                        var isOverWrite;
                        if (editMode === 2 /* FixedInsert */) {
                            isOverWrite = false;
                        } else if (editMode === 3 /* FixedOverwrite */) {
                            isOverWrite = true;
                        } else {
                            isOverWrite = !overwrite;
                            if (this.EditStatusChangedEvent != "" && this.EditStatusChangedEvent != null) {
                                var eventInfo = new Object();
                                eventInfo.Name = this.EditStatusChangedEvent;
                                eventInfo.Args = null;

                                //Add comments by Ryan Wu at 10:47 Apr. 5 2007.
                                //For support Aspnet Ajax 1.0.
                                eventInfo.Type = "EditStatusChanged";

                                //end by Ryan Wu.
                                retInfo.EventInfo = new Array();
                                retInfo.EventInfo[0] = eventInfo;
                            }
                        }
                        retInfo.Overwrite = isOverWrite;
                        break;

                    case 13:
                        if (multiLine && acceptReturn) {
                            this.keypressResponse = true;
                            this.keyupResponse = true;
                            retInfo.System = true;
                        } else if (multiLine && !acceptReturn) {
                            //cause postback
                            //retInfo.isSetCookies = true;
                            //					__doPostBack("","");
                            //Add comments by Yang at 8:40 June 1st 2007
                            //For fix bug 8331
                            //FindIMControl(this.ElementID).SetLastClientValues();
                            // End by Yang
                            // TODO:DOPostBack when do the wrapper.
                            retInfo.System = false;
                            retInfo.IsDoPostBack = true;
                        } else {
                            //retInfo.isSetCookies = true;
                            this.keypressResponse = true;
                            this.keyupResponse = false;
                            retInfo.System = true;
                            //Add comments by Yang at 8:40 June 1st 2007
                            //For fix bug 8331
                            //FindIMControl(this.ElementID).SetLastClientValues();
                            // End by Yang
                        }
                        break;

                    case 131085:
                        if (multiLine) {
                            this.systemEdit = true;
                            this.keypressResponse = true;
                            this.keyupResponse = true;
                            retInfo.System = true;
                        }
                        break;

                    case 9:

                    case 65545:
                        if (multiLine && acceptTab && !readOnly) {
                            this.keypressResponse = true;
                            retInfo.InputTab = true;
                        } else {
                            retInfo.System = true;
                            ret = new Object();

                            if (this.Owner.KeyExitEvent != "" && this.Owner.KeyExitEvent != null) {
                                ret.Name = this.Owner.KeyExitEvent;
                                ret.Args = { Key: (k == 9 ? 1 /* Tab */ : 2 /* ShiftTab */) };

                                //Add comments by Ryan Wu at 10:47 Apr. 5 2007.
                                //For support Aspnet Ajax 1.0.
                                ret.Type = "KeyExit";
                                //end by Ryan Wu.
                            }
                            retInfo.EventInfo = new Array();
                            retInfo.EventInfo[0] = ret;

                            // Modified by shenyuan at 2006-01-16 for bug 4969.
                            // Caret should move to the end of the text when move
                            // the focus to edit by tab key.
                            if (multiLine) {
                                retInfo.SelectionStart = text.GetLength();
                                retInfo.SelectionEnd = text.GetLength();
                            }
                        }
                        break;

                    case 131081:
                        // Add comments by Yang at 9:24 March 6th 2008
                        // For fix the bug 9711
                        //var ret = this.MoveControl(this.RealEditID, true, false, "Right");//01-20
                        ret = this.MoveControl(this.control.InputElement, true, false, "NextControl"); // End by Yang

                        // Modified by shenyuan at 2006-01-20.
                        if (ret != null) {
                            retInfo.EventInfo = new Array();
                            retInfo.EventInfo[0] = ret.EventInfo;
                            retInfo.FocusType = ret.FocusType;
                            retInfo.FocusExit = true;
                        }
                        break;

                    case 196617:
                        // Modofied by shenyuan at 2006-02-28 for bug #5410.
                        ret = this.MoveControl(this.control.InputElement, false, false, "PreviousControl"); // Modified by shenyuan at 2006-01-20.
                        if (ret != null) {
                            retInfo.EventInfo = new Array();
                            retInfo.EventInfo[0] = ret.EventInfo;
                            retInfo.FocusType = ret.FocusType;
                            retInfo.FocusExit = true;
                        }
                        break;

                    case 8:

                    case 65544:
                        this.systemEdit = true;
                        this.keyupResponse = true;

                        // Modified by shenyuan at 2006-01-20 for new undo rules.
                        this.DelOperation(k, start, end);

                        //				retInfo.DelStart = start - 1;
                        //				retInfo.DelEnd   = end - 1;
                        // Ended.
                        retInfo.DelInclude = true;
                        retInfo.SerialDel = this.IsSerialDel;
                        retInfo.System = true;
                        break;

                    case 46:
                        this.systemEdit = true;
                        this.keyupResponse = true;

                        // Modified by shenyuan at 2006-01-13 for new undo rules.
                        this.DelOperation(k, start, end);

                        retInfo.DelInclude = true;
                        retInfo.SerialDel = this.IsSerialDel;
                        retInfo.System = true;
                        break;

                    case 131080:
                    case 196616:
                        // Modified by shenyuan at 2005-12-28 for bug 4629
                        // when there is no selected text, do it by system defualt.
                        if (!this.isMulSelected) {
                            this.systemEdit = true;
                            this.keyupResponse = true;
                            retInfo.System = true;
                        } else {
                            this.keyupResponse = true;

                            //modified by sj for bug 3133
                            /*
                            retInfo.System = true;
                            retInfo.KeyCode = 39;
                            this.ctrlDelete = true;
                            */
                            this.ctrlBackspace = true;
                            //end by sj
                        }

                        // Modified by shenyuan at 2006-01-13 for new undo rules
                        this.DelOperation(k, start, end); //01-23
                        retInfo.SerialDel = this.IsSerialDel;
                        retInfo.DelInclude = true;
                        break;

                    case 131118:
                        this.keyupResponse = true;
                        retInfo.System = true;

                        // Modified by shenyuan at 2006-01-13 for new undo rules
                        this.DelOperation(k, start, end); //01-23
                        retInfo.SerialDel = this.IsSerialDel;
                        retInfo.DelInclude = true;
                        retInfo.KeyCode = 39;
                        this.ctrlDelete = true;
                        break;

                    case 131139:

                    case 131117:
                        //In password input status,copy shoud disable
                        //				if(multiLine || !passwordMode)
                        if (!passwordMode) {
                            var owner;
                            if (this.Owner === undefined) {
                                owner = this.control;
                            } else {
                                owner = this.Owner;
                            }
                            if (owner._isSupportClipBoard()) {
                                this.Copy(text, start, end);
                                //retInfo.System = false;
                            } else {
                                retInfo.System = true;
                            }
                        } else {
                            retInfo.System = false;
                        }
                        break;

                    case 65581:

                    case 131158:
                        if (this.Owner === undefined) {
                            owner = this.control;
                        } else {
                            owner = this.Owner;
                        }
                        if (owner._isSupportClipBoard()) {
                            // retInfo = this.Paste(start, end, pasteData, isExitOnLastChar);
                            retInfo = this.TextBoxPaste(start, end, text, exitOnLastChar, acceptTab, acceptReturn, maxLength, lengthAsByte, maxLine, isCountWrappedLine, multiLine);
                            //retInfo.System = false;
                        } else {
                            retInfo.System = true;
                        }
                        break;

                    case 131160:
                        //In password input status,cut shoud disable
                        //if(multiLine || !passwordMode)
                        if (!passwordMode) {
                            if (this.Owner === undefined) {
                                owner = this.control;
                            } else {
                                owner = this.Owner;
                            }
                            if (owner._isSupportClipBoard()) {
                                retInfo = this.Cut(text, start, end);
                                //retInfo.System = false;
                            } else {
                                retInfo.System = true;
                            }
                        } else {
                            retInfo.System = false;
                        }
                        break;

                    case 65582:
                        if (start != end) {
                            retInfo = this.Cut(text, start, end);
                        } else {
                            //use system backspace
                            this.systemEdit = true;
                            this.keyupResponse = true;
                            retInfo.KeyCode = 8;
                        }

                        // Modified by shenyuan at 2006-01-13 for new undo rules
                        this.DelOperation(k, start, end); //01-23
                        retInfo.SerialDel = this.IsSerialDel;
                        retInfo.DelInclude = true;
                        break;

                    case 131137:
                        retInfo = this.TextBoxSelectAll(text);
                        break;

                    case 131162:
                        // Need add undo methods by Ryan wu.
                        // Modified by shenyuan at 2006-01-13 for new undo rules.
                        retInfo = this.TextBoxUndo(text, buffText, undoText, oldStart, oldEnd, start, end); //02-07 for bug #5101
                        break;

                    case 65573:
                        this.ForwardSelection = "Left";
                        retInfo.System = true;
                        this.keyupResponse = true;
                        break;

                    case 65575:
                        this.ForwardSelection = "Right";
                        retInfo.System = true;
                        this.keyupResponse = true;
                        break;

                    case 65574:
                        if (multiLine) {
                            this.ForwardSelection = "Left";
                            retInfo.System = true;
                            this.keyupResponse = true;
                        } else {
                            if (end > 0) {
                                retInfo.SelectionEnd = end - 1;
                            }
                            retInfo.SetSelection = true;
                        }
                        break;

                    case 65576:
                        if (multiLine) {
                            this.ForwardSelection = "Right";
                            retInfo.System = true;
                            this.keyupResponse = true;
                        } else {
                            if (end < text.GetLength()) {
                                retInfo.SelectionEnd = end + 1;
                            }
                            retInfo.SetSelection = true;
                        }
                        break;

                    case 65569:
                        this.ForwardSelection = "Left";
                        retInfo.System = true;
                        this.keyupResponse = true;
                        break;

                    case 65570:
                        this.ForwardSelection = "Right";
                        retInfo.System = true;
                        this.keyupResponse = true;
                        break;

                    case 196645:
                        this.ForwardSelection = "Left";
                        retInfo.System = true;
                        this.keyupResponse = true;
                        break;

                    case 196647:
                        this.ForwardSelection = "Right";
                        retInfo.System = true;
                        this.keyupResponse = true;
                        break;

                    case 65572:

                    case 196644:
                        this.ForwardSelection = "Left";
                        retInfo.System = true;
                        this.keyupResponse = true;
                        break;

                    case 65571:

                    case 196643:
                        this.ForwardSelection = "Right";
                        retInfo.System = true;
                        this.keyupResponse = true;
                        break;

                    case 37:

                    case 131109:
                        //Add by Ryan Wu at 16:14 Feb. 19, 2006.
                        //For fix bug#4993.
                        isPressContinuousely = false; //If this.IsKeyDown is true, then indicate that the current action is pressing the key continousely.
                        if (this.IsKeyDown) {
                            isPressContinuousely = true;
                        } else {
                            this.IsKeyDown = true;
                            this.CurStart = start;
                            this.CurEnd = end;
                        }

                        if (isPressContinuousely) {
                            if (this.CurStart === 0 && this.CurEnd == 0 && (exitOnLeftRightKey === 3 /* Both */ || exitOnLeftRightKey === 1 /* Left */)) {
                                var exitType = k === 37 ? "Left" : "CtrlLeft";
                                ret = this.MoveControl(this.control.InputElement, false, true, exitType);
                                if (ret != null) {
                                    retInfo.EventInfo = new Array();
                                    retInfo.EventInfo[0] = ret.EventInfo;
                                    retInfo.FocusType = ret.FocusType;
                                    retInfo.FocusExit = true;
                                }

                                this.IsKeyDown = false;
                                break;
                            }
                        }

                        this.CurStart -= 1;
                        this.CurEnd = this.CurStart;

                        //end by Ryan.
                        //Move to previous control
                        if (start === 0 && end === 0 && (exitOnLeftRightKey === 3 /* Both */ || exitOnLeftRightKey === 1 /* Left */)) {
                            var exitType = k === 37 ? "Left" : "CtrlLeft";
                            ret = this.MoveControl(this.control.InputElement, false, true, exitType); //01-20

                            // Modified by shenyuan at 2006-01-20.
                            if (ret != null) {
                                retInfo.EventInfo = new Array();
                                retInfo.EventInfo[0] = ret.EventInfo;
                                retInfo.FocusType = ret.FocusType;
                                retInfo.FocusExit = true;
                            }
                        } else {
                            //Modified by shenyuan at 2006-02-08 for bug #4939.
                            if (!readOnly) {
                                this.keyupResponse = true;
                            }
                            retInfo.System = true;
                        }
                        break;

                    case 39:

                    case 131111:
                        //Add by Ryan Wu at 16:14 Feb. 19, 2006.
                        //For fix bug#4993.
                        isPressContinuousely = false; //If this.IsKeyDown is true, then indicate that the current action is pressing the key continousely.
                        if (this.IsKeyDown) {
                            isPressContinuousely = true;
                        } else {
                            this.IsKeyDown = true;
                            this.CurStart = start;
                            this.CurEnd = end;
                        }

                        if (isPressContinuousely) {
                            if (this.CurStart === text.GetLength() && this.CurEnd === text.GetLength() && (exitOnLeftRightKey === 3 /* Both */ || exitOnLeftRightKey === 2 /* Right */)) {
                                var exitType = k == 39 ? "Right" : "CtrlRight";
                                ret = this.MoveControl(this.control.InputElement, true, true, exitType);
                                if (ret != null) {
                                    retInfo.EventInfo = new Array();
                                    retInfo.EventInfo[0] = ret.EventInfo;
                                    retInfo.FocusType = ret.FocusType;
                                    retInfo.FocusExit = true;
                                }

                                this.IsKeyDown = false;
                                break;
                            }
                        }

                        this.CurStart += 1;
                        this.CurEnd = this.CurStart;

                        //end by Ryan.
                        //Move to next control
                        if (start === text.GetLength() && end === text.GetLength() && (exitOnLeftRightKey === 3 /* Both */ || exitOnLeftRightKey === 2 /* Right */)) {
                            var exitType = k == 39 ? "Right" : "CtrlRight";
                            ret = this.MoveControl(this.control.InputElement, true, true, exitType); //01-20

                            // Modified by shenyuan at 2006-01-20.
                            if (ret != null) {
                                retInfo.EventInfo = new Array();
                                retInfo.EventInfo[0] = ret.EventInfo;
                                retInfo.FocusType = ret.FocusType;
                                retInfo.FocusExit = true;
                            }
                        } else {
                            //Modified by shenyuan at 2006-02-08 for bug #4939.
                            if (!readOnly) {
                                this.keyupResponse = true;
                            }
                            retInfo.System = true;
                        }
                        break;

                    case 33:
                    case 131105:
                        this.keyupResponse = true;

                        //modified by sj for bug 887 on ttp
                        //				//modified by sj 2008.8.12 for bug 339
                        //				if (FindIMControl(this.ElementID).MultiLine)
                        //				{
                        //				    var startPosition=0;
                        //				    Utility.SetSelection(FindIMControl(this.ElementID).InputElement,startPosition,startPosition,true);
                        //				}
                        //
                        //				retInfo.System = false;
                        //				//end by sj
                        //				//retInfo.System = true;
                        if (multiLine) {
                            // DaryLuo 2012/11/07 fix bug 872 in IM Web 7.0.
                            //var selectionPosition = 0;
                            //retInfo.SetSelection = true;
                            //retInfo.SelectionStart = selectionPosition;
                            //retInfo.SelectionEnd = selectionPosition;
                            retInfo.System = true;
                        } else {
                            retInfo.System = false;
                        }

                        break;

                    case 34:
                    case 131106:
                        this.keyupResponse = true;

                        //modified by sj for bug 887 on ttp
                        //				//modified by sj 2008.8.12 for bug 339
                        //				if (FindIMControl(this.ElementID).MultiLine)
                        //				{
                        //					var endPosition=FindIMControl(this.ElementID).GetText().GetLength();
                        //				    Utility.SetSelection(FindIMControl(this.ElementID).InputElement,endPosition,endPosition,true);
                        //				}
                        //
                        //				retInfo.System = false;
                        //				//end by sj
                        //
                        //				//retInfo.System = true;
                        if (multiLine) {
                            // DaryLuo 2012/11/07 fix bug 872 in IM Web 7.0.
                            //var selectionPosition = text.GetLength();
                            //retInfo.SetSelection = true;
                            //retInfo.SelectionStart = selectionPosition;
                            //retInfo.SelectionEnd = selectionPosition;
                            retInfo.System = true;
                        } else {
                            retInfo.System = false;
                        }

                        break;

                    case 38:
                        //Modified by shenyuan at 2006-02-08 for bug #4939.
                        if (!readOnly) {
                            this.keyupResponse = true;
                        }

                        // HelenLiu 2013/06/24 fix bug 773 in IM HTML5.
                        if (this.Owner.GetMultiLine()) {
                            retInfo.System = true;
                        } else {
                            retInfo.System = false;
                        }

                        break;

                    case 40:
                        //Modified by shenyuan at 2006-02-08 for bug #4939.
                        if (!readOnly) {
                            this.keyupResponse = true;
                        }

                        // HelenLiu 2013/06/24 fix bug 773 in IM HTML5.
                        if (this.Owner.GetMultiLine()) {
                            retInfo.System = true;
                        } else {
                            retInfo.System = false;
                        }
                        break;

                    case 131108:
                    case 36:
                        this.keyupResponse = true;
                        retInfo.System = true;
                        break;

                    case 131107:
                    case 35:
                        this.keyupResponse = true;
                        retInfo.System = true;
                        break;

                    case 131112:
                    case 131110:
                        this.keyupResponse = true;
                        retInfo.System = true;
                        break;

                    case 27:
                        this.control.Clear();
                        break;

                    case 393266:
                    case 393267:
                    case 393268:
                    case 393269:
                    case 393271:
                    case 393272:
                    case 393273:
                    case 393264:
                    case 393403:
                    case 393285:
                    case 393442:
                    case 393293:
                    case 393402:
                        this.keypressResponse = true;
                        retInfo.System = true;
                        break;
                    default:
                        break;
                }

                if (k !== undefined && k !== null) {
                    if ((k >= 48 && k <= 57) || (k >= 65 && k <= 90) || (k >= 96 && k <= 105) || k == 229 || k == 0 || k == 231) {
                        //input status.Response by keypress event.
                        this.keypressResponse = true;
                        if (retInfo == null) {
                            retInfo = {};
                        }
                        retInfo.System = true;
                        retInfo.inputChar = true;
                        return retInfo;
                    }

                    // for symbol charactors
                    //Add comments by Ryan Wu at 15:03 Mar. 2 2006.
                    //For fix bug that 226 keycode can't be input into the edit reported by Japan.
                    /*if(  k==32 || k == 106 || k == 107 || k == 109 || k == 110 || k == 111 || k == 219
                    || k == 220 || k == 221 || k == 222 || (k >= 186 && k <= 192) )*/
                    //end by Ryan.
                    var fireFoxSpecial = (k == 173 || k == 64 || k == 160 || k == 65594 || k == 58 || k == 65709 || k == 65600 || k == 65696) && _input.CoreUtility.IsFireFox4OrLater();

                    if (fireFoxSpecial || k == 32 || k == 106 || k == 107 || k == 109 || k == 110 || k == 111 || k == 219 || k == 220 || k == 221 || k == 222 || (k >= 186 && k <= 192) || k == 226 || k == 231) {
                        //input status.Response by keypress event.
                        this.keypressResponse = true;
                        retInfo.System = true;
                        return retInfo;
                    }

                    // Add comments by Yang at 14:00 Sep. 12th 2007
                    // For fix the bug 8754
                    if (!_input.CoreUtility.IsIE() && (k === 61 || k === 59)) {
                        this.keypressResponse = true;
                        retInfo.System = true;
                        return retInfo;
                    }

                    // End by Yang
                    var tempk = k;

                    //Shift + key
                    if (evt.shiftKey) {
                        tempk = tempk - 65536;
                    }

                    //Alt + key
                    if (evt.altKey) {
                        tempk = tempk - 262144;
                    }

                    if ((tempk >= 48 && tempk <= 57) || (tempk >= 65 && tempk <= 90) || (tempk >= 96 && tempk <= 105) || tempk == 229) {
                        //input status.Response by keyup event.
                        this.keypressResponse = true;
                        retInfo.System = true;
                        return retInfo;
                    }

                    // for symbol charactors
                    //Add comments by Ryan Wu at 15:03 Mar. 2 2006.
                    //For fix bug that 226 keycode can't be input into the edit reported by Japan.
                    /*if (tempk == 32 || tempk == 106 || tempk == 107 || tempk == 109 || tempk == 110
                    || tempk == 111 || tempk == 219 || tempk == 220 || tempk == 221
                    || tempk == 222 || (tempk >= 186 && tempk <= 192))*/
                    if (tempk == 32 || tempk == 106 || tempk == 107 || tempk == 109 || (k == 173 && _input.CoreUtility.IsFireFox4OrLater()) || tempk == 110 || tempk == 111 || tempk == 219 || tempk == 220 || tempk == 221 || tempk == 222 || (tempk >= 186 && tempk <= 192) || tempk == 226 || tempk == 231) {
                        //input status.Response by keyup event.
                        this.keypressResponse = true;
                        retInfo.System = true;
                        return retInfo;
                    }

                    // Add comments by Yang at 14:00 Sep. 12th 2007
                    // For fix the bug 8754
                    if (!_input.CoreUtility.IsIE() && (tempk == 61 || tempk == 59)) {
                        this.keypressResponse = true;
                        retInfo.System = true;
                        return retInfo;
                    }
                    // End by Yang
                }
                return retInfo;
            };

            GcTextBoxUIProcess.prototype.TextBoxKeyPress = function (start, end, inputChar, oldText, maxLength, lengthAsByte, exitOnLastChar, overwrite, multiLine, maxLine, isCountWrappedLine) {
                // maxLine isCountWrappedLine
                if (this.keypressResponse == true) {
                    this.keypressResponse = false;
                    this.isInputValid = true;
                    var retInfo = new Object();
                    var processInfo = new Object();

                    // Add comments by Yang at 15:22 Sep. 5th 2007
                    // For in Firefox when press enter, the value is "\n".
                    var sEnter = "\r\n";
                    if (!_input.CoreUtility.IsIE() || parseInt($.browser.version) >= 9) {
                        sEnter = "\n";
                    }

                    // End by Yang
                    //if (this.japInput != true) {
                    //    this.japInput = (evt != null && evt.keyCode == 229) ? true : false;
                    //}
                    //Format check
                    var insertChar = "";

                    //If input tab character,ignore the format check
                    if (inputChar == "\t") {
                        insertChar = inputChar;
                    } else {
                        if (inputChar == "\r" || inputChar == "\n") {
                            if (multiLine) {
                                // Add comments by Yang at 15:22 Sep. 5th 2007
                                // For in Firefox when press enter, the value is "\n".
                                //insertChar = "\r\n";
                                insertChar = sEnter;
                                // End by Yang
                            } else {
                                retInfo.SystemEdit = true;
                                return retInfo;
                            }
                        } else {
                            if (inputChar.GetLength() == 1) {
                                insertChar = this.Filter.Check(inputChar);
                            } else {
                                var ret = this.Filter.CheckText(inputChar);
                                insertChar = ret.CheckedText;
                                this.isInputValid = ret.IsInputValid;
                            }
                        }
                    }

                    //maxLength check
                    if (start == end) {
                        if (maxLength != 0) {
                            var maxLengthOfNewInput = maxLength - this.GetLength(oldText, lengthAsByte);

                            // Add comments by Yang at 15:22 Sep. 5th 2007
                            // For in Firefox when press enter, the value is "\n".
                            //if (insertChar == "\r\n")
                            if (insertChar == sEnter) {
                                // Add comments by Yang at 15:22 Sep. 5th 2007
                                // For in Firefox when press enter, the value is "\n".
                                //if (maxLengthOfNewInput < 2 && maxLength != 0)
                                if (maxLengthOfNewInput < sEnter.GetLength() && maxLength != 0) {
                                    insertChar = "";
                                }
                            } else {
                                if (!overwrite || (overwrite && start == oldText.GetLength())) {
                                    if (maxLength > this.GetLength(oldText, lengthAsByte)) {
                                        insertChar = this.MaxLengthCheck(insertChar, maxLengthOfNewInput, lengthAsByte);
                                    } else {
                                        insertChar = "";
                                    }
                                } else if (overwrite) {
                                    var remainedText = oldText.Substring(0, start);
                                    var leftText = oldText.Substring(start, oldText.GetLength());

                                    // Add comments by Yang at 15:22 Sep. 5th 2007
                                    // For in Firefox when press enter, the value is "\n".
                                    //var index = leftText.IndexOf("\r\n");
                                    var index = leftText.IndexOf(sEnter);

                                    // End by Yang
                                    if (index != -1) {
                                        remainedText += leftText.Substring(index, leftText.GetLength());
                                    }
                                    maxLengthOfNewInput = maxLength - this.GetLength(remainedText, lengthAsByte);
                                    insertChar = this.MaxLengthCheck(insertChar, maxLengthOfNewInput, lengthAsByte);
                                }
                            }
                        }
                    } else {
                        var selectedText = oldText.Substring(Math.min(start, end), Math.max(start, end));
                        if (maxLength != 0) {
                            var maxLengthOfNewInput = maxLength - this.GetLength(oldText, lengthAsByte) + this.GetLength(selectedText, lengthAsByte);

                            // Add comments by Yang at 15:22 Sep. 5th 2007
                            // For in Firefox when press enter, the value is "\n".
                            //if (insertChar == "\r\n")
                            if (insertChar == sEnter) {
                                // Add comments by Yang at 15:22 Sep. 5th 2007
                                // For in Firefox when press enter, the value is "\n".
                                //if (maxLengthOfNewInput < 2)
                                if (maxLengthOfNewInput < sEnter.GetLength()) {
                                    insertChar = "";
                                }
                            } else {
                                insertChar = this.MaxLengthCheck(insertChar, maxLengthOfNewInput, lengthAsByte);
                            }
                        }
                    }

                    if (maxLine != 0 && multiLine) {
                        if (maxLine >= this.GetLinesCount(oldText, isCountWrappedLine)) {
                            var foreText = oldText.Substring(0, start);
                            var backText = oldText.Substring(end, oldText.GetLength());

                            //				    insertChar = this.MaxLineCheck(foreText, backText, insertChar, maxLine, isCountWrappedLine);
                            if (this.PasswordMode) {
                                foreText = this.GetPasswordText(foreText, this.PasswordChar, multiLine);
                                backText = this.GetPasswordText(backText, this.PasswordChar, multiLine);
                                var passwordText = this.GetPasswordText(insertChar, this.PasswordChar, multiLine);
                                passwordText = this.MaxLineCheck(foreText, backText, passwordText, maxLine, isCountWrappedLine);
                                insertChar = insertChar.Substring(0, passwordText.GetLength());
                            } else {
                                insertChar = this.MaxLineCheck(foreText, backText, insertChar, maxLine, isCountWrappedLine);
                            }
                        } else {
                            insertChar = "";
                        }
                    }

                    //Sign for Format InvalidInput
                    //modified by sj 2008.8.13 for bug 594
                    //if (insertChar == "")
                    if (inputChar != "" && insertChar == "") {
                        this.isInputValid = false;
                    }

                    //Change OldText
                    var newText = oldText;

                    //Insert
                    // Add comments by Yang at 15:22 Sep. 5th 2007
                    // For in Firefox when press enter, the value is "\n".
                    //if (!overwrite || insertChar == "\r\n" || start != end)
                    if (!overwrite || insertChar == sEnter || start != end) {
                        if (start > end) {
                            var temp = start;
                            start = end;
                            end = temp;
                        }

                        // Modified by shenyuan at 2006-01-13 for new undo rules.
                        if (start != end) {
                            retInfo.DelInclude = true;
                            this.IsDelInclude = true;
                        }

                        // Modified by shenyuan at 2006-01-23 for bug #5058.
                        //modified by sj to remove allowspace
                        //if (inputChar != " " || (allowspace != "None"))
                        if (insertChar != "") {
                            newText = oldText.Substring(0, start) + insertChar + oldText.Substring(end, oldText.GetLength());
                        }
                    } else {
                        if (insertChar != "") {
                            if (start == oldText.GetLength()) {
                                newText = oldText + insertChar;
                            } else {
                                // Add comments by Yang at 15:22 Sep. 5th 2007
                                // For in Firefox when press enter, the value is "\n".
                                //if (start + 2 <= oldText.GetLength() && oldText.Substring(start,start + 2) == "\r\n")
                                if (start + sEnter.GetLength() <= oldText.GetLength() && oldText.Substring(start, start + sEnter.GetLength()) == sEnter) {
                                    newText = oldText.Substring(0, start) + insertChar + oldText.Substring(start, oldText.GetLength());
                                } else {
                                    // Modified by shenyuan at 2006-01-11 for bug 4731.
                                    var replacedText;
                                    if (maxLength == 0 || !lengthAsByte) {
                                        replacedText = oldText.Substring(start, start + insertChar.GetLength());
                                    } else {
                                        var i_Start = insertChar.GetLength();
                                        var nextChar = oldText.Substring(start, start + i_Start);
                                        var oldLength = this.GetLength(nextChar, lengthAsByte);
                                        var insertLength = this.GetLength(insertChar, lengthAsByte);
                                        while (insertLength > oldLength && i_Start <= oldText.GetLength()) {
                                            i_Start = i_Start + 1;
                                            nextChar = oldText.Substring(start, start + i_Start);
                                            oldLength = this.GetLength(nextChar, lengthAsByte);
                                        }
                                        replacedText = oldText.Substring(start, start + i_Start);
                                    }

                                    // Add comments by Yang at 15:22 Sep. 5th 2007
                                    // For in Firefox when press enter, the value is "\n".
                                    //var index = replacedText.IndexOf("\r");
                                    var index = replacedText.IndexOf(sEnter);

                                    // End by Yang
                                    if (index != -1) {
                                        newText = oldText.Substring(0, start) + insertChar + oldText.Substring(start + index, oldText.GetLength());
                                    } else {
                                        newText = oldText.Substring(0, start) + insertChar + oldText.Substring(start + replacedText.GetLength(), oldText.GetLength());
                                    }
                                    // Ended.
                                }
                            }
                        }
                    }

                    retInfo.Text = newText;
                    retInfo.SetSelection = true;

                    //Reset Cursor position
                    if (this.isInputValid != false || insertChar.GetLength() > 0) {
                        retInfo.SelectionStart = start + insertChar.GetLength();
                        retInfo.SelectionEnd = retInfo.SelectionStart;
                    }
                    retInfo.EventInfo = new Array();

                    //InvalidInput
                    if (!this.isInputValid) {
                        this.isInputValid = true;
                        var ret = new Object();

                        //if (this.InvalidInputEvent != "" && this.InvalidInputEvent != null) {
                        ret.Name = this.control.InvalidInputEvent;

                        //ret.Args = "";
                        ret.Args = inputChar;

                        //Add comments by Ryan Wu at 10:47 Apr. 5 2007.
                        //For support Aspnet Ajax 1.0.
                        ret.Type = "invalidInput";

                        //end by Ryan Wu.
                        //}
                        retInfo.EventInfo[0] = ret;
                    }

                    //ExitOnLastChar
                    if (retInfo.Text != null && exitOnLastChar && maxLength != 0) {
                        var nowLength = this.GetLength(retInfo.Text.Substring(0, retInfo.SelectionStart), lengthAsByte);
                        if (nowLength == maxLength && insertChar != "") {
                            var ret = this.MoveControl(this.control.InputElement, true, false, "CharInput");

                            // Modified by shenyuan at 2006-01-20.
                            if (ret != null) {
                                retInfo.EventInfo[1] = ret.EventInfo;
                                retInfo.FocusType = ret.FocusType;
                                retInfo.FocusExit = true;
                                retInfo.SetSelection = false;
                            }
                        }
                    }

                    return retInfo;
                } else {
                    return false;
                }
            };

            GcTextBoxUIProcess.prototype.TextBoxKeyUp = function (oText, multiLine, start, end, text) {
                var retInfo = new Object();

                //Add by Ryan Wu at 16:29 Feb. 19 2006.
                //For fix bug#4993.
                this.IsKeyDown = false;

                //end by Ryan Wu.
                retInfo.SelectionStart = _input.Utility.GetSelectionStartPosition(oText);

                // Add comments by Yang at 14:00 Aug. 28th 2007
                // For Firefox doesn't support the method document.selection.createRange()
                //retInfo.SelectionEnd   = retInfo.SelectionStart + document.selection.createRange().text.GetLength();
                retInfo.SelectionEnd = retInfo.SelectionStart + _input.Utility.GetSelectionText(this.control.InputElement).GetLength();

                // End by Yang
                if (this.systemEdit == true) {
                    this.systemEdit = false;
                    retInfo.SystemEdit = true;
                }

                if (this.ctrlDelete || this.ctrlBackspace) {
                    var finalStart;
                    if (this.ctrlDelete) {
                        finalStart = retInfo.SelectionStart;
                        this.ctrlDelete = false;
                    } else if (this.ctrlBackspace) {
                        finalStart = end;
                        this.ctrlBackspace = false;
                    }

                    retInfo.Text = text.Substring(0, start) + text.Substring(finalStart, text.GetLength());
                    retInfo.SelectionStart = retInfo.SelectionEnd = start;
                    retInfo.SetSelection = true;
                }

                return retInfo;
            };

            GcTextBoxUIProcess.prototype.TextBoxMouseDown = function (oText, mouseButton) {
                this.isFocusing = false;
                return new Object();
            };

            GcTextBoxUIProcess.prototype.TextBoxMouseUp = function (oText, start, end, mouseButton, multiLine, text, isCtrlPress, highlightText, evt) {
                var retInfo = new Object();
                if (this.isFocusing) {
                    this.isFocusing = false;

                    if (highlightText) {
                        return retInfo;
                    }
                }

                //MoueButton.Left
                if (mouseButton == 0 /* Left */) {
                    //var elementID = this.ElementID + Utility.EditFieldSuffix;
                    //if (this.IsjQueryControl == true) {
                    //    elementID = this.ElementID;
                    //}
                    //Trick Click
                    if (this.isDblClick && !_input.Utility.GrapeCityTimeout) {
                        this.isDblClick = false;
                        this.isTriClick = true;
                        if (multiLine) {
                            var position = _input.Utility.GetSelectionStartPosition(oText);
                            var ret = this.GetLineEnds(position, text);
                            if (ret.start != null) {
                                retInfo.SelectionStart = ret.start;
                            }

                            if (ret.end != null) {
                                retInfo.SelectionEnd = ret.end;
                            }
                        } else {
                            retInfo.SelectionStart = 0;
                            retInfo.SelectionEnd = text.GetLength();
                        }
                    } else if (_input.Utility.GetSelectionText(this.control.InputElement) != "" || !multiLine) {
                        retInfo.SelectionStart = _input.Utility.GetSelectionStartPosition(oText);
                        retInfo.SelectionEnd = retInfo.SelectionStart + _input.Utility.GetSelectionText(this.control.InputElement).GetLength();
                    } else if (_input.Utility.GetSelectionText(this.control.InputElement) == "") {
                        retInfo.SelectionStart = _input.Utility.GetSelectionStartPosition(oText);
                        retInfo.SelectionEnd = retInfo.SelectionStart + _input.Utility.GetSelectionText(this.control.InputElement).GetLength();
                    } else {
                        retInfo.SelectionStart = _input.Utility.GetSelectionStartPosition(oText);
                        if (document.selection) {
                            if (evt.y < document.selection.createRange().offsetTop) {
                                retInfo.SelectionStart -= 2;
                            }
                        }
                        retInfo.SelectionEnd = retInfo.SelectionStart;
                    }

                    //Add comments by Yang at 14:00 Sep. 23 2007.
                    //For fix the bug 8848.
                    if (!_input.CoreUtility.IsIE() && _input.Utility.FuncKeysPressed.Ctrl) {
                        //modified by sj for bug 874
                        //	            retInfo = this.SelectAll(oText.value);
                        //		        return retInfo;
                        if (multiLine) {
                            var position = _input.Utility.GetSelectionStartPosition(oText);
                            var ret = this.GetLineEnds(position, text);
                            if (ret.start != null) {
                                retInfo.SelectionStart = ret.start;
                            }

                            if (ret.end != null) {
                                retInfo.SelectionEnd = ret.end;
                            }
                        } else {
                            retInfo.SelectionStart = 0;
                            retInfo.SelectionEnd = text.GetLength();
                        }
                        //end by sj
                    }

                    //End by Yang.
                    if (retInfo.SelectionStart != retInfo.SelectionEnd) {
                        retInfo.SetSelection = true; //For Bug 3782
                    }
                }
                return retInfo;
            };

            GcTextBoxUIProcess.prototype.GetLineEnds = function (realCursorPosition, text) {
                var temp = text;
                var position1 = 0;

                // Add comments by Yang at 15:22 Sep. 5th 2007
                // For in Firefox when press enter, the value is "\n".
                var sEnter = "\r\n";
                if (!_input.CoreUtility.IsIE() || parseInt($.browser.version) >= 9) {
                    sEnter = "\n";
                }

                // End by Yang
                // Add comments by Yang at 15:22 Sep. 5th 2007
                // For in Firefox when press enter, the value is "\n".
                //var position2 = temp.IndexOf("\r\n");
                var position2 = temp.IndexOf(sEnter);

                // End by Yang
                var retInfo = new Object();
                while (position2 != -1) {
                    // Add comments by Yang at 15:22 Sep. 5th 2007
                    // For in Firefox when press enter, the value is "\n".
                    //if(realCursorPosition >=  position1 && realCursorPosition < position1 + position2 + 2)
                    if (realCursorPosition >= position1 && realCursorPosition < position1 + position2 + sEnter.GetLength()) {
                        retInfo.start = position1;
                        retInfo.end = position1 + position2;
                        return retInfo;
                    } else {
                        // Add comments by Yang at 15:22 Sep. 5th 2007
                        // For in Firefox when press enter, the value is "\n".
                        //position1 = position1 + position2 + 2;
                        //temp = temp.Substring(position2 + 2, temp.GetLength());
                        //position2  = temp.IndexOf("\r\n");
                        position1 = position1 + position2 + sEnter.GetLength();
                        temp = temp.Substring(position2 + sEnter.GetLength(), temp.GetLength());
                        position2 = temp.IndexOf(sEnter);
                        // End by Yang
                    }
                }
                retInfo.start = position1;
                retInfo.end = text.GetLength();
                return retInfo;
            };

            GcTextBoxUIProcess.prototype.ShowContextMenu = function (oText, multiLine) {
                var retInfo = new Object();

                //var elementID = this.ElementID + Utility.EditFieldSuffix;
                //if (this.IsjQueryControl == true) {
                //    elementID = this.ElementID;
                //}
                retInfo.SelectionStart = _input.Utility.GetSelectionStartPosition(oText);
                retInfo.SelectionEnd = retInfo.SelectionStart + _input.Utility.GetSelectionText(this.control.InputElement).GetLength();
                return retInfo;
            };

            GcTextBoxUIProcess.prototype.TextBoxDoubleClick = function (oText, start, text) {
                //var elementID = this.ElementID + Utility.EditFieldSuffix;
                //if (this.IsjQueryControl == true) {
                //    elementID = this.ElementID;
                //}
                this.isDblClick = true;

                //set timer for tripple click
                _input.Utility.GrapeCityTimeout = false;
                window.setTimeout(function () {
                    _input.Utility.GrapeCityTimeout = true;
                }, 500);

                var retInfo = new Object();
                retInfo.SelectionStart = _input.Utility.GetSelectionStartPosition(oText);
                retInfo.SelectionEnd = retInfo.SelectionStart + _input.Utility.GetSelectionText(this.control.InputElement).GetLength();
                return retInfo;
            };

            GcTextBoxUIProcess.prototype.SelectStart = function (obj, selText, multiLine) {
                if (this.isTriClick) {
                    this.isTriClick = false;
                }

                var retInfo = new Object();
                retInfo.SelectionStart = _input.Utility.GetSelectionStartPosition(obj);
                retInfo.SelectionEnd = retInfo.SelectionStart;
                return retInfo;
            };

            GcTextBoxUIProcess.prototype.Copy = function (text, start, end) {
                if (start != end) {
                    if (start > end) {
                        var temp = start;
                        start = end;
                        end = temp;
                    }

                    var cText = text.Substring(start, end);
                    var useClipboard = true;
                    if (this.Owner) {
                        if (this.Owner.MultiLine === false) {
                            cText = _input.BaseUIProcess.UpdateCrLfString(cText, this.Owner.AcceptsCrLf);
                        }
                        useClipboard = this.Owner.UseClipboard;
                    }
                    if (!_input.CoreUtility.IsIE()) {
                        _input.Utility.SetCopy(cText, false);
                    } else {
                        _input.Utility.SetCopy(cText, useClipboard);
                    }
                }
            };

            GcTextBoxUIProcess.prototype.TextBoxPaste = function (start, end, text, exitOnLastChar, acceptTab, acceptReturn, maxLength, lengthAsByte, maxLine, isCountWrappedLine, multiLine, clipboardtext, isSetSelectedText) {
                // maxLine multiLine isCountWrappedLine
                this.isInputValid = true;
                var retInfo = new Object();
                var useClipboard = (this.Owner ? this.Owner.UseClipboard : true);
                if (!_input.CoreUtility.IsIE()) {
                    useClipboard = false;
                }

                //var pasteData = Utility.GetPasteData(this.Owner ? this.Owner.GetUseClipboard() : true);
                var pasteData = (clipboardtext == null ? _input.Utility.GetPasteData(useClipboard) : clipboardtext);
                if (_input.CoreUtility.chrome) {
                    pasteData = pasteData.replace(/\r\n/g, "\n");
                }
                if (!isSetSelectedText && this.Owner && this.Owner.MultiLine === false) {
                    pasteData = _input.BaseUIProcess.UpdateCrLfString(pasteData, this.Owner.AcceptsCrLf);
                }

                if (_input.CoreUtility.IsIE9OrLater()) {
                    if (this.Owner && this.Owner.MultiLine === true) {
                        // DaryLuo 2013/05/07 fix bug 1067 in IM Web 7.0, html textarea doesn't support '\r' char.
                        pasteData = _input.BaseUIProcess.FilterReturnChar(pasteData);
                    }
                }
                ;

                if (pasteData == null) {
                    return retInfo;
                }
                this.FireClientEvent("OnBeforePaste");
                var formatedPasteData = this.FormatCheck(pasteData, acceptTab, acceptReturn);
                var maxLengthCheckedPasteDate = formatedPasteData;
                var maxLengthOfNewInput;
                if (maxLength != 0) {
                    //Modified for lengthAsByte == true
                    //The selectedText's length may not be start - end
                    var selectedTextLength = this.GetLength(text.Substring(Math.min(start, end), Math.max(start, end)), lengthAsByte);
                    maxLengthOfNewInput = maxLength - this.GetLength(text, lengthAsByte) + selectedTextLength;
                    maxLengthCheckedPasteDate = this.MaxLengthCheck(formatedPasteData, maxLengthOfNewInput, lengthAsByte);
                }

                if (maxLine != 0 && multiLine) {
                    if (maxLine >= this.GetLinesCount(text, isCountWrappedLine)) {
                        var foreText = text.Substring(0, start);
                        var backText = text.Substring(end, text.GetLength());

                        //			    maxLengthCheckedPasteDate = this.MaxLineCheck(foreText, backText, maxLengthCheckedPasteDate, maxLine, isCountWrappedLine);
                        if (this.PasswordMode) {
                            foreText = this.GetPasswordText(foreText, this.PasswordChar, multiLine);
                            backText = this.GetPasswordText(backText, this.PasswordChar, multiLine);
                            var passwordText = this.GetPasswordText(maxLengthCheckedPasteDate, this.PasswordChar, multiLine);
                            passwordText = this.MaxLineCheck(foreText, backText, passwordText, maxLine, isCountWrappedLine);
                            maxLengthCheckedPasteDate = maxLengthCheckedPasteDate.Substring(0, passwordText.GetLength());
                        } else {
                            maxLengthCheckedPasteDate = this.MaxLineCheck(foreText, backText, maxLengthCheckedPasteDate, maxLine, isCountWrappedLine);
                        }
                    } else {
                        maxLengthCheckedPasteDate = "";
                    }
                }

                var selectionStart = Math.min(start, end);
                var selectionEnd = Math.max(start, end);

                // HelenLiu 2013/06/14 fix bug 688 in IM HTML5.
                if (maxLengthCheckedPasteDate != "" || isSetSelectedText === true) {
                    retInfo.Text = text.Substring(0, selectionStart) + maxLengthCheckedPasteDate + text.Substring(selectionEnd, text.GetLength());

                    //// HelenLiu 2013/06/09 fix bug 645 in IM HTML5.0.
                    //if (isSetSelectedText === true) {
                    //    retInfo.SelectionStart = selectionStart;
                    //    retInfo.SelectionEnd = retInfo.SelectionStart + maxLengthCheckedPasteDate.GetLength();
                    //} else {
                    retInfo.SelectionStart = selectionStart + maxLengthCheckedPasteDate.GetLength();
                    retInfo.SelectionEnd = retInfo.SelectionStart;
                    //}
                }
                retInfo.SetSelection = true;

                // Modified by shenyuan at 2006-01-13 for new undo rules
                if (start != end) {
                    retInfo.DelInclude = true;
                    this.IsDelInclude = true;
                }

                retInfo.EventInfo = new Array();

                //InvalidInput
                if (!this.isInputValid) {
                    this.isInputValid = true;
                    var ret = new Object();

                    //if (this.InvalidInputEvent != "" && this.InvalidInputEvent != null) {
                    ret.Name = this.control.InvalidInputEvent;

                    //ret.Args = "";
                    ret.Args = pasteData;

                    //Add comments by Ryan Wu at 10:47 Apr. 5 2007.
                    //For support Aspnet Ajax 1.0.
                    ret.Type = "invalidInput";

                    //end by Ryan Wu.
                    //}
                    retInfo.EventInfo[0] = ret;
                }

                //ExitOnLastChar
                if (retInfo.Text != null) {
                    var nowLength = this.GetLength(retInfo.Text.Substring(0, retInfo.SelectionStart), lengthAsByte);
                } else {
                    // DaryLuo 2012/11/02 fix bug 857 in IM Web 7.0.
                    var nowLength = 0;
                }
                if (maxLength != 0 && nowLength == maxLength && exitOnLastChar && maxLengthCheckedPasteDate != "") {
                    // Add comments by Yang at 11:10 October 11th 2007
                    // For fix the bug 9000
                    // HelenLiu 2013/07/04 fix bug 744 in IM HTML5.
                    //if (!Utility.IsIE()) {
                    //    FindIMControl(this.ElementID).SetServerSideText(retInfo.Text);
                    //}
                    // End by Yang
                    var ret = this.MoveControl(this.control.InputElement, true, false, "CharInput");

                    // Modified by shenyuan at 2006-01-20.
                    if (ret != null) {
                        retInfo.EventInfo[1] = ret.EventInfo;
                        retInfo.FocusType = ret.FocusType;
                        retInfo.FocusExit = true;
                        retInfo.SetSelection = false;
                    }
                }

                this.FireClientEvent("OnPaste");
                return retInfo;
            };

            GcTextBoxUIProcess.prototype.Cut = function (text, start, end) {
                var retInfo = new Object();

                //this.FireClientEvent("OnBeforeCut");
                //modified by sj 2008.8.8 for bug 82
                if (start != end) {
                    this.FireClientEvent("OnBeforeCut");
                }

                //end by sj
                this.Copy(text, start, end);

                //Delete the Selection part
                if (start < end) {
                    retInfo.SelectionStart = start;
                    retInfo.Text = text.Substring(0, start) + text.Substring(end, text.GetLength());
                } else {
                    retInfo.SelectionStart = end;
                    retInfo.Text = text.Substring(0, end) + text.Substring(start, text.GetLength());
                }

                retInfo.SelectionEnd = retInfo.SelectionStart;
                retInfo.SetSelection = true;

                //Modified by shenyuan at 2006-02-20 for bug #5303.
                //Modified by shenyuan at 2006-02-27 for bug #5377.
                if (retInfo.Text != text) {
                    retInfo.DelInclude = true;
                    this.IsDelInclude = true;
                }

                //this.FireClientEvent("OnCut");
                //modified by sj 2008.8.8 for bug 82
                if (start != end) {
                    this.FireClientEvent("OnCut");
                }

                //end by sj
                return retInfo;
            };

            GcTextBoxUIProcess.prototype.TextBoxUndo = function (text, buffText, undoText, oldStart, oldEnd, oStart, oEnd) {
                var retInfo = new Object();

                // Modified by shenyuan at 2006-01-13 for new undo rules.
                //if (text != undoText)
                if (this.IsDelInclude) {
                    if (text != buffText) {
                        retInfo.Text = buffText;

                        //retInfo.SelectionStart = buffText.GetLength();
                        //retInfo.SelectionEnd = buffText.GetLength();
                        // Modified by shenyuan at 2006-02-07 for bug #5101.
                        retInfo.SelectionStart = oStart;
                        retInfo.SelectionEnd = oEnd;
                        retInfo.SetSelection = true;
                        retInfo.DelInclude = true;
                        retInfo.Undo = true;
                    }
                } else {
                    if (text != undoText) {
                        retInfo.Text = undoText;
                        retInfo.SelectionStart = oldStart;
                        retInfo.SelectionEnd = oldEnd;
                        retInfo.SetSelection = true;
                        retInfo.Undo = true;
                    }
                }

                //Modified by shenyuan at 2006-01-24 for bug #5100.
                //When undo is done, the StartPos should be initialized.
                this.StartPos = null;

                //Modified by shenyuan at 2006-02-21 for reopened bug #5098.
                this.LastKey = null;
                return retInfo;
            };

            GcTextBoxUIProcess.prototype.Delete = function (multiLine, text, start, end) {
                var retInfo = new Object();
                if (start < end) {
                    retInfo.SelectionStart = start;
                    retInfo.Text = text.Substring(0, start) + text.Substring(end, text.GetLength());
                } else {
                    retInfo.SelectionStart = end;
                    retInfo.Text = text.Substring(0, end) + text.Substring(start, text.GetLength());
                }
                retInfo.SelectionEnd = retInfo.SelectionStart;
                retInfo.SetSelection = true;

                //Modified by shenyuan at 2006-02-27 for bug #5385.
                if (retInfo.Text != text) {
                    retInfo.DelInclude = true;
                    this.IsDelInclude = true;
                }
                return retInfo;
            };

            GcTextBoxUIProcess.prototype.TextBoxSelectAll = function (text) {
                var retInfo = new Object();
                retInfo.SelectionStart = 0;
                retInfo.SelectionEnd = text.GetLength();
                retInfo.SetSelection = true;
                return retInfo;
            };

            GcTextBoxUIProcess.prototype.DragDrop = function (dragText, exitOnLastChar, start, end, maxLength, lengthAsByte, maxLine, isCountWrappedLine, multiLine, text) {
                this.isInputValid = true;
                var retInfo = new Object();
                var formatedDragText = this.FormatCheck(dragText);
                var maxLengthCheckedDragText = formatedDragText;
                var maxLengthOfNewInput = 0;
                if (maxLength != 0) {
                    maxLengthOfNewInput = maxLength - this.GetLength(text, lengthAsByte);
                    maxLengthCheckedDragText = this.MaxLengthCheck(formatedDragText, maxLengthOfNewInput, lengthAsByte);
                }

                if (maxLine != 0 && multiLine) {
                    if (maxLine >= this.GetLinesCount(text, isCountWrappedLine)) {
                        var foreText = text.Substring(0, start);
                        var backText = text.Substring(end, text.GetLength());

                        //			    maxLengthCheckedDragText = this.MaxLineCheck(foreText, backText, maxLengthCheckedDragText, maxLine, isCountWrappedLine);
                        if (this.PasswordMode) {
                            foreText = this.GetPasswordText(foreText, this.PasswordChar, multiLine);
                            backText = this.GetPasswordText(backText, this.PasswordChar, multiLine);
                            var passwordText = this.GetPasswordText(maxLengthCheckedDragText, this.PasswordChar, multiLine);
                            passwordText = this.MaxLineCheck(foreText, backText, passwordText, maxLine, isCountWrappedLine);

                            //maxLengthCheckedDragText = insertChar.Substring(0, maxLengthCheckedDragText.GetLength());
                            maxLengthCheckedDragText = passwordText.Substring(0, maxLengthCheckedDragText.GetLength());
                        } else {
                            maxLengthCheckedDragText = this.MaxLineCheck(foreText, backText, maxLengthCheckedDragText, maxLine, isCountWrappedLine);
                        }
                    } else {
                        maxLengthCheckedDragText = "";
                    }
                }

                retInfo.DropText = maxLengthCheckedDragText;

                retInfo.EventInfo = new Array();

                //InvalidInput
                if (!this.isInputValid) {
                    this.isInputValid = true;
                    var ret = new Object();

                    //if (this.InvalidInputEvent != "" && this.InvalidInputEvent != null) {
                    ret.Name = this.control.InvalidInputEvent;

                    //ret.Args = "";
                    ret.Args = formatedDragText;

                    //Add comments by Ryan Wu at 10:47 Apr. 5 2007.
                    //For support Aspnet Ajax 1.0.
                    ret.Type = "invalidInput";

                    //end by Ryan Wu.
                    //}
                    retInfo.EventInfo[0] = ret;
                }

                //ExitOnLastChar
                if (this.GetLength(formatedDragText, lengthAsByte) >= maxLengthOfNewInput && maxLength != 0 && exitOnLastChar && maxLengthCheckedDragText != "") {
                    //var ret = this.MoveControl(this.ElementID, true);
                    var ret = new Object();
                    if (this.Owner.KeyExitEvent != "" && this.Owner.KeyExitEvent != null) {
                        ret.Name = this.Owner.KeyExitEvent;

                        //modified by sj 2008.8.13 for bug 582
                        //ret.Args="";
                        ret.Args = new Object();
                        ret.Args.Key = 9;

                        //end by sj
                        //Add comments by Ryan Wu at 10:48 Apr. 5 2007.
                        //For support Aspnet Ajax 1.0.
                        ret.Type = "KeyExit";
                        //end by Ryan Wu.
                    }
                    retInfo.EventInfo[1] = ret;
                    //retInfo.FocusType = ret.FocusType;
                    //retInfo.FocusExit = true;
                }
                return retInfo;
            };

            GcTextBoxUIProcess.prototype.TextBoxFocus = function (focusType, oText, text, multiline, highlightText, showContextmenu) {
                var retInfo = new Object();
                this.isFocusing = true;

                //var elementID = this.ElementID + Utility.EditFieldSuffix;
                //if (this.IsjQueryControl == true) {
                //    elementID = this.ElementID;
                //}
                //Add comments by Ryan Wu at 15:38 Apr. 27 2007.
                //For fix the bug#7769.
                if (focusType === 9 /* Left */) {
                    retInfo.SelectionStart = 0;
                    retInfo.SelectionEnd = 0;
                } else if (focusType === 10 /* Right */) {
                    retInfo.SelectionStart = text.GetLength();
                    retInfo.SelectionEnd = text.GetLength();
                }

                //end by Ryan Wu.
                if (!highlightText) {
                    if (focusType === 1 /* Click */ || focusType == 11 /* DragDrop */) {
                        retInfo.SelectionStart = _input.Utility.GetSelectionStartPosition(oText);
                        retInfo.SelectionEnd = retInfo.SelectionStart + _input.Utility.GetSelectionText(this.control.InputElement).GetLength();
                    }
                } else if (!showContextmenu) {
                    retInfo.SelectionStart = 0;
                    retInfo.SelectionEnd = text.GetLength();
                }

                if ((focusType !== 1 /* Click */) || highlightText) {
                    retInfo.SetSelection = true;
                }

                return retInfo;
            };

            GcTextBoxUIProcess.prototype.MaxLengthCheck = function (text, maxLength, lengthAsByte) {
                var checkedText = "";
                var textLength = 0;

                //if text "\r\n",text cannot be clipped
                if (text == "\r\n") {
                    if (maxLength >= 2) {
                        checkedText = text;
                    }
                } else {
                    if (lengthAsByte) {
                        for (var i = 0; i < text.GetLength(); i++) {
                            var substr = text.Substring(i, i + 1);
                            if (substr.length >= 2) {
                                textLength += 2 * substr.length;
                            } else if (this.Filter.IsFullWidth(substr)) {
                                textLength += 2;
                            } else {
                                textLength++;
                            }

                            if (textLength <= maxLength) {
                                checkedText += text.Substring(i, i + 1);
                            } else {
                                break;
                            }
                        }
                    } else {
                        if (text.GetLength() <= maxLength) {
                            checkedText = text;
                        } else {
                            checkedText = text.Substring(0, maxLength);
                        }
                    }
                }

                var temp = checkedText.GetLength();
                if (temp != 0 && checkedText.Substring(temp - 1, temp) == "\r") {
                    checkedText = checkedText.Substring(0, temp - 1);
                }

                if (checkedText != text) {
                    this.isInputValid = false;
                }
                return checkedText;
            };

            GcTextBoxUIProcess.prototype.MaxLineCheck = function (foreText, backText, insertText, maxLine, isCountWrappedLine) {
                var checkedText = "";
                var maxLineText = foreText + insertText + backText;
                var lineCount = this.GetLinesCount(maxLineText, isCountWrappedLine);
                if (lineCount <= maxLine) {
                    checkedText = insertText;
                } else {
                    var start = 0;
                    var end = insertText.GetLength();
                    do {
                        var mid = Math.floor((start + end) / 2);
                        var tempInsert = insertText.Substring(0, mid);
                        maxLineText = foreText + tempInsert + backText;
                        lineCount = this.GetLinesCount(maxLineText, isCountWrappedLine);
                        if (lineCount > maxLine) {
                            end = mid;
                        } else if (lineCount < maxLine) {
                            start = mid;
                        } else if ((lineCount == maxLine) && (end > start + 1)) {
                            start = mid;
                        } else if ((lineCount == maxLine) && (end == start + 1)) {
                            break;
                        }
                    } while(start < end);

                    checkedText = insertText.Substring(0, start);
                }

                if (checkedText != insertText) {
                    this.isInputValid = false;
                }

                return checkedText;
            };

            GcTextBoxUIProcess.prototype.GetLinesCount = function (text, countWrappedLine) {
                var count = 1;
                var isWrappedLine = countWrappedLine;

                if (text == "") {
                    return count;
                }

                var obj = this._testTextArea;

                if (this._testTextArea === undefined || this._testTextArea === null) {
                    this._testTextArea = $("<textarea/>");
                    this._testTextArea.css('visibility', "hidden");
                    this._testTextArea.css('position', "absolute");
                    this._testTextArea.css('left', "-100000000px");
                    this._testTextArea.css('top', "-100000000px");
                    this._testTextArea.attr('rows', 1);

                    this._testTextArea.appendTo($(document.body));
                    obj = this._testTextArea;
                    isWrappedLine = false;
                }

                if (!isWrappedLine) {
                    var temptext = text;
                    var savetext = temptext;
                    var index = temptext.IndexOf("\r\n");
                    count = 1;
                    while (index != -1) {
                        savetext = savetext.replace("\r\n", "");
                        count = count + 1;
                        temptext = temptext.Substring(index + 2, temptext.GetLength());
                        index = temptext.IndexOf("\r\n");
                    }

                    temptext = savetext;
                    index = temptext.IndexOf("\r");
                    while (index != -1) {
                        savetext = savetext.replace("\r", "");
                        count = count + 1;
                        temptext = temptext.Substring(index + 1, temptext.GetLength());
                        index = temptext.IndexOf("\r");
                    }

                    temptext = savetext;
                    index = temptext.IndexOf("\n");
                    while (index != -1) {
                        savetext = savetext.replace("\n", "");
                        count = count + 1;
                        temptext = temptext.Substring(index + 1, temptext.GetLength());
                        index = temptext.IndexOf("\n");
                    }

                    return count;
                }

                // Add comments by Yang at 16:54 Dec.2th 2008
                // For fix the bug TTP 751
                var temptext1 = text;
                temptext1 = temptext1.replace(/\r\n/g, "\r");
                temptext1 = temptext1.replace(/\n/g, "\r");
                var index = temptext1.IndexOf("\r");
                if (index != -1) {
                    count = 0;
                    var preText = temptext1.Substring(0, index);
                    count += this.GetLinesCount(preText, countWrappedLine);
                    temptext1 = temptext1.Substring(index + 1, temptext1.GetLength());
                    count += this.GetLinesCount(temptext1, countWrappedLine);
                    return count;
                } else {
                    //modified by sj 2008.8.12 for bug 365
                    var obj_edit = $(this.control.InputElement);

                    // HelenLiu 2013/06/19 fix bug 754 in IM HTML5.
                    obj.css('fontSize', obj_edit.css('fontSize'));
                    obj.css('fontFamily', obj_edit.css('fontFamily'));
                    obj.css('width', obj_edit.css('width'));
                    obj.css('borderWidth', obj_edit.css('borderWidth'));
                    obj.css('padding', obj_edit.css('padding'));

                    // HelenLiu 2013/07/17 fix bug 1098 in IM HTML5.
                    obj.css('wordWrap', obj_edit.css('wordWrap'));

                    //obj.style.overflowX = obj_edit.style.overflowX;
                    obj.css('overflowY', obj_edit.css('overflowY'));

                    //end by sj
                    if (obj != null) {
                        obj.val(text);

                        obj = obj.get(0);
                        while (obj.scrollHeight - obj.clientHeight > 1) {
                            obj.rows++;
                        }

                        obj.scrollTop = 0;
                        count = obj.rows;

                        if (obj.rows > 1) {
                            obj.rows = 1;
                        }
                        return count;
                    }
                }
            };

            GcTextBoxUIProcess.prototype.FormatCheck = function (text, acceptTab, acceptReturn) {
                if (this.Owner && !this.Owner.MultiLine && text) {
                    if (typeof (text) != "string") {
                        text = text.toString();
                    }

                    text = text.replace(/[\r\n]/g, "");
                }

                var ret = this.Filter.CheckText(text);
                var formatedText = ret.CheckedText;
                this.isInputValid = ret.IsInputValid;
                return formatedText;
            };

            GcTextBoxUIProcess.prototype.ListValidateCheck = function (text) {
                var temp = this.Filter.autoConvert;
                this.Filter.autoConvert = false;
                var ret = this.Filter.CheckText(text);
                this.Filter.autoConvert = temp;
                return ret.IsInputValid;
            };

            GcTextBoxUIProcess.prototype.GetLength = function (text, lengthAsByte) {
                var textLength = 0;
                if (lengthAsByte) {
                    for (var i = 0; i < text.GetLength(); i++) {
                        var substr = text.Substring(i, i + 1);
                        if (substr.length >= 2) {
                            textLength += 2 * substr.length;
                        } else if (this.Filter.IsFullWidth(substr)) {
                            textLength += 2;
                        } else {
                            textLength++;
                        }
                    }
                } else {
                    textLength = text.GetLength();
                }
                return textLength;
            };

            GcTextBoxUIProcess.prototype.TextBoxProcessBackSpace = function (multiLine, text, start, end) {
                var retInfo = new Object();
                this.systemEdit = true;
                this.keyupResponse = true;
                retInfo.System = true;
                return retInfo;
            };

            GcTextBoxUIProcess.prototype.GetRightWordPosition = function (start, text) {
                if (start < text.GetLength()) {
                    var cursorPosition = start;
                    var character = text.Substring(start, start + 1);
                    var previousChar = character;
                    while (!((this.Filter.IsFormatSpace(previousChar) && !(this.Filter.IsFormatSpace(character))) || ((character == "\r" || previousChar == "\n") && start != cursorPosition) || ((character == "\t" || previousChar == "\t") && start != cursorPosition))) {
                        cursorPosition = cursorPosition + 1;
                        if (cursorPosition < text.GetLength()) {
                            previousChar = character;
                            character = text.Substring(cursorPosition, cursorPosition + 1);
                        } else {
                            break;
                        }
                    }
                    return cursorPosition;
                } else {
                    return start;
                }
            };

            GcTextBoxUIProcess.prototype.DelOperation = function (dKey, sPosition, ePosition) {
                this.IsDelInclude = true;
                var selectlength = Math.abs(ePosition - sPosition);

                switch (dKey) {
                    case 8:
                        //Add by shenyuan at 2006-02-28 for bug #5411.
                        var isPressContinuousely = false;

                        //If this.IsKeyDown is true, then indicate that the current action is pressing the key continousely.
                        if (this.IsKeyDown) {
                            isPressContinuousely = true;
                        } else {
                            this.IsKeyDown = true;
                            this.CurStart = sPosition - 1;
                        }

                        if (isPressContinuousely) {
                            this.IsSerialDel = true;
                            break;
                        } else {
                            if (this.CurStart == this.StartPos) {
                                this.IsSerialDel = true;
                                this.CurStart -= 1;
                            }
                        }

                        //Ended.
                        if (sPosition != ePosition) {
                            if (sPosition < this.StartPos) {
                                this.StartPos -= selectlength;
                            } else if (sPosition == this.StartPos) {
                                this.IsSerialDel = true;
                                this.StartPos = sPosition;
                                break;
                            }
                        } else if (sPosition == this.StartPos) {
                            this.IsSerialDel = true;
                            this.StartPos = sPosition - 1;
                            break;
                        }

                        sPosition -= 1;

                        if (this.StartPos == sPosition) {
                            this.IsSerialDel = true;
                        } else {
                            this.IsSerialDel = false;
                        }

                        this.StartPos = sPosition - 1;
                        break;

                    case 131080:
                    case 196616:
                        if (sPosition == ePosition) {
                            sPosition -= 1;
                        } else if (sPosition < this.StartPos) {
                            this.StartPos -= selectlength;
                        } else if (sPosition == this.StartPos) {
                            this.IsSerialDel = true;
                            this.StartPos = sPosition - 1;
                            break;
                        }

                        if (this.StartPos == sPosition) {
                            this.IsSerialDel = true;
                        } else {
                            this.IsSerialDel = false;
                        }
                        this.StartPos = sPosition - 1;
                        break;

                    case 65544:
                        if (sPosition != ePosition) {
                            if (sPosition < this.StartPos) {
                                this.StartPos -= selectlength;
                            }
                        }

                        if (this.StartPos == sPosition) {
                            this.IsSerialDel = true;
                        } else {
                            this.IsSerialDel = false;
                        }
                        this.StartPos = sPosition - 1;
                        break;

                    case 65582:
                        if (sPosition == ePosition) {
                            sPosition -= 1;
                        } else if (sPosition < this.StartPos) {
                            this.StartPos -= selectlength;
                        } else if (sPosition == this.StartPos) {
                            this.IsSerialDel = true;
                            this.StartPos = sPosition;
                            break;
                        }

                        if (this.StartPos == sPosition || this.StartPos == ePosition) {
                            this.IsSerialDel = true;
                        } else {
                            this.IsSerialDel = false;
                        }

                        this.StartPos = sPosition - 1;
                        break;

                    case 46:
                        var tmpPos = null;
                        if (this.LastKey == 8) {
                            tmpPos = sPosition;
                            sPosition -= 1;
                        }

                        if (this.StartPos == sPosition || (this.StartPos != null && Math.abs(this.StartPos - sPosition) == 1) || this.StartPos == ePosition) {
                            this.IsSerialDel = true;
                        } else {
                            this.IsSerialDel = false;

                            //Added by shenyuan for bug #5404.
                            if (tmpPos != null) {
                                this.StartPos = tmpPos;
                                break;
                            }
                        }
                        this.StartPos = sPosition;
                        break;

                    case 131118:
                        if (sPosition != ePosition) {
                            if (sPosition < this.StartPos) {
                                this.StartPos -= selectlength;
                            } else if (sPosition == this.StartPos) {
                                this.IsSerialDel = true;
                                this.StartPos = sPosition;
                                break;
                            }
                        }

                        sPosition -= 1;

                        if (this.StartPos == sPosition || (sPosition - this.StartPos) == 1) {
                            this.IsSerialDel = true;
                        } else {
                            this.IsSerialDel = false;
                        }
                        this.StartPos = sPosition;
                        break;
                }

                this.LastKey = dKey;
            };

            GcTextBoxUIProcess.prototype.GetPasswordText = function (text, passowrdchar, multiline) {
                var passwordText = "";
                for (var i = 0; i < text.GetLength(); i++) {
                    var singletext = text.Substring(i, i + 1);
                    if (singletext != "\r" && singletext != "\n") {
                        passwordText += passowrdchar;
                    } else {
                        if (multiline) {
                            passwordText += singletext;
                        }
                    }
                }
                return passwordText;
            };
            return GcTextBoxUIProcess;
        })(_input.BaseUIProcess);
        _input.GcTextBoxUIProcess = GcTextBoxUIProcess;
        ;

        /** @ignore */
        var AutoComplete = (function () {
            function AutoComplete(owner) {
                this._hightlightIndex = -1;
                this._dataList = [];
                this._isDeleteItem = false;
                this._isFocusOnList = false;
                this._isMouseOnList = false;
                this._owner = owner;

                var defaultMaxItems = 5;

                this._maxItems = defaultMaxItems;
                this._firstItemShowing = 0;
                this._lastItemShowing = defaultMaxItems - 1;

                this._refreshElement();
                this._createDropdown();
            }
            AutoComplete.prototype._refreshElement = function () {
                this._controlContainer = this._owner.GetContainer();
                this._inputElement = this._owner.GetJQueryInputElement();
                this._maxItems = this._owner.GetMaxHistoryCount();
                if (this._inputElement) {
                    this._inputElement.attr("autocomplete", "off");
                }
            };

            AutoComplete.prototype._createDropdown = function () {
                var div = $("<div>");
                div.css({
                    "position": "absolute",
                    "zIndex": "999999",
                    "display": "none",
                    "backgroundColor": "white",
                    "border": "solid 1px black",
                    "overflowX": "hidden",
                    "overflowY": "auto"
                });

                var self = this;

                div.bind("focus", function () {
                    self._isFocusOnList = true;
                    div.blur();
                    self._owner.SetInnerFocus(2 /* ContextMenu */);
                });
                div.bind("mouseover", function () {
                    self._isMouseOnList = true;
                });
                div.bind("mouseout", function () {
                    self._isMouseOnList = false;
                });

                div.bind("contextmenu", function (evt) {
                    evt.preventDefault();
                });

                this._dropDownElement = div;
            };

            AutoComplete.prototype.GetIsDeleteItem = function () {
                return this._isDeleteItem;
            };
            AutoComplete.prototype.SetIsDeleteItem = function (value) {
                this._isDeleteItem = value;
            };

            AutoComplete.prototype.GetIsFocusOnList = function () {
                return this._isFocusOnList;
            };
            AutoComplete.prototype.SetIsFocusOnList = function (value) {
                this._isFocusOnList = value;
            };

            AutoComplete.prototype.GetIsMouseOnList = function () {
                return this._isMouseOnList;
            };

            AutoComplete.prototype.ShowDropdown = function () {
                this._refreshElement();

                if (this.IsVisible()) {
                    this.HideDropdown();
                }

                this._dropDownElement.empty();
                var displayCount;
                displayCount = this._addDisplayItems();
                if (displayCount === 0) {
                    return;
                }

                var left = _input.Utility.GetElementPosition(this._controlContainer.get(0)).Left;
                var top = _input.Utility.GetElementPosition(this._controlContainer.get(0)).Top + this._controlContainer.outerHeight();
                var width = this._controlContainer.outerWidth();
                var height = "";
                if (displayCount > this._maxItems) {
                    var itemHeight = _input.CoreUtility.MeasureText("WHQ", this._dropDownElement.get(0).firstChild).Height;
                    height = this._maxItems * (itemHeight + 2) + 'px';
                }
                var zoom = "";
                if (_input.Utility.IsTouchMouseDown == true) {
                    zoom = this._owner.GetTouchDropDownScale() + '';
                }
                width -= 2; //2 is the borders.
                this._dropDownElement.css("left", left + "px");
                this._dropDownElement.css("top", top + "px");
                this._dropDownElement.css("width", width + "px");
                this._dropDownElement.css("display", "");
                _input.Utility.SetZoomStyle(this._dropDownElement, zoom);
                this._dropDownElement.css("height", height);

                $("body").append(this._dropDownElement);
                var self = this;
                this._docClickListerner = function () {
                    self.HideDropdown();
                };

                $(document).bind("click", this._docClickListerner);
            };

            AutoComplete.prototype._addDisplayItems = function () {
                var value = this._inputElement.val();
                var toDisplay = [];

                for (var i = 0; i < this._dataList.length; ++i) {
                    if (this._dataList[i].substr(0, value.GetLength()) == value && this._dataList[i].GetLength() > value.GetLength()) {
                        toDisplay.push(this._dataList[i]);
                    }
                }

                var self = this;

                // HelenLiu 2013/07/02 fix bug 888 in IM HTML5.
                var length = (toDisplay.length > this._maxItems ? this._maxItems : toDisplay.length);
                for (i = 0; i < length; ++i) {
                    var newDiv = $('<div>');

                    newDiv.attr("index", i);
                    newDiv.css({
                        "fontFamily": _input.Utility.GetOSDefaultFontFamily(),
                        "fontSize": "10pt",
                        "whiteSpace": 'nowrap',
                        "padding": "1px"
                    });
                    newDiv.bind("mouseover", function (evt) {
                        var srcElement = evt.target || evt.srcElement;
                        self.HighlightItem(parseInt(srcElement.getAttribute('index').toString()));
                    });
                    newDiv.bind("click", function () {
                        self._isFocusOnList = false;
                        self.SetValue();
                        self.HideDropdown();
                    });
                    newDiv.html(_input.Utility.EncodingToHTML(toDisplay[i]));

                    this._dropDownElement.append(newDiv);
                }
                return length;
            };

            AutoComplete.prototype.HideDropdown = function () {
                if (this.IsVisible()) {
                    this._dropDownElement.remove();
                    this._dropDownElement.css("display", "none");

                    $("document").unbind("click", this._docClickListerner);

                    this._dropDownElement.empty();
                    this._isMouseOnList = false;

                    // HelenLiu 2013/06/20 fix bug 786 in IM HTML5.
                    this._hightlightIndex = -1;
                }
            };

            AutoComplete.prototype.SetDataList = function (list) {
                if (list === null || list === undefined) {
                    list = [];
                }
                this._dataList = list;
            };

            AutoComplete.prototype.IsDataListEmpty = function () {
                return this._dataList.length === 0;
            };

            AutoComplete.prototype.HighlightItem = function (index) {
                this.SetHighlighItem(index);
            };

            AutoComplete.prototype.SetHighlighItem = function (index) {
                var node = this._dropDownElement.get(0).childNodes[this._hightlightIndex];
                if (this._hightlightIndex !== -1) {
                    node.style.backgroundColor = "";
                    node.style.color = "";
                }
                this._hightlightIndex = index;
                if (this._hightlightIndex !== -1) {
                    //if (this._owner.GetRealControlEffect() === ControlEffect.VistaTheme) {
                    //    this._dropDownElement.childNodes[this._hightlightIndex].style.backgroundColor = "#3399ff";
                    //} else {
                    //    if (this._dropDownElement.childNodes[this._hightlightIndex] !== undefined) {
                    //        this._dropDownElement.childNodes[this._hightlightIndex].style.backgroundColor = "#0a246a";
                    //    }
                    //}
                    node.style.color = "white";
                }
            };

            AutoComplete.prototype.Highlight = function (index) {
                var isBound = false;
                if (index > 0 && this._hightlightIndex == this._dropDownElement.get(0).childNodes.length - 1) {
                    this.SetHighlighItem(-1);
                    isBound = true;
                } else if (index < 0 && this._hightlightIndex == 0) {
                    this.SetHighlighItem(-1);
                    isBound = true;
                }

                if (this._hightlightIndex === -1) {
                    if (isBound == false) {
                        if (index > 0) {
                            this.SetHighlighItem(0);
                        }
                        if (index < 0) {
                            this.SetHighlighItem(this._dropDownElement.get(0).childNodes.length - 1);
                        }
                    }
                } else {
                    var newIndex;
                    if (index > 1) {
                        if ((this._firstItemShowing + this._maxItems - 1) !== this._hightlightIndex) {
                            index = this._firstItemShowing + this._maxItems - this._hightlightIndex;
                        }
                    }
                    if (index < -1) {
                        if (this._firstItemShowing != this._hightlightIndex) {
                            index = this._firstItemShowing - this._hightlightIndex;
                        }
                    }
                    if (index > 0) {
                        newIndex = ((this._hightlightIndex + index) >= this._dropDownElement.get(0).childNodes.length) ? this._dropDownElement.get(0).childNodes.length - 1 : (this._hightlightIndex + index);
                    } else {
                        newIndex = ((this._hightlightIndex + index) < 0) ? 0 : (this._hightlightIndex + index);
                    }
                    if (index > 1) {
                        newIndex = newIndex - 1;
                    }

                    this.SetHighlighItem(newIndex);
                }
            };

            AutoComplete.prototype.SetValue = function () {
                var node = this._dropDownElement.get(0).childNodes[this._hightlightIndex], newText = node.innerHTML;

                newText = _input.Utility.DecodingFromHTML(newText);

                this._owner.InternalSetText(newText, true);
                this._owner.SetInnerFocus(2 /* ContextMenu */);

                var ePos = this._inputElement.val().GetLength();

                var selectedLength = Math.abs(this._owner.SelectionEnd - this._owner.SelectionStart);
                if (selectedLength != 0) {
                    this._owner.InternalSetSelection(0, ePos);
                } else {
                    this._owner.InternalSetSelection(ePos, ePos);
                }
            };

            AutoComplete.prototype.ScrollCheck = function () {
                if (this._hightlightIndex !== -1) {
                    if (this._hightlightIndex > this._lastItemShowing) {
                        this._firstItemShowing = this._hightlightIndex - (this._maxItems - 1);
                        this._lastItemShowing = this._hightlightIndex;
                    }

                    if (this._hightlightIndex < this._firstItemShowing) {
                        this._firstItemShowing = this._hightlightIndex;
                        this._lastItemShowing = this._hightlightIndex + (this._maxItems - 1);
                    }
                    var itemHeight = _input.CoreUtility.MeasureText("WQH", this._dropDownElement.get(0).firstChild).Height + 2;
                    this._dropDownElement.get(0).scrollTop = this._firstItemShowing * itemHeight;
                }
            };

            AutoComplete.prototype.KeyDown = function (evt) {
                var keyCode = evt.keyCode;
                var functionKeyPressed = { Shift: false, Ctrl: false, Alt: false };
                if (evt.shiftKey) {
                    functionKeyPressed.Shift = true;
                }

                if (evt.ctrlKey) {
                    functionKeyPressed.Ctrl = true;
                }

                if (evt.altKey) {
                    functionKeyPressed.Alt = true;
                }

                var Keys = _input.Key;
                switch (keyCode) {
                    case 13 /* Enter */:
                        if (this._hightlightIndex !== -1) {
                            this.SetValue();
                            this.HideDropdown();
                            evt.stopPropagation();
                            evt.preventDefault();
                            return false;
                        }
                        break;

                    case 46 /* Delete */:
                        if (this._hightlightIndex !== -1) {
                            var node = this._dropDownElement.get(0).childNodes[this._hightlightIndex], str = node.innerHTML;
                            this.HideDropdown();
                            this._owner.DeleteItem(str);
                            this._isDeleteItem = true;
                            this._inputElement.focus();
                            if (!this.IsVisible()) {
                                this.ShowDropdown();
                            }
                            evt.stopPropagation();
                            evt.preventDefault();
                            return false;
                        }
                        break;

                    case 27 /* Escape */:
                        this.HideDropdown();
                        evt.stopPropagation();
                        evt.preventDefault();
                        break;

                    case 38 /* Up */:
                        if (functionKeyPressed.Alt) {
                            break;
                        }
                        if (!this.IsVisible()) {
                            this.ShowDropdown();
                        } else {
                            if (this._hightlightIndex === -1) {
                                this.ShowDropdown();
                            }
                            this.Highlight(-1);
                            this.ScrollCheck();
                        }
                        return false;

                    case 33 /* PageUp */:
                        if (!this.IsVisible()) {
                            this.ShowDropdown();
                        } else {
                            if (this._hightlightIndex === -1) {
                                this.ShowDropdown();
                            }
                            this.Highlight(-1 * (this._maxItems));
                            this.ScrollCheck();
                        }
                        return false;

                    case 9 /* Tab */:
                        this.HideDropdown();
                        break;

                    case 40 /* Down */:
                        if (functionKeyPressed.Alt) {
                            break;
                        }
                        if (!this.IsVisible()) {
                            this.ShowDropdown();
                        } else {
                            this.Highlight(1);
                            this.ScrollCheck();
                        }
                        return false;

                    case 34 /* PageDown */:
                        if (!this.IsVisible()) {
                            this.ShowDropdown();
                        } else {
                            this.Highlight(this._maxItems);
                            this.ScrollCheck();
                        }
                        return false;
                }
            };

            AutoComplete.prototype.KeyUp = function (evt, showdropdown) {
                if (showdropdown === true) {
                    this.ShowDropdown();
                    return;
                }

                var keyCode = evt.keyCode;
                var keys = _input.Key;
                switch (keyCode) {
                    case 13 /* Enter */:
                        break;
                    case 27 /* Escape */:
                        this.HideDropdown();
                        break;
                    case 38 /* Up */:
                    case 40 /* Down */:
                        break;

                    default:
                        this.ShowDropdown();
                        break;
                }
            };

            AutoComplete.prototype.IsVisible = function () {
                return this._dropDownElement.css("display") === '';
            };
            return AutoComplete;
        })();
        _input.AutoComplete = AutoComplete;
        ;
    })(wijmo.input || (wijmo.input = {}));
    var input = wijmo.input;
})(wijmo || (wijmo = {}));


;
/*
 * Depends:
 * jquery-1.11.1.js
 * jquery.ui.core.js
 * jquery.ui.widget.js
 * globalize.js
 * jquery.wijmo.widget.js
 * jquery.wijmo.wijutil.js
 * wijmo.data.js
 *
 * Optional dependencies for paging feature:
 * jquery.wijmo.wijpager.js
 *
 * Optional dependencies for scrolling feature:
 * jquery.wijmo.wijsuperpanel.js
 *
 * Optional dependencies for filtering feature:
 * jquery.ui.position.js
 * jquery.wijmo.wijinputdateformat.js
 * jquery.wijmo.wijinputdateroller.js
 * jquery.wijmo.wijinputdate.js
 * jquery.wijmo.wijinputtextformat.js
 * jquery.wijmo.wijinputtext.js
 * jquery.wijmo.wijinputnumberformat.js
 * jquery.wijmo.wijinputnumber.js
 * jquery.wijmo.wijlist.js
 *
 * Optional dependencies for column moving feature:
 * jquery.ui.draggable.js
 * jquery.ui.droppable.js
 * jquery.ui.position.js
 *
 */

/// <reference path="../../../Base/jquery.wijmo.widget.ts"/>
/// <reference path="../../../wijutil/jquery.wijmo.wijutil.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /// <reference path="interfaces.ts" />
    /// <reference path="bands_traversing.ts" />
    /// <reference path="misc.ts"/>
    /// <reference path="cellInfo.ts"/>
    /// <reference path="selection.ts"/>
    /// <reference path="cellEditorHelper.ts"/>
    /// <reference path="cellFormatterHelper.ts"/>
    /// <reference path="cellStyleFormatterHelper.ts"/>
    /// <reference path="rowStyleFormatterHelper.ts"/>
    /// <reference path="fixedView.ts"/>
    /// <reference path="flatView.ts"/>
    /// <reference path="dataViewWrapper.ts"/>
    /// <reference path="filterOperators.ts"/>
    /// <reference path="columnsGenerator.ts"/>
    /// <reference path="rowAccessor.ts"/>
    /// <reference path="grouper.ts"/>
    /// <reference path="renderBoundsCollection.ts"/>
    /// <reference path="uiDragndrop.ts"/>
    /// <reference path="uiSelection.ts"/>
    /// <reference path="uiResizer.ts"/>
    /// <reference path="uiFrozener.ts"/>
    /// <reference path="c1field.ts"/>
    /// <reference path="c1band.ts"/>
    /// <reference path="c1buttonfield.ts"/>
    /// <reference path="sketchTable.ts"/>
    /// <reference path="hierarchyBuilder.ts"/>
    /// <reference path="../../../data/src/core.ts"/>
    /// <reference path="../../../data/src/dataView.ts"/>
    /// <reference path="../data/converters.ts"/>
    /// <reference path="../data/koDataView.ts"/> // add reference, otherwise it will be not added to the grunt output.
    /// <reference path="../../../wijpager/jquery.wijmo.wijpager.ts"/>
    (function (grid) {
        var $ = jQuery;

        /** @ignore */
        function extendWidgetOptions(baseOptions, newOptions) {
            var result = $.extend(true, {}, baseOptions, newOptions);

            delete result.constructor; // Remove the constructor because the widget.options object is a ts class now (widgetName_options).

            return result;
        }
        grid.extendWidgetOptions = extendWidgetOptions;

        /** @widget
        * Represents the wijgrid widget.
        */
        var wijgrid = (function (_super) {
            __extends(wijgrid, _super);
            function wijgrid() {
                _super.apply(this, arguments);
                this.mDataOffset = 0;
                this.mRowOuterHeight = -1;
                this._windowResizeTimer = 0;
                this.mEditSkechRowIndex = -1;
                this.mCurrentCellLocker = false;
            }
            // * override
            wijgrid.prototype._createWidget = function (options, element) {
                // A fix for the case if options.data contains a complex object leading to stack overflow when
                // 1. $.extend is called in the widget factory
                // 2. wijmoASPNetParseOptions is  called in the _create method.
                // Clear the data options (grid + details) and persist them within the element using $.data().
                wijmo.grid.DataOptionPersister.persistAndClearIntoElement(element, options);

                _super.prototype._createWidget.apply(this, arguments);

                wijmo.grid.DataOptionPersister.restoreFromElement(this.element[0], options, true); // restore the .data option(s) back.
            };

            wijgrid.prototype._create = function () {
                var self = this;

                if (!this.element.is("table")) {
                    throw "invalid markup";
                }

                this.mAdjustHeaderText = true;
                this.mSplitDistanceX = 0;
                this.mSplitDistanceY = 0;
                this.mCurrentCellLocker = false;
                this._windowResizeTimer = 0;
                this.mDataOffset = 0;
                this.mScrollingState = { x: null, y: null, index: 0, scrollLeft: 0 };
                this.mRowOuterHeight = -1;
                this._initialized = false;
                this.mDestroyed = false;
                this._rendered = false;
                this._eventUID = undefined;
                ;
                this.mDataViewWrapper = undefined;
                this._originalHtml = undefined;
                this._originalAttr = undefined;
                this._originalCssText = undefined;
                this.mAutoHeight = undefined;
                this.mAutoWidth = undefined;
                this.mRenderCounter = 0;
                this.mSuperPanelHeader = undefined;
                this.mTopPagerDiv = undefined;
                this.mBottomPagerDiv = undefined;
                this.$groupArea = undefined;
                this.mUID = undefined;
                this.mWijDataView = undefined;
                this.mOuterDiv = undefined;
                this.mSketchTable = undefined;
                this.mCellFormatter = undefined;
                this.mRowStyleFormatter = undefined;
                this.mCellStyleFormatter = undefined;
                this._eventUID = wijmo.grid.getUID();
                this._spinnerActivated = false;
                this.mDeficientFilters = {};
                this.mRenderableColumns = new grid.renderableColumnsCollection();

                this.mDetails = [];
                this.mLoadingDetails = 0;

                if (this._isDetail()) {
                    this.mMasterInfo = this.element.data(wijgrid.JQDATA_MASTER_INFO_KEY);
                    this.element.removeData(wijgrid.JQDATA_MASTER_INFO_KEY);
                    this.mIgnoreSizing = true;
                }

                // Note: the data options (grid + details) are empty on this stage (see _createWidget() method)
                this.options = $.extend(true, {}, this.options); // jQuery UI 1.9.0 fix

                if ($.isFunction(window["wijmoASPNetParseOptions"])) {
                    window["wijmoASPNetParseOptions"](this.options);
                }

                wijmo.grid.DataOptionPersister.restoreFromElement(this.element[0], this.options); // restore the .data option(s)

                // enable touch support:
                if (window.wijmoApplyWijTouchUtilEvents) {
                    $ = window.wijmoApplyWijTouchUtilEvents($);
                }

                this._initialized = false;
                this.mDestroyed = false;

                // culture
                this.mClosestCulture = $.wijGetCulture(this.options.culture, this.options.cultureCalendar);

                // initialize data
                this.mDataViewWrapper = new wijmo.grid.dataViewWrapper(this);

                this._originalHtml = this.element.html(); // store original html. Will be restored in the destroy() method.
                this._originalAttr = {};
                this._originalCssText = this.element[0].style.cssText;

                this.element.addClass(wijgrid.CSS.root);
                this.element.wrap("<div class=\"" + this.options.wijCSS.widget + " " + wijgrid.CSS.wijgrid + " " + this.options.wijCSS.wijgrid + " " + wijgrid.CSS.outerDivMarker + " " + this.options.wijCSS.content + " " + this.options.wijCSS.cornerAll + "\"></div>"); // outer div
                this.mOuterDiv = this.element.parent();

                var styleHeight = this.element[0].style.height, styleWidth = this.element[0].style.width;

                if (this._isDetail()) {
                    var opt = this.options;
                    styleHeight = opt.height || (opt.height === 0) ? opt.height + "" : styleHeight;
                    styleWidth = opt.width || (opt.width === 0) ? opt.width + "" : styleWidth;
                }

                if (styleHeight) {
                    this.mOuterDiv.css("height", styleHeight);
                }

                if (styleWidth) {
                    this.mOuterDiv.css("width", styleWidth);
                }

                this.mAutoHeight = (styleHeight == "" || styleHeight == "auto");
                this.mAutoWidth = (styleWidth == "" || styleWidth == "auto");
                this.mResizeOnWindowResize = this.mAutoHeight || ((styleHeight + "").indexOf("%") > 0) || this.mAutoWidth || ((styleWidth + "").indexOf("%") > 0);

                this.element.css({ "height": "", "width": "" });

                if (this.options.disabled) {
                    this.disable();
                }

                // formatters
                this.mCellFormatter = new wijmo.grid.cellFormatterHelper();
                this.mRowStyleFormatter = new wijmo.grid.rowStyleFormatterHelper(this);
                this.mCellStyleFormatter = new wijmo.grid.cellStyleFormatterHelper(this);

                // * set bounds
                this._viewPortBounds({ start: 0, end: 0, startX: 0, endX: 0 });

                if (this._allowVVirtualScrolling()) {
                    this._viewPortBounds().start = this.mScrollingState.index; // == 0 by default.

                    if (this._serverSideVirtualScrolling()) {
                        this.mDataOffset = this.mScrollingState.index;
                    }
                }

                // set bounds *
                // wijObservable
                if (this.element.wijAddVisibilityObserver) {
                    this.element.wijAddVisibilityObserver(function (e) {
                        if (self._initialized && !self.mDestroyed && (e.target !== self.mOuterDiv[0]) && self.element.is(":visible")) {
                            self.setSize();
                        }
                    }, "wijgrid");
                }

                this._winOrientation = wijmo.grid.getWindowOrientation();

                this.mRenderCounter = 0;
            };

            wijgrid.prototype._destroy = function () {
                var self = this;

                try  {
                    if (this.element.wijRemoveVisibilityObserver) {
                        this.element.wijRemoveVisibilityObserver();
                    }

                    this._view().dispose();

                    this._detachEvents(true);

                    if (this._resizerui) {
                        this._resizerui.dispose();
                        this._resizerui = null;
                    }

                    if (this._frozenerui) {
                        this._frozenerui.dispose();
                        this._frozenerui = null;
                    }

                    if (this._selectionui) {
                        this._selectionui.dispose();
                        this._selectionui = null;
                    }

                    if (this._dragndropui) {
                        this._dragndropui.dispose();
                        this._dragndropui = null;
                    }

                    this.mDataViewWrapper.dispose();

                    if (this.mCellFormatter) {
                        this.mCellFormatter.dispose();
                        this.mCellFormatter = null;
                    }

                    // cleanup $data
                    wijmo.grid.remove$dataByPrefix(this.element, this.mDataPrefix);

                    // ** restore original content
                    // restore content and destroy children widgets + data.
                    this.element.insertBefore(this.mOuterDiv);
                    this.mOuterDiv.remove();
                    this.element.html(this._originalHtml);

                    // restore attributes
                    $.each(this._originalAttr, function (key, value) {
                        if (value === undefined) {
                            self.element.removeAttr(key);
                        } else {
                            self.element.attr(key, value);
                        }
                    });

                    this.element.removeClass(wijmo.grid.wijgrid.CSS.root);
                    this.element[0].style.cssText = this._originalCssText; // restore style properties
                    // restore original content **
                } finally {
                    this.mDestroyed = true;
                }
            };

            wijgrid.prototype._init = function () {
                this.mSuperPanelHeader = null;
                this.mTopPagerDiv = null;
                this.mBottomPagerDiv = null;
                this.$groupArea = null;

                this._prevHoveredSketchRowIndex = -1;

                // culture
                this.mClosestCulture = $.wijGetCulture(this.options.culture, this.options.cultureCalendar);

                if (!this.options.data) {
                    if (!this.mTHead) {
                        this.mTHead = this._readTableSection(this.element, 1 /* head */, this.options.readAttributesFromData);
                    }

                    if (!this.mTFoot) {
                        this.mTFoot = this._readTableSection(this.element, 3 /* foot */, this.options.readAttributesFromData);
                    }
                }

                this._initialized = this._initialized || false; // to avoid reinitialization.

                if (this._isDetail()) {
                    this._validateRelation(this.options.relation);
                }

                this.ensureControl(true);
            };

            wijgrid.prototype._setOption = function (key, value) {
                var presetFunc = this["_preset_" + key], oldValue = this.options[key], optionChanged, postsetFunc;

                if (presetFunc !== undefined) {
                    value = presetFunc.apply(this, [value, oldValue]);
                }

                optionChanged = (value !== oldValue) || (key.toLowerCase() === "data") || (key.toLowerCase() === "columns"); // same reference, handle a situation when the option.columns array was modifed directly. (TFS issue #41296)

                //$.Widget.prototype._setOption.apply(this, arguments); note: there is no dynamic linkage between the arguments and the formal parameter values when strict mode is used
                _super.prototype._setOption.apply(this, [key, value]); // update this.options

                if (optionChanged) {
                    postsetFunc = this["_postset_" + key];
                    if (postsetFunc !== undefined) {
                        postsetFunc.apply(this, [value, oldValue]);
                    }
                }
            };

            // * override
            // * public
            /** Returns a one-dimensional array of widgets bound to visible column headers.
            * @example
            * var colWidgets = $("#element").wijgrid("columns");
            * @remarks
            * wijgrid columns are represented as widgets. This method returns a one-dimensional array of widgets that are bound to visible column headers.
            *
            * The column widget is initiated with values taken from the corresponding item in the wijgrid.options.columns array. However, the options of a column widget instance reference not the original object but a copy created by the widget factory. Due to that, changes to the wijgrid.options.columns options are not automatically propagated to the column widget options and vice versa.
            * To solve this issue, the wijgrid synchronized the column widget option values with the source items. This synchronization occurs inside the ensureControl() method which is automatically called at each action requiring the wijgrid to enter.
            *
            * Still, there is a drawback. For example, a user may want to filter wijgrid data from user code as in this sample:
            *
            *	$("#element").wijgrid("option", "columns")[0].filterValue = "newValue";
            *	$("#element").wijgrid("ensureControl", true); // make wijgrid re-shape data and re-render.
            *
            * In the sample above, nothing will happen since at synchronization user changes will be ignored.You need to change the filterValue of a column widget. This is what the columns() method is for:
            *
            *	$("#element").wijgrid("columns")[0].options.filterValue = "newValue";
            *	$("#element").wijgrid("ensureControl", true); // make wijgrid re-shape data and re-render.
            *
            * Here's the best way to change the filterValue:
            *
            *	$("#element").wijgrid("columns")[0].option("filterValue", "newValue"); // column widget handles all the needful.
            *
            * @returns {Object[]} A one-dimensional array of widgets bound to visible column headers.
            */
            wijgrid.prototype.columns = function () {
                return this.mVisibleLeaves || [];
            };

            wijgrid.prototype._setColumns = function (value) {
                this.mVisibleLeaves = value;
            };

            /** @ignore */
            wijgrid.prototype.currentCell = function (a, b, changeSelection) {
                var currentCell, view = this._view(), rows = this._rows();

                if (arguments.length === 0) {
                    currentCell = this._currentCell();
                    if (!currentCell) {
                        this._currentCell(currentCell = wijmo.grid.cellInfo.outsideValue);
                    }
                    return currentCell;
                } else {
                    //currentCell = (arguments.length === 1)
                    //	? (<wijmo.grid.cellInfo>a)._clone()
                    //	: new wijmo.grid.cellInfo(<number>a, <number>b);
                    currentCell = (typeof (a) !== "number") ? a._clone() : new wijmo.grid.cellInfo(a, b);

                    if (!currentCell.isEqual(wijmo.grid.cellInfo.outsideValue)) {
                        if (!currentCell._isValid()) {
                            throw "invalid arguments";
                        }

                        currentCell._clip(this._getDataCellsRange(0 /* sketch */));

                        if (currentCell.rowIndex() >= 0) {
                            var rowInfo = view._getRowInfoBySketchRowIndex(currentCell.rowIndex());
                            if (!rowInfo || !(rowInfo.type & 2 /* data */)) {
                                return;
                            }
                        }
                    }

                    currentCell._setGridView(this);

                    this._changeCurrentCell(null, currentCell, { changeSelection: changeSelection || false, setFocus: false });

                    return this._currentCell();
                }
            };

            /** Gets an array of underlying data.
            * @example
            * var data = $("#element").wijgrid("data");
            * @returns {object[]} An array of underlying data.
            */
            wijgrid.prototype.data = function () {
                //return this._dataViewWrapper.dataView()();
                return this.mDataViewWrapper.dataView().getSource();
            };

            /** Gets an underlying wijdataview instance.
            * @example
            * var dataView = $("#element").wijgrid("dataView");
            * @returns {wijmo.data.IDataView} An underlying wijdataview instance.
            */
            wijgrid.prototype.dataView = function () {
                return this.mDataViewWrapper.dataView();
            };

            wijgrid.prototype._isRoot = function () {
                return !this._isDetail();
            };

            wijgrid.prototype._isDetail = function () {
                return this.options._isDetail === true;
            };

            wijgrid.prototype._clearDetails = function () {
                if (this.mDetails) {
                    this.mDetails.splice(0, this.mDetails.length);
                }
            };

            /** Returns an array which consists of hierarchy nodes in wijgrid. */
            wijgrid.prototype.details = function () {
                if (!this.mDetails) {
                    this.mDetails = [];
                }

                return this.mDetails;
            };

            /** Re-renders wijgrid.
            * @example
            * $("#element").wijgrid("doRefresh");
            * @param {Object} userData Infrastructure, not intended to be used by user.
            */
            wijgrid.prototype.doRefresh = function (userData) {
                var _this = this;
                if (!$.isPlainObject(userData)) {
                    userData = {};
                }

                var self = this, virtualRefresh = userData && userData.virtualScrollData;

                if (!this._initialized) {
                    try  {
                        this._prepareColumns(this.options.columns, this.options.columnsAutogenerationMode, this.mDataViewWrapper.getFieldsInfo(), true, true); // prepare static and dynamic columns
                    } catch (e) {
                        throw e;
                    } finally {
                        //ownerise the column for bug 16936, 17079
                        this._initialized = true;
                    }
                }

                if (!virtualRefresh) {
                    this._rebuildLeaves(); // build leaves, visible leaves, set dataIndex etc

                    var dataSlice = grid.lazy(this.mDataViewWrapper.data, this.mDataViewWrapper), dataView = this.mDataViewWrapper.dataView();

                    var totalsRequest = this._prepareTotalsRequest();
                    if (totalsRequest.length) {
                        $.each(this._leaves(), function (i, column) {
                            column.options._totalsValue = (dataSlice().totals) ? dataSlice().totals[column.options.dataKey] : undefined;
                        });
                    }

                    // this._setPageCount(dataSlice);
                    if (dataView.count()) {
                        var leaves = this._leaves();
                        var lazyTable = new wijmo.grid.LazySketchTable({
                            count: function () {
                                return dataView.count();
                            },
                            getRange: function (start, count, dest, offset) {
                                for (var i = 0; i < count; i++) {
                                    var index = start + i;
                                    var dataItem = dataView.item(index);
                                    dest[offset + i] = _this._buildSketchRow(_this.mDataViewWrapper._wrapDataItem(dataItem, index), leaves);
                                }
                            }
                        });
                        if (this._hasGrouping() || this._hasMerging() || this._hasDetail()) {
                            lazyTable.ensureNotLazy();
                        }
                        this.mSketchTable = lazyTable;
                    } else {
                        this.mSketchTable = new wijmo.grid.SketchTable();
                        var emptyData = dataSlice().emptyData;
                        if (emptyData) {
                            $.each(emptyData, function (i, item) {
                                self.mSketchTable.add(self._buildSketchRowEmptyDataItem(item, _this._leaves(), i === emptyData.length - 1));
                            });
                        }
                    }
                }

                this._onRendering(userData);

                if (!virtualRefresh) {
                    this._refresh(userData);
                } else {
                    this._refreshVirtual(userData);
                }

                if (userData && $.isFunction(userData.beforeOnRendered)) {
                    userData.beforeOnRendered.apply(this, [userData]);
                }

                var view = this._view();
                if (this.mEditSkechRowIndex >= 0 && (view._isRowRendered(this.mEditSkechRowIndex) >= 0)) {
                    var rowInfo = view._getRowInfoBySketchRowIndex(this.mEditSkechRowIndex);
                    if (rowInfo && (rowInfo.state & 16 /* editing */)) {
                        view._makeRowEditable(rowInfo);
                    }
                }

                this._onRendered(userData);

                if (userData && $.isFunction(userData.afterRefresh)) {
                    userData.afterRefresh.apply(this, [userData]);
                }
            };

            /** Puts the current cell into edit mode, as long as the editingMode options is set to "cell".
            * @example
            * $("#element").wijgrid({}
            *		editingMode: "cell",
            *		currentCellChanged: function (e, args) {
            *			if ($(e.target).wijgrid("option", "isLoaded")) {
            *				window.setTimeout(function () {
            *					$(e.target).wijgrid("beginEdit");
            *				}, 100);
            *			}
            *		}
            * });
            * @returns {Boolean} True if the cell is successfully put into edit mode, otherwise false.
            */
            wijgrid.prototype.beginEdit = function () {
                if (!this._allowCellEditing()) {
                    throw "Can be used only if the editingMode option is set to \"cell\".";
                }

                return this._beginEditInternal(null);
            };

            /** Finishes editing the current cell.
            * @example
            * // endEdit is being called from within the saveChanges function
            * function saveChanges() {
            *		$("#element").wijgrid("endEdit");
            * }
            * functon cancelChanges() {
            *		$("#element").wijgrid("endEdit", true);
            * }
            * @param {Boolean} reject An optional parameter indicating whether changes will be rejected (true) or commited (false). The default value is false.
            * @returns {Boolean} True if the editing was finished successfully, othewise false.
            */
            wijgrid.prototype.endEdit = function (reject) {
                if (typeof reject === "undefined") { reject = false; }
                return this._endEditInternal(null, reject);
            };

            /** Starts editing of the specified row, can only be used when the editingMode option is set to "row".
            * @example
            * $("#element").wijgrid("editRow", 0);
            * @param {Number} dataItemIndex Determines the data item to edit.
            */
            wijgrid.prototype.editRow = function (dataItemIndex) {
                if (this.options.editingMode !== "row") {
                    throw "Can be used only if the editingMode option is set to \"row\".";
                }

                if (this.mEditSkechRowIndex >= 0) {
                    this.cancelRowEditing(); // only one row can be edited at a time.
                }

                if (dataItemIndex >= 0) {
                    var sketchRowIndex = -1, sketchRow;

                    for (var i = 0; i < this.mSketchTable.count() && sketchRowIndex < 0; i++) {
                        sketchRow = this.mSketchTable.row(i);

                        if (sketchRow.isDataRow() && ((sketchRow.dataItemIndex()) === dataItemIndex)) {
                            sketchRowIndex = i;
                        }
                    }

                    if (sketchRowIndex >= 0) {
                        var view = this._view();

                        this.mEditSkechRowIndex = sketchRowIndex;

                        sketchRow.renderState |= 16 /* editing */;

                        if (view._isRowRendered(this.mEditSkechRowIndex) >= 0) {
                            var row = view._getRowInfoBySketchRowIndex(this.mEditSkechRowIndex, false);

                            row.state |= 16 /* editing */; // ??

                            view._removeBodyRow(row.sectionRowIndex, true); // delete an exisiting row

                            var newRow = view._insertBodyRow(sketchRow, row.sectionRowIndex, row.dataItemIndex, row.virtualDataItemIndex, this.mEditSkechRowIndex);
                            newRow.dataRowIndex = row.dataRowIndex;

                            if (this._hasMerging()) {
                                this._view()._rebuildOffsets();
                            }

                            view._makeRowEditable(newRow);

                            this.selection()._ensureSelectionInRow(this.mEditSkechRowIndex);
                        }
                    }
                }
            };

            /**
            * Exports the grid to a specified format.
            * The export method only works when wijmo.exporter.gridExport's reference is on the page.
            * @remarks Possible exported types are: xls, xlsx, csv, pdf,
            * @param {string|Object} exportSettings
            * 1.The name of the exported file.
            * 2.Settings of exporting, should be conformed to wijmo.exporter.GridExportSetting
            * @param {string} type The type of the exported file.
            * @param {object} settings The export setting.
            * @param {string} serviceUrl The export service url.
            * @example
            * $("#element").wijgrid("exportGrid", "grid", "csv");
            */
            wijgrid.prototype.exportGrid = function (exportSettings, type, settings, serviceUrl) {
            };

            /** Finishes editing and updates the datasource.
            * @example
            * $("#element").wijgrid("updateRow");
            */
            wijgrid.prototype.updateRow = function () {
                if (this.mEditSkechRowIndex >= 0) {
                    var dataView = wijmo.grid.asEditableDataView(this.mDataViewWrapper.dataView()), errorOccurs = false;

                    if (!dataView) {
                        throw "The provided DataView doesn't supports the editing operation.";
                    }

                    try  {
                        var sketchRow = this.mSketchTable.row(this.mEditSkechRowIndex), view = this._view();

                        if (!sketchRow || !sketchRow.isDataRow() || !(sketchRow.renderState & 16 /* editing */)) {
                            throw "Invalid row";
                        }

                        if (this._view()._isRowRendered(this.mEditSkechRowIndex) >= 0) {
                            var row = view._getRowInfoBySketchRowIndex(this.mEditSkechRowIndex, false);

                            // ** get the new values and update an underlying data source
                            var visibleLeaves = this._visibleLeaves(), cells = [], cellEditor = new wijmo.grid.cellEditorHelper();

                            for (var i = 0; i < visibleLeaves.length; i++) {
                                var column = visibleLeaves[i];

                                if ((column instanceof grid.c1field) && !column.options.readOnly) {
                                    var $cell = row.$rows.children("td, th").eq(i);

                                    if ($cell.length) {
                                        var state = view._changeCellRenderState($cell, 0 /* none */, true);

                                        if (state & 16 /* editing */) {
                                            var cellInfo = view.getAbsoluteCellInfo($cell[0], true), updateRes = cellEditor.updateCell(this, cellInfo, null, false);

                                            if (!(updateRes & 2 /* success */)) {
                                                errorOccurs = true;
                                                return;
                                            }

                                            if (!(updateRes & 8 /* notEdited */)) {
                                                cells.push(cellInfo);
                                            }
                                        }
                                    }
                                }
                            }

                            for (var i = 0; i < cells.length; i++) {
                                cellEditor.cellEditEnd(this, cells[i], null);
                            }

                            // collect new values and update underlying data source **
                            // ** no errors, update DOM **
                            sketchRow.renderState &= ~16 /* editing */;

                            row.state &= ~16 /* editing */; // ??
                            view._removeBodyRow(row.sectionRowIndex, true); // delete an exisiting row

                            var newRow = view._insertBodyRow(sketchRow, row.sectionRowIndex, row.dataItemIndex, row.virtualDataItemIndex, this.mEditSkechRowIndex);
                            newRow.dataRowIndex = row.dataRowIndex;

                            this.selection()._ensureSelectionInRow(this.mEditSkechRowIndex);
                        } else {
                            sketchRow.renderState &= ~16 /* editing */;
                        }
                    } finally {
                        if (!errorOccurs) {
                            this.mEditSkechRowIndex = -1;
                        }
                    }
                }
            };

            /** Discards changes and finishes editing of the edited row.
            * @example
            * $("#element").wijgrid("cancelRowEditing");
            */
            wijgrid.prototype.cancelRowEditing = function () {
                if (this.mEditSkechRowIndex >= 0) {
                    try  {
                        var sketchRow = this.mSketchTable.row(this.mEditSkechRowIndex), view = this._view();

                        if (!sketchRow || !sketchRow.isDataRow() || !(sketchRow.renderState & 16 /* editing */)) {
                            throw "Invalid row.";
                        }

                        sketchRow.renderState &= ~16 /* editing */;

                        if (this._view()._isRowRendered(this.mEditSkechRowIndex) >= 0) {
                            var row = view._getRowInfoBySketchRowIndex(this.mEditSkechRowIndex, false);

                            row.state &= ~16 /* editing */; // ??
                            view._removeBodyRow(row.sectionRowIndex, true); // delete an exisiting row

                            var newRow = view._insertBodyRow(sketchRow, row.sectionRowIndex, row.dataItemIndex, row.virtualDataItemIndex, this.mEditSkechRowIndex);
                            newRow.dataRowIndex = row.dataRowIndex;

                            if (this._hasMerging()) {
                                this._view()._rebuildOffsets();
                            }

                            this.selection()._ensureSelectionInRow(this.mEditSkechRowIndex);
                        }
                    } finally {
                        this.mEditSkechRowIndex = -1;
                    }
                }
            };

            /** Deletes the specified row.
            * @example
            * $("#element").wijgrid("cancelRowEditing");
            * @param {Number} dataItemIndex Determines the data item to edit.
            */
            wijgrid.prototype.deleteRow = function (dataItemIndex) {
                if (dataItemIndex >= 0) {
                    var dataView = wijmo.grid.asEditableDataView(this.mDataViewWrapper.dataView());

                    if (!dataView || !dataView.canRemove()) {
                        throw "The provided DataView doesn't supports the deleting operation.";
                    }

                    this.mDataViewWrapper.ignoreChangeEvent(true);
                    dataView.remove(dataItemIndex);
                    this.mDataViewWrapper.ignoreChangeEvent(false);

                    if (!this.mDataViewWrapper.isKODataView()) {
                        this.ensureControl(true, {
                            forceDataLoad: true
                        });
                    }
                }
            };

            /** Moves the column widget options to the wijgrid options and renders the wijgrid. Use this method when you need to re-render the wijgrid and reload remote data from the datasource.
            * @example
            * // Adds a new row to the viewModel and refreshes the wijgrid
            * var len = viewModel.data().length;
            * viewModel.data.push(new Person({ ID: len, Company: "New Company" + len, Name: "New Name" + len }));
            * $("#element").wijgrid("ensureControl", true);
            * @param {Boolean} loadData Determines if the wijgrid must load data from a linked data source before rendering.
            */
            wijgrid.prototype.ensureControl = function (loadData, userData) {
                this._loading();

                if (!$.isPlainObject(userData)) {
                    userData = {
                        data: null,
                        afterRefresh: null,
                        beforeRefresh: null
                    };
                }

                if (!this._initialized) {
                    // this._prepareColumnOptions(false); // prepare static columns only (to make a proper sorting or filtering request to remote service)
                    this._prepareColumns(this.options.columns, this.options.columnsAutogenerationMode, this.mDataViewWrapper.isDataLoaded() && this.mDataViewWrapper.getFieldsInfo(), this.mDataViewWrapper.isDataLoaded(), false);

                    if (!this.mDataViewWrapper.isOwnDataView()) {
                        // map sorting\ filtering\ paging settings from external dataView to the grid's options during initialization stage
                        (new wijmo.grid.settingsManager(this)).MapDVToWG();
                    }
                }

                if (this._initialized) {
                    if (userData && $.isFunction(userData.beforeRefresh)) {
                        userData.beforeRefresh.apply(this);
                    }
                }

                if (!userData || !userData.virtualScrollData) {
                    this.mAllowVVirtualScrolling = undefined;
                    this.mEditSkechRowIndex = -1;
                }

                if (loadData === true) {
                    this.mDataViewWrapper.load(userData);
                } else {
                    this.doRefresh(userData);
                    this._loaded();
                }
            };

            /** Gets an instance of the wijmo.grid.cellInfo class that represents the grid's specified cell.
            * @example
            * var cellInfo = $("#element").wijgrid("getCellInfo", domCell);
            * @param {Object} domCell A HTML DOM Table cell object
            * @returns {wijmo.grid.cellInfo} Object that represents a cell of the grid.
            */
            wijgrid.prototype.getCellInfo = function (domCell) {
                var cellInfo = null;

                if (domCell && (domCell = this._findUntilOuterDiv(domCell, { td: true, th: true }))) {
                    cellInfo = this._view().getAbsoluteCellInfo(domCell, false);
                }

                return cellInfo;
            };

            /** Returns a one-dimensional array of filter operators which are applicable to the specified data type.
            * @example
            * var operators = $("#element").wijgrid("getFilterOperatorsByDataType", "string");
            * @param {String} dataType Specifies the type of data to which you apply the filter operators. Possible values are: "string", "number", "datetime", "currency" and "boolean".
            * @returns {wijmo.grid.IFilterOperator[]} A one-dimensional array of filter operators.
            */
            wijgrid.prototype.getFilterOperatorsByDataType = function (dataType) {
                return (new wijmo.grid.filterOperatorsCache(this)).getByDataType(dataType || "string");
            };

            /** Gets the number of pages.
            * @example
            * var pageCount = $("#element").wijgrid("pageCount");
            * @returns {Number} The number of pages.
            */
            wijgrid.prototype.pageCount = function () {
                if (this._customPagingEnabled()) {
                    return Math.ceil(this.options.totalRows / this.options.pageSize) || 1;
                }

                return this.options.allowPaging ? this.mDataViewWrapper.dataView().pageCount() : 1;
            };

            wijgrid.prototype._closestCulture = function () {
                return this.mClosestCulture;
            };

            wijgrid.prototype._serverShaping = function () {
                // used to support asp.net C1GridView
                return false;
            };

            wijgrid.prototype._pageIndexForDataView = function () {
                /** Infrastructure */
                return this.options.pageIndex;
            };

            /** Sets the size of the grid using the width and height parameters.
            * @example
            * $("#element").wijgrid("setSize", 200, 200);
            * @param {String|Number} width Determines the width of the grid.
            * @param {String|Number} height Determines the height of the grid.
            */
            wijgrid.prototype.setSize = function (width, height, rowsToAdjust, resizeDetails) {
                if (typeof resizeDetails === "undefined") { resizeDetails = true; }
                if (!this._rendered || this.mIgnoreSizing) {
                    return;
                }

                var view = this._view(), scrollValue = null, outerDiv = this.mOuterDiv, visibleLeaves = this._visibleLeaves(), leavesWithFilter = [], ieLT9 = $.browser && $.browser.msie && ($.browser.version < 9);

                try  {
                    if (ieLT9) {
                        wijmo.grid.wijgrid.IGNORE_WIN_RESIZE = true; // #72351
                    }

                    if (view && view.getScrollValue) {
                        scrollValue = view.getScrollValue();
                    }

                    if (width || (width === 0)) {
                        this.mAutoWidth = false;
                        outerDiv.width(width);
                    }

                    if (height || (height === 0)) {
                        this.mAutoHeight = false;
                        outerDiv.height(height);
                    }

                    view._resetWidth();

                    this._hideAllFilterDropDownLists();

                    // recalculate sizes
                    if (this._allowHVirtualScrolling()) {
                        // re-render grid completely (#106452)
                        this._resetScrollState();
                        this.doRefresh();
                    } else {
                        this._setSizeInternal(scrollValue, rowsToAdjust, resizeDetails);
                    }
                } finally {
                    wijmo.grid.wijgrid.IGNORE_WIN_RESIZE = false;
                }
            };

            wijgrid.prototype._setSizeWithoutDetails = function () {
                var old = this._ignoreSizing();
                this._ignoreSizing(false);
                this.setSize(undefined, undefined, undefined, false);
                this._ignoreSizing(old);
            };

            wijgrid.prototype._setSizeInternal = function (scrollValue, rowsToAdjust, resizeDetails) {
                if (typeof resizeDetails === "undefined") { resizeDetails = true; }
                if (!this._rendered) {
                    return;
                }

                if (this._isDetail() && this.mIgnoreSizing) {
                    this.element.width("100%"); // just stretch the detail grid within the parent's cell.
                }

                if (this.mIgnoreSizing) {
                    return;
                }

                if (resizeDetails) {
                    this._resetDetailsSize();
                }

                this._view().updateSplits(scrollValue, rowsToAdjust);
                this._UIFrozener().refresh();

                if (resizeDetails && this.mLoadingDetails === 0) {
                    var dtls = this.details();
                    for (var i = 0; i < dtls.length; i++) {
                        var d = dtls[i].grid();

                        if (d) {
                            d._ignoreSizing(false);
                            d.setSize();
                            d._ignoreSizing(true);
                        }
                    }
                }
            };

            wijgrid.prototype._resetDetailsSize = function () {
                if (this._rendered && this.mLoadingDetails === 0) {
                    var dtls = this.details();

                    for (var i = 0; i < dtls.length; i++) {
                        var detailGrid = dtls[i].grid();
                        if (detailGrid) {
                            detailGrid._view()._resetWidth();
                            detailGrid._resetDetailsSize();
                        }
                    }
                }
            };

            /** Gets an object that manages selection in the grid.
            * @example
            * // Use the row index to add the row to the selection object
            * var selection = $("#element").wijgrid("selection");
            * selection.addRows(2);
            * @remarks
            * See the description of the wijmo.grid.selection class for more details.
            * @returns {wijmo.grid.selection} Object that manages selection in the grid.
            */
            wijgrid.prototype.selection = function () {
                if (!this.mSelection) {
                    this.mSelection = new wijmo.grid.selection(this);
                }
                return this.mSelection;
            };

            // * public
            wijgrid.prototype._ignoreSizing = function (value) {
                if (arguments.length) {
                    this.mIgnoreSizing = value;
                }

                return this.mIgnoreSizing;
            };

            wijgrid.prototype._masterInfo = function () {
                return this.mMasterInfo;
            };

            wijgrid.prototype._master = function () {
                return this.mMasterInfo ? this.mMasterInfo.master : null;
            };

            wijgrid.prototype._validateRelation = function (r) {
                if (!r || !r.length) {
                    throw "The relation option must be defined.";
                }

                for (var i = 0; i < r.length; i++) {
                    if (!r[i].detailDataKey || !r[i].masterDataKey) {
                        throw "Both detailDataKey and masterDataKey properties must be defined.";
                    }
                }
            };

            wijgrid.prototype._topMaster = function () {
                var master = this, mi;

                while (mi = master._masterInfo()) {
                    master = mi.master;
                }

                return master;
            };

            wijgrid.prototype._leaves = function () {
                if (!this.mLeaves) {
                    this.mLeaves = [];
                }

                return this.mLeaves;
            };

            wijgrid.prototype._visibleLeaves = function () {
                if (!this.mVisibleLeaves) {
                    this.mVisibleLeaves = [];
                }

                return this.mVisibleLeaves;
            };

            wijgrid.prototype._renderedLeaves = function () {
                if (!this.mRenderedLeaves) {
                    this.mRenderedLeaves = [];
                }

                return this.mRenderedLeaves;
            };

            wijgrid.prototype._virtualLeaves = function () {
                if (!this.mVirtualLeaves) {
                    this.mVirtualLeaves = [];
                }

                return this.mVirtualLeaves;
            };

            wijgrid.prototype._allColumns = function () {
                if (!this.mAllColumns) {
                    this.mAllColumns = [];
                }

                return this.mAllColumns;
            };

            wijgrid.prototype._findInstance = function (column) {
                if (column) {
                    return this._allColumns()[column._travIdx] || null;
                }

                return null;
            };

            wijgrid.prototype._currentCell = function (value) {
                if (!arguments.length) {
                    return this.mCurrentCell;
                }

                this.mCurrentCell = value;
            };

            wijgrid.prototype._groupAreaColumns = function () {
                if (!this.mGroupAreaColumns) {
                    this.mGroupAreaColumns = [];
                }

                return this.mGroupAreaColumns;
            };

            wijgrid.prototype._tHead = function () {
                return this.mTHead;
            };

            wijgrid.prototype._onDataViewCurrentPositionChanged = function (e, args) {
                var cellInfo = this._currentCellFromDataView(this.currentCell().cellIndex());

                // move currentCell to the new position
                cellInfo = this.currentCell(cellInfo, null, true);
            };

            wijgrid.prototype._resetColumns = function () {
                wijmo.grid.traverse(this.options.columns, function (column, columns) {
                    if (column._dynamic) {
                        // remove autogenerated columns
                        var idx = $.inArray(column, columns);
                        if (idx >= 0) {
                            columns.splice(idx, 1);
                        }
                    } else {
                        // restore original values
                        column.dataKey = column._originalDataKey;
                        column.headerText = column._originalHeaderText;
                    }
                });

                this._initialized = false; // to generate columns when doRefresh() or ensureControl() methods will be called
            };

            wijgrid.prototype._resetDataProperitesOnFilterChanging = function () {
                this._resetDataProperties();
                this._resetVerticalBounds();
            };

            wijgrid.prototype._resetDataProperties = function () {
                this.options.pageIndex = 0;
            };

            wijgrid.prototype._resetVerticalBounds = function () {
                var bounds = this._viewPortBounds();

                //bounds.start = bounds.end = 0;
                bounds.start = 0; // #52058: reset the .start property only. Let wijgrid to update the .end property when the underlying data will be refreshed actually.

                this.mScrollingState.index = 0;
                this.mScrollingState.y = 0;
            };

            wijgrid.prototype._resetScrollState = function () {
                // re-render grid completely
                if (this.mScrollingState) {
                    this.mScrollingState.scrollLeft = 0;
                    this.mScrollingState.x = 0;
                }
            };

            wijgrid.prototype._onDataViewLoading = function () {
                this._clearDetails(); // clear subtree.
                this._activateSpinner(); // if data loading proccess was triggered outside the wijgrid.
                this._trigger("dataLoading");
            };

            wijgrid.prototype._onDataViewReset = function (userData, resetColumns) {
                this.mEditSkechRowIndex = -1; // #49039

                if (this.mCurrentCellLocker) {
                    if (!(this._serverSideVirtualScrolling() && userData && userData.virtualScrollData)) {
                        this._resetVerticalBounds();
                    }
                    this.mCurrentCellLocker = false;
                }

                (new wijmo.grid.settingsManager(this)).MapDVToWG();

                this._trigger("dataLoaded");

                if (resetColumns) {
                    this._resetColumns();
                }

                this.doRefresh(userData);

                this._loaded();
            };

            wijgrid.prototype._onDataViewLoaded = function () {
            };

            wijgrid.prototype._loading = function () {
                if (!this._isDetail()) {
                    this._activateSpinner();
                }

                if (!this._isRoot()) {
                    var master = this._masterInfo().master;
                    master._onDetailLoading(this);
                }

                this._trigger("loading");
            };

            wijgrid.prototype._onDetailLoading = function (detail) {
                this._topMaster()._activateSpinner();
            };

            wijgrid.prototype._loaded = function () {
                if (!(this._isRoot() && this.mLoadingDetails > 0)) {
                    this._deactivateSpinner();
                }

                if (!this._isRoot()) {
                    var master = this._masterInfo().master;
                    master._onDetailLoaded(this);
                }

                this._trigger("loaded");
            };

            wijgrid.prototype._onDetailLoaded = function (detail) {
                if (this.mLoadingDetails > 0) {
                    this.mLoadingDetails--;
                }

                // provide a detail instance to the parent's hierarchyNode
                var mi = detail._masterInfo();
                mi.master.details()[mi.dataRowIndex]._setGrid(detail);

                if (this.mLoadingDetails === 0) {
                    if (this._isRoot()) {
                        if (this._rendered) {
                            this._setSizeInternal(this.mScrollingState, undefined, true); // resize all grids starting from the top.
                            this._deactivateSpinner();
                        }
                    } else {
                        if (this._rendered) {
                            this._masterInfo().master._onDetailLoaded(this); // bubble
                        }
                    }
                }
            };

            wijgrid.prototype._buildSketchRow = function (wrappedDataItem, leaves) {
                var meta = wijmo.grid.dataViewWrapper.getMetadata(wrappedDataItem.values), sketchRow = new grid.SketchDataRow(wrappedDataItem.originalRowIndex, 1 /* rendering */, meta && meta.rowAttributes), cellAttributes = meta && meta.cellsAttributes;

                for (var i = 0, len = leaves.length; i < len; i++) {
                    var leaf = leaves[i];

                    if (leaf instanceof grid.c1field) {
                        var boundField = leaf, cellAttr = cellAttributes ? cellAttributes[boundField.options.dataKey] : null, value = this.mDataViewWrapper.getValue(wrappedDataItem.values, boundField.options.dataKey);

                        sketchRow.add(new grid.ValueCell(this.parse(leaf.options, value), cellAttr));
                    } else {
                        sketchRow.add(new grid.ValueCell(null, {}));
                    }
                }

                return sketchRow;
            };

            wijgrid.prototype._buildSketchRowEmptyDataItem = function (dataItem, leaves, isLastRow) {
                var sketchRow = new grid.SketchRow(128 /* emptyDataRow */, 1 /* rendering */, null), leavesLen = leaves.length;

                for (var i = 0, len = dataItem.length; i < len; i++) {
                    sketchRow.add(new grid.HtmlCell(dataItem[i], {
                        colSpan: (leavesLen > 0 && isLastRow) ? this._visibleLeaves().length : 1
                    }));
                }

                return sketchRow;
            };

            wijgrid.prototype._prepareColumnsStage1 = function (columns, dataLoaded, finalStage) {
                new wijmo.grid.bandProcessor().getVisibleHeight(columns, true); // set .isLeaf
            };

            wijgrid.prototype._prepareColumnsStage2 = function (columns, generationMode, fieldsInfo, dataLoaded, finalState, generateInsances) {
                var _this = this;
                if (typeof generateInsances === "undefined") { generateInsances = true; }
                wijmo.grid.traverse(columns, function (column) {
                    column._originalDataKey = column.dataKey;
                    column._originalHeaderText = column.headerText;
                });

                if (dataLoaded) {
                    wijmo.grid.columnsGenerator.generate(generationMode, fieldsInfo, columns);
                }

                wijmo.grid.setTraverseIndex(columns); // build indices (linearIdx, travIdx, parentIdx)

                if (generateInsances) {
                    this._generateColumnInstancesFromOptions(columns);
                }

                // provide headerText and footerText if not specified
                if (dataLoaded && this.mDataViewWrapper && this.mAdjustHeaderText) {
                    $.each(this._leaves(), function (index, column) {
                        var boundedToDOM = _this.mDataViewWrapper.isBoundedToDOM(), opt = column.options, cellIndex = (typeof (opt.dataKey) === "number") ? opt.dataKey : opt._leavesIdx;

                        // assume headerText options of the static columns only when using "merge" mode.
                        if ((opt.headerText === undefined) && (_this.options.columnsAutogenerationMode === "merge" || opt._dynamic)) {
                            var headerRow = _this._originalHeaderRowData();

                            if (boundedToDOM && headerRow && (cellIndex < headerRow.length)) {
                                opt.headerText = $.trim(headerRow[cellIndex]);
                            } else {
                                if (column instanceof grid.c1field) {
                                    opt.headerText = opt.dataKey + "";
                                }
                            }
                        }

                        var footerRow = _this._originalFooterRowData();
                        if (boundedToDOM && footerRow && (cellIndex < footerRow.length)) {
                            opt._footerTextDOM = $.trim(footerRow[cellIndex]);
                        }
                    });
                }
            };

            wijgrid.prototype._prepareColumns = function (columns, generationMode, fieldsInfo, dataLoaded, finalStage, generateInstances) {
                if (typeof generateInstances === "undefined") { generateInstances = true; }
                this._prepareColumnsStage1(columns, dataLoaded, finalStage);
                this._prepareColumnsStage2(columns, generationMode, fieldsInfo, dataLoaded, finalStage, generateInstances);
            };

            wijgrid.prototype._rebuildLeaves = function () {
                var tmp = [];

                this._addVirtualColumns(tmp);

                $.each(this.options.columns, function (index, item) {
                    tmp.push(item); // append columns
                });

                wijmo.grid.setTraverseIndex(tmp); // build indices (linearIdx, travIdx, parentIdx)

                // generate span table and build leaves
                this._columnsHeadersTable(new wijmo.grid.bandProcessor().generateSpanTable(tmp));

                this._generateColumnInstancesFromOptions(tmp);

                this._onLeavesCreated();
            };

            wijgrid.prototype._addVirtualColumns = function (columns) {
                if (this._showRowHeader()) {
                    columns.push(grid.c1rowheaderfield.getInitOptions());
                }

                if (this._hasDetail()) {
                    columns.push(grid.c1detailrowheaderfield.getInitOptions());
                }
            };

            wijgrid.prototype._generateColumnInstancesFromOptions = function (columns) {
                var _this = this;
                this.mAllColumns = [];
                this.mLeaves = [];
                this.mVirtualLeaves = [];
                this.mVisibleLeaves = [];
                this.mGroupedLeaves = null; // force recreating.
                this.mRenderedLeaves = [];

                var dataIndex = 0, leavesIdx = 0, visLeavesIdx = 0;

                wijmo.grid.traverse(columns, function (opt) {
                    opt._visLeavesIdx = undefined;
                    opt._leavesIdx = undefined;
                    opt._renderedIndex = undefined;

                    if (opt._isLeaf) {
                        opt._leavesIdx = leavesIdx++;

                        if (opt._parentVis) {
                            opt._visLeavesIdx = visLeavesIdx++;
                        }
                    }

                    opt.disabled = _this.options.disabled === true;

                    var instance = wijmo.grid.asColumnInstance(_this, opt);

                    _this.mAllColumns.push(instance);

                    if (instance instanceof grid.c1field) {
                        opt.dataIndex = dataIndex++;
                    }

                    if (opt._isLeaf) {
                        _this.mLeaves.push(instance);

                        if (opt._parentVis) {
                            _this.mVisibleLeaves.push(instance);

                            if (instance instanceof grid.c1rowheaderfield) {
                                _this.mVirtualLeaves.push(instance);
                            }
                        }
                    }
                });
            };

            wijgrid.prototype._onLeavesCreated = function () {
            };

            wijgrid.prototype._allowEditing = function () {
                return (this.options.allowEditing === true) || (this.options.editingMode === "cell") || (this.options.editingMode === "row");
            };

            wijgrid.prototype._allowCellEditing = function () {
                var editingMode = this.options.editingMode;

                if (editingMode === "row") {
                    return false;
                }

                return (this.options.allowEditing === true) || (editingMode === "cell");
            };

            wijgrid.prototype._allowVirtualScrolling = function () {
                return this._allowVVirtualScrolling() || this._allowHVirtualScrolling();
            };

            wijgrid.prototype._allowVVirtualScrolling = function () {
                if (this.mAllowVVirtualScrolling === undefined) {
                    var mode = this.options.scrollingSettings.virtualizationSettings.mode, allow = this.options.allowVirtualScrolling || mode === "rows" || mode === "both";

                    this.mAllowVVirtualScrolling = !this.options.allowPaging && allow && (this._lgGetStaticRowIndex() < 0) && (this._lgGetScrollMode() !== "none") && !this._hasMerging() && !this._hasDetail();
                }

                return this.mAllowVVirtualScrolling;
            };

            wijgrid.prototype._allowHVirtualScrolling = function () {
                if (this.mAllowHVirtualScrolling === undefined) {
                    var mode = this.options.scrollingSettings.virtualizationSettings.mode, allow = mode === "columns" || mode === "both";

                    this.mAllowHVirtualScrolling = allow && (this._lgGetScrollMode() !== "none") && !this._hasGrouping() && !this._hasBands() && !this._hasDetail();
                }

                return this.mAllowHVirtualScrolling;
            };

            wijgrid.prototype._headerRows = function () {
                return this._view().headerRows();
            };

            wijgrid.prototype._filterRow = function () {
                return this._view().filterRow();
            };

            wijgrid.prototype._rows = function () {
                return this._view().bodyRows();
            };

            wijgrid.prototype._localizeFilterOperators = function (locArray) {
                var self = this, helper = new wijmo.grid.filterOperatorsCache(this);

                $.each(locArray, function (i, o) {
                    if (o.name) {
                        var fop = helper.getByName(o.name);
                        if (fop) {
                            fop.displayName = o.displayName;
                        }
                    }
                });
            };

            wijgrid.prototype._KeyDownEventListener = function () {
                if (!this.mKeyDownEventListener) {
                    var view = this._view(), $fe = view && view.focusableElement();

                    if ($fe) {
                        this.mKeyDownEventListener = new grid.keyDownEventListener(this, $fe);
                    }
                }

                return this.mKeyDownEventListener;
            };

            wijgrid.prototype._UIDragndrop = function (force) {
                if (!this._dragndropui && force) {
                    this._dragndropui = new wijmo.grid.uiDragndrop(this);
                }

                return this._dragndropui;
            };

            wijgrid.prototype._UIFrozener = function (force) {
                if (!this._frozenerui || force) {
                    this._frozenerui = new wijmo.grid.uiFrozener(this);
                }

                return this._frozenerui;
            };

            wijgrid.prototype._UIResizer = function (force) {
                if (!this._resizerui && force) {
                    this._resizerui = new wijmo.grid.uiResizer(this);
                }

                return this._resizerui;
            };

            wijgrid.prototype._UISelection = function (force) {
                if (!this._selectionui && force) {
                    this._selectionui = new wijmo.grid.uiSelection(this);
                }

                return this._selectionui;
            };

            // * propeties (pre-\ post-)
            wijgrid.prototype._postset_allowColMoving = function (value, oldValue) {
                var self = this;

                $.each(this.columns(), function (idx, wijField) {
                    if (value) {
                        self._UIDragndrop(true).attach(wijField);
                    } else {
                        self._UIDragndrop(true).detach(wijField);
                    }
                });

                var groupedWidgets = this._groupAreaColumns();

                if (groupedWidgets) {
                    $.each(groupedWidgets, function (idx, wijField) {
                        if (value) {
                            self._UIDragndrop(true).attach(wijField);
                        } else {
                            self._UIDragndrop(true).detach(wijField);
                        }
                    });
                }
            };

            wijgrid.prototype._postset_allowEditing = function (value, oldValue) {
                this._postset_editingMode(this.options.editingMode, undefined);
            };

            wijgrid.prototype._postset_allowSorting = function (value, oldValue) {
                this.ensureControl(false);
            };

            wijgrid.prototype._postset_columns = function (value, oldValue) {
                this._initialized = false;
                this.ensureControl(true);
            };

            wijgrid.prototype._postset_allowPaging = function (value, oldValue) {
                this.ensureControl(true);
            };

            wijgrid.prototype._postset_freezingMode = function (value, oldValue) {
                if (this._frozenerui) {
                    this._frozenerui.refresh();
                }
            };

            wijgrid.prototype._postset_culture = function (value, oldValue) {
                this.mClosestCulture = $.wijGetCulture(this.options.culture, this.options.cultureCalendar);
                this.ensureControl(false);
            };

            wijgrid.prototype._postset_customFilterOperators = function (value, oldValue) {
                var dataView = this.mDataViewWrapper.dataView();
            };

            wijgrid.prototype._postset_data = function (value, oldValue) {
                this._resetColumns();

                // this._resetDataProperties();
                if (this.mDataViewWrapper) {
                    this.mDataViewWrapper.dispose();
                }

                this.mDataViewWrapper = new wijmo.grid.dataViewWrapper(this);

                this.ensureControl(true);
            };

            wijgrid.prototype._postset_disabled = function (value, oldValue) {
                // update children widgets
                var self = this, view = this._view();

                wijmo.grid.iterateChildrenWidgets(this.mOuterDiv, function (index, widget) {
                    if (widget !== self) {
                        widget.option("disabled", value);
                    }
                });

                // update editors (#69699)
                if ((this.mEditSkechRowIndex >= 0) && (view._isRowRendered(this.mEditSkechRowIndex) >= 0)) {
                    var row = view._getRowInfoBySketchRowIndex(this.mEditSkechRowIndex, false);
                    if (row) {
                        row.$rows.find("." + wijmo.grid.wijgrid.CSS.inputMarker).prop("disabled", value);
                    }
                }

                //
                if (view) {
                    view.ensureDisabledState();
                }
            };

            wijgrid.prototype._postset_editingMode = function (value, oldValue) {
                if (this.mKeyDownEventListener) {
                    this.mKeyDownEventListener.dispose();
                    this.mKeyDownEventListener = null;

                    this._KeyDownEventListener();
                }
            };

            wijgrid.prototype._postset_groupIndent = function (value, oldValue) {
                this.ensureControl(false);
            };

            wijgrid.prototype._postset_groupAreaCaption = function (value, oldValue) {
                var groupedColumns = this._groupedLeaves();

                if (this.$groupArea && (!groupedColumns || !groupedColumns.length)) {
                    this.$groupArea.html(value || "&nbsp;");
                }
            };

            wijgrid.prototype._postset_highlightCurrentCell = function (value, oldValue) {
                var currentCell = this.currentCell();

                if (currentCell && currentCell._isValid()) {
                    this._highlightCellPosition(currentCell, value);
                }
            };

            wijgrid.prototype._preset_pageIndex = function (value, oldValue) {
                if (grid.isNaN(value)) {
                    throw "out of range";
                }

                var pageCount = this.pageCount(), fn = function (val) {
                    if (val > pageCount - 1) {
                        val = pageCount - 1;
                    }

                    if (val < 0) {
                        val = 0;
                    }

                    return val;
                };

                value = fn(value);

                if (this.options.allowPaging && value !== oldValue) {
                    var args = { newPageIndex: value };

                    if (!this._onPageIndexChanging(args)) {
                        value = oldValue;

                        // revert wijpager's pageIndex option
                        $.each([this.mTopPagerDiv, this.mBottomPagerDiv], function (_, elem) {
                            if (elem && elem.length) {
                                var instance = elem.data("wijmo-wijpager");
                                if (instance) {
                                    instance.options.pageIndex = value;
                                }
                            }
                        });
                    } else {
                        value = fn(args.newPageIndex);
                    }
                }

                return value;
            };

            wijgrid.prototype._postset_pageIndex = function (value, oldValue) {
                if (this.options.allowPaging) {
                    var args = { newPageIndex: value };

                    if (this._customPagingEnabled()) {
                        this._onPageIndexChanged(args); // Allow user the ability to load a new data and refresh the grid.
                    } else {
                        this.ensureControl(true, {
                            afterRefresh: function () {
                                this._onPageIndexChanged(args);
                            }
                        });
                    }
                }
            };

            wijgrid.prototype._preset_pageSize = function (value, oldValue) {
                if (grid.isNaN(value)) {
                    throw "out of range";
                }

                if (value <= 0) {
                    value = 1;
                }

                return value;
            };

            wijgrid.prototype._postset_pageSize = function (value, oldValue) {
                this._resetDataProperties();

                if (this.options.allowPaging && !this._customPagingEnabled()) {
                    this.ensureControl(true);
                }
            };

            wijgrid.prototype._postset_pagerSettings = function (value, oldValue) {
                this.ensureControl(false);
            };

            wijgrid.prototype._postset_rowHeight = function (value, oldValue) {
                this.mRowOuterHeight = -1;
                this.ensureControl(false);
            };

            wijgrid.prototype._postset_scrollMode = function (value, oldValue) {
                this.ensureControl(false);
            };

            wijgrid.prototype._preset_scrollingSettings = function (value, oldValue) {
                return $.extend(true, {}, $.wijmo.wijgrid.prototype.options.scrollingSettings, value);
            };

            wijgrid.prototype._postset_selectionMode = function (value, oldValue) {
                var selection = this.selection(), currentCell = this.currentCell(), hasSelection = this.selection().selectedCells().length();

                selection.beginUpdate();

                selection.clear();

                if (currentCell && currentCell._isValid() && hasSelection) {
                    selection._selectRange(new wijmo.grid.cellInfoRange(currentCell, currentCell), false, false, 0 /* none */, null);
                }

                selection.endUpdate();

                this._view().toggleDOMSelection(value === "none"); // disable or enable DOM selection
            };

            wijgrid.prototype._postset_showFilter = function (value, oldValue) {
                this.ensureControl(false);
            };

            wijgrid.prototype._postset_showGroupArea = function (value, oldValue) {
                this.ensureControl(false);
            };

            wijgrid.prototype._postset_showRowHeader = function (value, oldValue) {
                this.ensureControl(false);
            };

            wijgrid.prototype._postset_staticRowIndex = function (value, oldValue) {
                if (this._freezingAllowed()) {
                    this.options.scrollingSettings.staticRowIndex = value;
                    this.ensureControl(false);
                }
            };

            wijgrid.prototype._postset_staticColumnIndex = function (value, oldValue) {
                if (this._freezingAllowed()) {
                    this.options.scrollingSettings.staticColumnIndex = value;
                    this.ensureControl(false);
                }
            };

            wijgrid.prototype._postset_allowVirtualScrolling = function (value, oldValue) {
                this.ensureControl(false);
            };

            wijgrid.prototype._preset_allowVirtualScrolling = function (value, oldValue) {
                if (grid.isNaN(value) || value < 0) {
                    throw "out of range";
                }

                return value;
            };

            // * propeties (pre-\ post-)
            // * private
            wijgrid.prototype._activateSpinner = function () {
                //For fix the issue#151745.
                //if (!this._spinnerActivated)
                if (!this._spinnerActivated && !this._topMaster()._spinnerActivated) {
                    var defCSS = wijmo.grid.wijgrid.CSS, wijCSS = this.options.wijCSS, loadingText = this.mOuterDiv.append("<div class=\"" + defCSS.spinnerMarker + " " + defCSS.loadingOverlay + " " + wijCSS.wijgridLoadingOverlay + " " + wijCSS.overlay + "\"></div>" + "<span class=\"" + defCSS.spinnerMarker + " " + defCSS.loadingText + " " + wijCSS.wijgridLoadingText + " " + wijCSS.content + " " + wijCSS.cornerAll + "\">" + "<span class=\"" + defCSS.spinnerMarker + " " + wijCSS.icon + " " + wijCSS.iconClock + "\"></span>" + this.options.loadingText + "</span>").find("> ." + defCSS.loadingText);

                    loadingText.position({
                        my: "center",
                        at: "center center",
                        of: this.mOuterDiv,
                        collision: "none"
                    });

                    this._spinnerActivated = true;
                }
            };

            wijgrid.prototype._customPagingEnabled = function () {
                return this.options.allowPaging && this.options.totalRows >= 0;
            };

            wijgrid.prototype._deactivateSpinner = function () {
                if (this._spinnerActivated) {
                    try  {
                        var defCSS = wijmo.grid.wijgrid.CSS;

                        this.mOuterDiv.children("." + defCSS.spinnerMarker).remove();
                    } finally {
                        this._spinnerActivated = false;
                    }
                }
            };

            wijgrid.prototype._prepareTotalsRequest = function () {
                var leaves = this._leaves(), result;

                if (!leaves || !this.options.showFooter) {
                    return [];
                }

                result = $.map(leaves, function (column, index) {
                    var opt = column.options;

                    if ((column instanceof grid.c1field) && opt.aggregate && opt.aggregate !== "none") {
                        return [column];
                    }

                    return null;
                });

                return result;
            };

            wijgrid.prototype._groupedLeaves = function (force) {
                var result;

                force = !(result = this.mGroupedLeaves) || force;

                if (force) {
                    result = [];

                    var leaves = this._leaves(), rebuildIndexes = false;

                    $.each(leaves, function (i, leaf) {
                        if (grid.c1field.isGroupedColumn(leaf)) {
                            rebuildIndexes = rebuildIndexes || (leaf.options.groupedIndex === undefined);

                            if (!rebuildIndexes) {
                                result.push(leaf);
                            }
                        } else {
                            delete leaf.options.groupedIndex;
                        }
                    });

                    if (rebuildIndexes) {
                        $.each(leaves, function (i, leaf) {
                            if (grid.c1field.isGroupedColumn(leaf)) {
                                leaf.options.groupedIndex = result.length;
                                result.push(leaf);
                            }
                        });
                    } else {
                        result.sort(function (a, b) {
                            return a.options.groupedIndex - b.options.groupedIndex;
                        });

                        $.each(result, function (i, column) {
                            column.options.groupedIndex = i;
                        });
                    }

                    this.mGroupedLeaves = result;
                }

                return result || [];
            };

            wijgrid.prototype._ensureRenderableBounds = function (bounds) {
                return wijmo.grid.ensureBounds(bounds, this._renderableRowsCount() - 1);
            };

            wijgrid.prototype._ensureTotalRowsBounds = function (bounds) {
                return wijmo.grid.ensureBounds(bounds, this._totalRowsCount() - 1);
            };

            wijgrid.prototype._ensureLowerBoundVisible = function (bounds) {
                var visibleQty = this._renderableRowsCount();

                if (bounds.end >= visibleQty) {
                    var view = this._view(), size = view.getVirtualPageSize(false);

                    bounds.end = visibleQty - 1;
                    bounds.start = bounds.end - size + 1;

                    bounds.start = Math.max(0, bounds.start);
                    bounds.end = Math.max(0, bounds.end);
                }

                return bounds;
            };

            wijgrid.prototype._renderableColumnsRange = function () {
                return this.mRenderableColumns;
            };

            wijgrid.prototype._renderableRowsRange = function () {
                return this.mRenderableRows;
            };

            wijgrid.prototype._rebuildRenderableRowsCollection = function () {
                var start = -1, end = -1, rangeFound = false, total = this._totalRowsCount();

                this.mRenderableRows = new wijmo.grid.renderableRowsCollection(total - 1);

                if (this._allowVVirtualScrolling() && this._serverSideVirtualScrolling()) {
                    this.mRenderableRows.add({ start: 0, end: total - 1 }); // all rows, groping is disabled
                } else {
                    if (!this._allowVVirtualScrolling() || !this._hasGrouping()) {
                        // assumption: if there is no grouping, then all sketch rows are visible
                        this.mRenderableRows.add({ start: 0, end: total - 1 }); // all rows
                    } else {
                        for (var i = 0; i < this.mSketchTable.count(); i++) {
                            var sketchItem = this.mSketchTable.row(i);

                            if (sketchItem.extInfo.state & 1 /* hidden */) {
                                if (start >= 0) {
                                    this.mRenderableRows.add({ start: start, end: end });
                                    rangeFound = false;
                                }

                                start = end = -1;
                            } else {
                                if (start < 0) {
                                    rangeFound = true;
                                    start = end = i;
                                } else {
                                    end++;
                                }
                            }
                        }

                        if (rangeFound) {
                            this.mRenderableRows.add({ start: start, end: end });
                        }
                    }
                }
            };

            wijgrid.prototype._refresh = function (userData) {
                if (this._hasGrouping() && this._hasDetail()) {
                    throw "It is not possible to use columns grouping and master-detail hierarchy simultaneously.";
                }

                if (this._hasDetail() && this._allowVirtualScrolling()) {
                    throw "It is not possible to use virtual scrolling and master-detail hierarchy simultaneously.";
                }

                // build hierarchy
                grid.hierarchyBuilder.build(this);

                // apply grouping
                new wijmo.grid.grouper().group(this, this.mSketchTable);

                // apply merging
                new wijmo.grid.merger().merge(this, this.mSketchTable);

                this._rebuildRenderableRowsCollection();

                //this._ensureViewPortBounds(this._viewPortBounds());
                // view
                if (this._lgGetScrollMode() !== "none") {
                    this.mView = new wijmo.grid.fixedView(this, this._viewPortBounds());
                } else {
                    this.mView = new wijmo.grid.flatView(this, this._viewPortBounds());
                }

                this._render();

                // pager
                if (this.options.allowPaging) {
                    // top pager
                    if (this.mTopPagerDiv) {
                        this.mTopPagerDiv.wijpager(this._pagerSettings2PagerWidgetSettings()).css("zIndex", 4);
                    }

                    // bottom pager
                    if (this.mBottomPagerDiv) {
                        this.mBottomPagerDiv.wijpager(this._pagerSettings2PagerWidgetSettings()).css("zIndex", 4);
                    }
                }
                // (re)create iternal widgets
            };

            wijgrid.prototype._refreshVirtual = function (userData) {
                var scrollData = userData.virtualScrollData, direction = userData.virtualScrollData.direction;

                if (direction === "h") {
                    this._view().render(true);
                } else {
                    var diffData = {
                        top: 0,
                        bottom: 0
                    };

                    if (scrollData.data) {
                        diffData = this._processVirtualData(scrollData);
                    }

                    this._updateRowInfos(scrollData, diffData);

                    this._renderVirtualIntoView(scrollData);
                }
                // debug
                /*var rows = this._view().bodyRows();
                for (var i = 0; i < rows.length(); i++) {
                var ri = this._view()._getRowInfo(rows.item(i));
                var innerDiv = ri.$rows.find("td:first ." + wijmo.grid.wijgrid.CSS.wijgridCellContainer);
                var html = innerDiv.html();
                
                html = "d:" + ri.dataItemIndex + " s:" + ri.sectionRowIndex + "  ||" + ri.data[0] + "|| " + html;
                innerDiv.html(html);
                }*/
                // debug
                /*if (scrollData.data && scrollData.mode === intersectionMode.reset) {
                this._view().vsUI.scrollToRow(scrollData.newBounds.start, true); // original scrollIndex could change due pageSize alignment, so we need to re-set position of the vertical scrollbar.
                }*/
            };

            wijgrid.prototype._updateRowInfos = function (scrollData, diffData) {
                var bounds = this._viewPortBounds(), view = this._view(), newBounds = scrollData.newBounds, rows = this._view().bodyRows(), relMatch, i, diff, rowInfo;

                switch (scrollData.mode) {
                    case 3 /* reset */:
                        break;

                    case 2 /* overlapBottom */:
                        relMatch = {
                            start: newBounds.start - bounds.start,
                            end: bounds.end - bounds.start
                        };

                        diff = newBounds.start - bounds.start;

                        for (i = relMatch.start; i <= relMatch.end; i++) {
                            rowInfo = view._getRowInfo(rows.item(i), false);

                            rowInfo.sectionRowIndex -= diff;

                            if (diffData.top !== 0) {
                                rowInfo.dataItemIndex += diffData.top;
                                rowInfo.sketchRowIndex += diffData.top;
                            }

                            view._setRowInfo(rowInfo.$rows, rowInfo);
                        }

                        break;

                    case 1 /* overlapTop */:
                        relMatch = {
                            start: bounds.start - bounds.start,
                            end: newBounds.end - bounds.start
                        };

                        diff = bounds.start - newBounds.start;

                        for (i = relMatch.start; i <= relMatch.end; i++) {
                            rowInfo = view._getRowInfo(rows.item(i), false);

                            rowInfo.sectionRowIndex += diff;

                            if (diffData.top !== 0) {
                                rowInfo.dataItemIndex += diffData.top;
                                rowInfo.sketchRowIndex += diffData.top;
                            }

                            view._setRowInfo(rowInfo.$rows, rowInfo);
                        }

                        break;
                }
            };

            wijgrid.prototype._renderVirtualIntoView = function (scrollData) {
                var bounds = this._viewPortBounds(), self = this, sketchRow, view = this._view(), match, sectionRowIndex, sketchRowIndex;

                view._clearNorthTablesHeight(true);
                view._ensureRenderHBounds();

                switch (scrollData.mode) {
                    case 3 /* reset */:
                        // remove all rows
                        view._clearBody();

                        // add new rows
                        var count = scrollData.newBounds.end - scrollData.newBounds.start + 1;

                        this._renderableRowsRange().forEachIndex(scrollData.newBounds.start, count, function (sketchIndex) {
                            sketchRowIndex = sketchIndex - self.mDataOffset;
                            sketchRow = self.mSketchTable.row(sketchRowIndex);
                            view._insertBodyRow(sketchRow, -1, sketchRow.dataItemIndex(), sketchRow.dataItemIndex(self.mDataOffset), sketchRowIndex);
                        });

                        view._rebuildOffsets();

                        break;

                    case 2 /* overlapBottom */:
                        match = {
                            start: scrollData.newBounds.start,
                            end: bounds.end
                        };

                        for (var i = 0; i < match.start - bounds.start; i++) {
                            view._removeBodyRow(0);
                        }

                        // add new rows to the bottom
                        var count = scrollData.newBounds.end - match.end;

                        this._renderableRowsRange().forEachIndex(match.end + 1, count, function (sketchIndex) {
                            sketchRowIndex = sketchIndex - self.mDataOffset;
                            sketchRow = self.mSketchTable.row(sketchRowIndex);
                            view._insertBodyRow(sketchRow, -1, sketchRow.dataItemIndex(), sketchRow.dataItemIndex(self.mDataOffset), sketchRowIndex);
                        });

                        break;

                    case 1 /* overlapTop */:
                        match = {
                            start: bounds.start,
                            end: scrollData.newBounds.end
                        };

                        for (var i = 0; i < bounds.end - scrollData.newBounds.end; i++) {
                            view._removeBodyRow(match.end - match.start + 1); // relative index starting from zero.
                        }

                        // add new tows to the top
                        sectionRowIndex = 0;

                        var count = bounds.start - scrollData.newBounds.start;

                        this._renderableRowsRange().forEachIndex(scrollData.newBounds.start, count, function (sketchIndex) {
                            sketchRowIndex = sketchIndex - self.mDataOffset;
                            sketchRow = self.mSketchTable.row(sketchRowIndex);
                            view._insertBodyRow(sketchRow, sectionRowIndex++, sketchRow.dataItemIndex(), sketchRow.dataItemIndex(self.mDataOffset), sketchRowIndex);
                        });

                        break;

                    default:
                        break;
                }
            };

            wijgrid.prototype._processVirtualData = function (scrollData) {
                var dvw = this.mDataViewWrapper, source = dvw.dataView().getSource(), dataItem, leaves = this._leaves(), i, alignedViewBounds, cachedBounds, exceeded = 0, dataDiff = {
                    top: 0,
                    bottom: 0
                }, margin = this._serverSideVirtualScrollingMargin();

                switch (scrollData.mode) {
                    case 3 /* reset */:
                        this.mSketchTable.clear();
                        dvw._unsafeSplice(0, source.length);

                        this.mDataOffset = scrollData.request.index;

                        for (i = 0; i < scrollData.data.length; i++) {
                            dvw._unsafePush(dataItem = scrollData.data[i]); // append rows to a dataStore
                            this.mSketchTable.add(this._buildSketchRow(dvw._wrapDataItem(dataItem, i), leaves));
                        }

                        break;

                    case 2 /* overlapBottom */:
                        for (i = 0; i < scrollData.data.length; i++) {
                            dvw._unsafePush(dataItem = scrollData.data[i]); // append rows to a dataStore
                            this.mSketchTable.add(this._buildSketchRow(dvw._wrapDataItem(dataItem, source.length - 1), leaves));
                        }

                        dataDiff.bottom = scrollData.data.length;

                        break;

                    case 1 /* overlapTop */:
                        for (i = scrollData.data.length - 1; i >= 0; i--) {
                            dvw._unsafeSplice(0, 0, dataItem = scrollData.data[i]);
                            this.mSketchTable.insert(0, this._buildSketchRow(dvw._wrapDataItem(dataItem, i), leaves));
                        }

                        this.mDataOffset = scrollData.request.index;

                        dataDiff.top = scrollData.data.length;

                        break;
                }

                // extend underlying data *
                // * remove cached items exceeded cached bounds
                // [margin][pageSize = viewBounds][margin]
                alignedViewBounds = this._ensureTotalRowsBounds({
                    start: scrollData.newBounds.start,
                    end: scrollData.newBounds.end
                });

                cachedBounds = {
                    start: this.mDataOffset,
                    end: this.mDataOffset + source.length - 1
                };

                // remove items from the bottom
                exceeded = (cachedBounds.end - alignedViewBounds.end) - margin;
                if (exceeded > 0) {
                    dataDiff.bottom -= exceeded;
                    dvw._unsafeSplice(source.length - exceeded, exceeded);
                    this.mSketchTable.removeLast(exceeded);
                }

                // remove items from the top
                exceeded = (alignedViewBounds.start - cachedBounds.start) - margin;
                if (exceeded > 0) {
                    dataDiff.top -= exceeded;
                    dvw._unsafeSplice(0, exceeded);
                    this.mSketchTable.removeFirst(exceeded);
                    this.mDataOffset += exceeded;
                }

                // remove data exceeded cached bounds *
                // * update metadata
                this.mSketchTable.updateIndexes();

                // update metadata *
                dvw._refreshSilent();

                return dataDiff;
            };

            wijgrid.prototype._needToCreatePagerItem = function () {
                return this.options.allowPaging === true;
            };

            wijgrid.prototype._isMobileEnv = function () {
                return this._isMobile;
            };

            wijgrid.prototype._isTouchEnv = function () {
                return !!($.support.isTouchEnabled && $.support.isTouchEnabled());
            };

            wijgrid.prototype._render = function () {
                var view = this._view(), o = this.options, defCSS = wijmo.grid.wijgrid.CSS, wijCSS = this.options.wijCSS, content;

                view.render(false);

                // YK: for fixing pager is not align to top and bottom when header is fixed.
                content = this.mOuterDiv;
                if (this._lgGetScrollMode() !== "none") {
                    // fixed header content
                    content = this.mOuterDiv.find("div." + defCSS.scroller + ":first");
                }

                this.mSuperPanelHeader = null;

                // ** top pager (top div)
                if (this.mTopPagerDiv) {
                    if (this.mTopPagerDiv.data("wijmo-wijpager")) {
                        this.mTopPagerDiv.wijpager("destroy");
                    }

                    this.mTopPagerDiv.remove();
                }

                this.mTopPagerDiv = null;

                if (this._needToCreatePagerItem() && ((o.pagerSettings.position === "top") || (o.pagerSettings.position === "topAndBottom"))) {
                    if (!this.mTopPagerDiv) {
                        content.prepend(this.mSuperPanelHeader = $("<div class=\"wijmo-wijsuperpanel-header\"></div>"));
                        this.mSuperPanelHeader.prepend(this.mTopPagerDiv = $("<div class=\"" + defCSS.headerArea + " " + wijCSS.wijgridHeaderArea + " " + wijCSS.header + " " + wijCSS.cornerTop + "\"></div>"));
                    }
                }

                // top pager **
                if (o.showGroupArea) {
                    this._processGroupArea(content);
                } else {
                    this.$groupArea = null;
                }

                // ** bottom pager (bottom div)
                if (this.mBottomPagerDiv) {
                    if (this.mBottomPagerDiv.data("wijmo-wijpager")) {
                        this.mBottomPagerDiv.wijpager("destroy");
                    }

                    this.mBottomPagerDiv.remove();
                }

                this.mBottomPagerDiv = null;

                if (this._needToCreatePagerItem() && ((o.pagerSettings.position === "bottom") || (o.pagerSettings.position === "topAndBottom"))) {
                    if (!this.mBottomPagerDiv) {
                        content.append(this.mBottomPagerDiv = $("<div class=\"" + defCSS.footerArea + " " + wijCSS.wijgridFooterArea + " wijmo-wijsuperpanel-footer " + wijCSS.stateDefault + " " + wijCSS.cornerBottom + "\"></div>"));
                    }
                }
                // bottom pager **
            };

            wijgrid.prototype._processGroupArea = function (content) {
                var _this = this;
                var self = this, groupCollection = this._groupedLeaves(), defCSS = wijmo.grid.wijgrid.CSS, wijCSS = this.options.wijCSS;

                this.mGroupAreaColumns = [];
                this.$groupArea = $("<div class=\"" + wijCSS.content + " " + wijCSS.helperClearFix + " " + defCSS.groupArea + " " + wijCSS.wijgridGroupArea + "\"></div>");

                if (groupCollection.length > 0) {
                    $.each(groupCollection, function (index, column) {
                        var groupElement = $("<a href=\"#\"></a>").appendTo(self.$groupArea);
                        _this.mGroupAreaColumns.push(_this._createGroupAreaColumnHeader(groupElement, column));
                    });
                } else {
                    this.$groupArea.addClass(defCSS.groupAreaEmpty).css("padding", 0).html(this.options.groupAreaCaption || "&nbsp;");
                }

                if (!this.mSuperPanelHeader) {
                    content.prepend(this.mSuperPanelHeader = $("<div class=\"wijmo-wijsuperpanel-header\"></div>"));
                }

                this.mSuperPanelHeader.prepend(this.$groupArea);

                this._UIDragndrop(true).attachGroupArea(this.$groupArea);
            };

            wijgrid.prototype._createGroupAreaColumnHeader = function (element, column) {
                return new grid.c1groupedfield(this, column.options, element);
            };

            wijgrid.prototype._pagerSettings2PagerWidgetSettings = function () {
                return $.extend({}, this.options.pagerSettings, {
                    disabled: this.options.disabled,
                    pageCount: this.pageCount(),
                    pageIndex: this.options.pageIndex,
                    pageIndexChanging: $.proxy(this._onPagerWidgetPageIndexChanging, this),
                    pageIndexChanged: $.proxy(this._onPagerWidgetPageIndexChanged, this)
                });
            };

            wijgrid.prototype._showRowHeader = function () {
                return (this.options.showRowHeader === true) && (this._lgGetStaticColumnsAlignment() !== "right");
            };

            wijgrid.prototype._attachEvents = function () {
                var view = this._view(), $fe = view.focusableElement(), self = this, k = function (eventName) {
                    return eventName + "." + self.widgetName;
                };

                $fe.unbind(k("keydown")).bind(k("keydown"), $.proxy(this._onKeyDown, this));
                $fe.unbind(k("focusin")).bind(k("focusin"), $.proxy(this._onFocusIn, this));

                this._KeyDownEventListener();

                $.each(view.subTables(), function (index, element) {
                    var domTable = element.element();
                    if (domTable) {
                        if (domTable.tHead) {
                            $(domTable.tHead).unbind(k("click")).bind(k("click"), $.proxy(self._onClick, self));
                        }

                        if (domTable.tBodies.length) {
                            $(domTable.tBodies[0]).unbind(k("click")).bind(k("click"), $.proxy(self._onClick, self)).bind(k("dblclick")).bind(k("dblclick"), $.proxy(self._onDblClick, self)).bind(k("mousemove")).bind(k("mousemove"), $.proxy(self._onMouseMove, self)).bind(k("mouseout")).bind(k("mouseout"), $.proxy(self._onMouseOut, self));
                        }
                    }
                });

                if (this._isRoot()) {
                    $(window).bind("resize." + this.widgetName + "." + this._eventUID, $.proxy(this._onWinResize, this));
                }
            };

            wijgrid.prototype._detachEvents = function (destroy) {
                var view = this._view(), self = this, $fe;

                if (this._windowResizeTimer > 0) {
                    window.clearTimeout(this._windowResizeTimer);
                    this._windowResizeTimer = 0;
                }

                $(window).unbind("resize." + this.widgetName + "." + this._eventUID);

                if (view) {
                    $fe = view.focusableElement();

                    $fe.unbind("." + this.widgetName);

                    $.each(view.subTables(), function () {
                        var domTable = this.element();

                        if (domTable) {
                            if (domTable.tHead) {
                                $(domTable.tHead).unbind("." + self.widgetName);
                            }

                            if (domTable.tBodies.length) {
                                $(domTable.tBodies[0]).unbind("." + self.widgetName);
                            }
                        }
                    });
                }
            };

            wijgrid.prototype._handleSort = function (column, multiSort) {
                var colOpt = column.options, columns = this.options.columns;

                if (this.options.allowSorting) {
                    var newSortDirection = ((colOpt.sortDirection === "none") ? "ascending" : ((colOpt.sortDirection === "ascending") ? "descending" : "ascending"));

                    var sortingArgs = {
                        column: colOpt,
                        sortDirection: newSortDirection,
                        sortCommand: colOpt.dataKey + " " + (newSortDirection === "ascending" ? "asc" : "desc")
                    };

                    if (this._onColumnSorting(sortingArgs)) {
                        colOpt.sortDirection = sortingArgs.sortDirection;

                        if (multiSort) {
                            colOpt._sortOrder = this.mCustomSortOrder++;
                        } else {
                            this.mCustomSortOrder = 1000; // reset to default

                            // reset sortDirection for all columns except sorting one and grouped columns
                            $.each(this._allColumns(), function (i, item) {
                                item.options._sortOrder = 0;

                                if (item instanceof grid.c1field) {
                                    var itemOpt = item.options;

                                    if (item !== column && !(itemOpt.groupInfo && itemOpt.groupInfo.position !== "none")) {
                                        itemOpt.sortDirection = "none";
                                    }
                                }
                            });
                        }

                        var sortedArgs = {
                            column: colOpt,
                            sortDirection: colOpt.sortDirection,
                            sortCommand: colOpt.dataKey + " " + (colOpt.sortDirection === "ascending" ? "asc" : "desc")
                        };

                        if (this._customPagingEnabled()) {
                            this._onColumnSorted(sortedArgs); // Allow user the ability to load a new data and refresh the grid.
                        } else {
                            this.ensureControl(true, {
                                afterRefresh: function () {
                                    this._onColumnSorted(sortedArgs);
                                }
                            });
                        }
                    }
                }
            };

            wijgrid.prototype._handleDragnDrop = function (dragInst, dropInst, at, dragInGroup, dropInGroup) {
                var drag = dragInst.options, drop = ((dropInst && dropInst.options) || null), dragSource = dragInGroup ? "groupArea" : "columns", dropSource = dropInGroup ? "groupArea" : "columns";

                if (dropInGroup) {
                    if (this._onColumnGrouping({ drag: drag, drop: drop, dragSource: dragSource, dropSource: dropSource, at: at })) {
                        this.ensureControl(true, {
                            beforeRefresh: function () {
                                if (!drop) {
                                    drag.groupedIndex = 0;
                                } else {
                                    switch (at) {
                                        case "left":
                                            drag.groupedIndex = drop.groupedIndex - 0.5;
                                            break;

                                        case "right":
                                            drag.groupedIndex = drop.groupedIndex + 0.5;
                                            break;
                                    }
                                }

                                if (!dragInGroup) {
                                    $.extend(true, drag, {
                                        groupInfo: {
                                            position: "header"
                                        }
                                    });
                                }
                            },
                            afterRefresh: function () {
                                this._onColumnGrouped({ drag: drag, drop: drop, dragSource: dragSource, dropSource: dropSource, at: at });
                            }
                        });
                    }
                } else {
                    var traverseList = this._allColumns(), dragAt = drag._parentIdx >= 0 ? traverseList[drag._parentIdx].options.columns : this.options.columns, dropAt = drop._parentIdx >= 0 ? traverseList[drop._parentIdx].options.columns : this.options.columns, dragLinearOffset = (dragAt === this.options.columns) ? this._virtualLeaves().length : 0, dropLinearOffset = (dropAt === this.options.columns) ? this._virtualLeaves().length : 0;

                    if (this._onColumnDropping({ drag: drag, drop: drop, at: at })) {
                        this.ensureControl(false, {
                            beforeRefresh: function () {
                                /* modifying the wijgrid.options.columns option */
                                dragAt.splice(drag._linearIdx - dragLinearOffset, 1);

                                switch (at) {
                                    case "left":
                                        if (dragAt === dropAt && drag._linearIdx < drop._linearIdx) {
                                            dropAt.splice(drop._linearIdx - dropLinearOffset - 1, 0, drag);
                                        } else {
                                            dropAt.splice(drop._linearIdx - dropLinearOffset, 0, drag);
                                        }
                                        break;

                                    case "right":
                                        if (dragAt === dropAt && drag._linearIdx < drop._linearIdx) {
                                            dropAt.splice(drop._linearIdx - dropLinearOffset, 0, drag);
                                        } else {
                                            dropAt.splice(drop._linearIdx - dropLinearOffset + 1, 0, drag);
                                        }
                                        break;

                                    case "center":
                                        drop.columns.push(drag);
                                        break;
                                }
                            },
                            afterRefresh: function () {
                                this._onColumnDropped({ drag: drag, drop: drop, at: at });
                            }
                        });
                    }
                }
            };

            wijgrid.prototype._handleFilter = function (column, rawOperator, rawValue) {
                var operator = (new wijmo.grid.filterOperatorsCache(this)).getByName(rawOperator), value, ok;

                if (operator) {
                    var opt = column.options;

                    if (operator.arity > 1) {
                        // check value
                        if (opt.dataType === 'boolean' && rawValue.toLowerCase() !== 'true' && rawValue.toLowerCase() !== 'false') {
                            return;
                        }
                        value = this.parse(opt, rawValue);
                        ok = (value !== null && (wijmo.grid.getDataType(opt) === "string" || !grid.isNaN(value)));
                    } else {
                        ok = true;
                    }

                    if (ok) {
                        var args = { column: opt, operator: operator.name, value: value };

                        if (this._onColumnFiltering(args)) {
                            opt.filterValue = args.value;
                            opt.filterOperator = args.operator;

                            this._resetDataProperitesOnFilterChanging();

                            if (this._customPagingEnabled()) {
                                this._onColumnFiltered({ column: opt }); // Allow user the ability to load a new data and refresh the grid.
                            } else {
                                this.ensureControl(true, {
                                    afterRefresh: function () {
                                        this._onColumnFiltered({ column: opt });
                                    }
                                });
                            }
                        }
                    }
                }
            };

            wijgrid.prototype._handleUngroup = function (column) {
                var opt = column.options;

                if (this._onColumnUngrouping({ column: opt })) {
                    this.ensureControl(true, {
                        beforeRefresh: function () {
                            delete opt.groupedIndex;

                            $.extend(true, opt, {
                                groupInfo: {
                                    position: "none"
                                }
                            });
                        },
                        afterRefresh: function () {
                            this._onColumnUngrouped({ column: opt });
                        }
                    });
                }
            };

            wijgrid.prototype._onVirtualScrolling = function (newBounds, request, mode, scrollIndex, completeCallback, data /* opt*/ ) {
                var self = this;

                this.ensureControl(this._serverSideVirtualScrolling(), {
                    virtualScrollData: {
                        direction: "v",
                        newBounds: newBounds,
                        request: request,
                        mode: mode,
                        data: data
                    },
                    beforeRefresh: function () {
                        self._view().resetRowsHeightsCache(); // don't use cached heights
                    },
                    beforeOnRendered: function (userData) {
                        var bounds = self._viewPortBounds();
                        $.extend(bounds, userData.virtualScrollData.newBounds);
                    },
                    afterRefresh: function (userData) {
                        self._view()._adjustRowsHeights(); // recalculate heights

                        self._UIFrozener().ensureVBarHeight();

                        if (completeCallback) {
                            completeCallback(scrollIndex);
                        }
                    }
                });
            };

            wijgrid.prototype._handleVerticalVirtualScrolling = function (scrollIndex, forceIntersectionMode, completeCallback) {
                if (typeof forceIntersectionMode === "undefined") { forceIntersectionMode = null; }
                var view = this._view(), bounds = this._viewPortBounds(), newBounds = this._ensureRenderableBounds({
                    start: scrollIndex,
                    end: scrollIndex + view.getVirtualPageSize() - 1
                }), cachedDataBounds = this._ensureTotalRowsBounds({
                    start: this.mDataOffset,
                    end: this.mDataOffset + this.mDataViewWrapper.dataView().count() - 1
                }), request = null, mode, virtualPageSize = view.getVirtualPageSize();

                // check viewBounds
                if (forceIntersectionMode) {
                    mode = forceIntersectionMode;
                } else {
                    if (newBounds.start > bounds.end || newBounds.end < bounds.start) {
                        mode = 3 /* reset */;
                    } else {
                        if (newBounds.start > bounds.start) {
                            mode = 2 /* overlapBottom */;
                        } else {
                            if (newBounds.start < bounds.start) {
                                mode = 1 /* overlapTop */;
                            } else {
                                mode = newBounds.start !== bounds.start || newBounds.end !== bounds.end ? 3 /* reset */ : 0 /* none */; // same range, "none"
                            }
                        }
                    }
                }

                // quick fix
                //mode = intersectionMode.reset;
                //
                // check dataBounds
                if (this._serverSideVirtualScrolling()) {
                    switch (mode) {
                        case 3 /* reset */:
                            request = {
                                index: scrollIndex,
                                maxCount: virtualPageSize
                            };

                            break;

                        case 2 /* overlapBottom */:
                            if (newBounds.end > cachedDataBounds.end) {
                                request = {
                                    index: cachedDataBounds.end + 1,
                                    maxCount: virtualPageSize
                                };
                            }

                            break;

                        case 1 /* overlapTop */:
                            if (newBounds.start < cachedDataBounds.start) {
                                request = {
                                    index: Math.max(0, cachedDataBounds.start - virtualPageSize),
                                    maxCount: 0
                                };
                                request.maxCount = cachedDataBounds.start - request.index;
                            }

                            break;
                    }
                }

                if (mode !== 0 /* none */) {
                    this._onVirtualScrolling(newBounds, request, mode, scrollIndex, completeCallback); // note: scrollIndex could be changed
                }
            };

            wijgrid.prototype._handleHorizontalVirtualScrolling = function (range, completeCallback) {
                var self = this;

                this.mRenderableColumns = range;
                this.mRenderedLeaves = [];

                if (self._allowCellEditing() && self.currentCell()._isValid() && self.currentCell()._isEdit()) {
                    self.endEdit(true);
                }

                this.ensureControl(false, {
                    virtualScrollData: {
                        direction: "h"
                    },
                    afterRefresh: function (userData) {
                        //(<wijmo.grid.fixedView>self._view())._adjustRowsHeights(); // Slow. A better solution is placed in the fixedView._rowRendered method.
                        self._attachEvents();

                        if (completeCallback) {
                            completeCallback();
                        }
                    }
                });
            };

            wijgrid.prototype._serverSideVirtualScrolling = function () {
                return false;
            };

            wijgrid.prototype._serverSideVirtualScrollingMargin = function () {
                var margin = this._view().getVirtualPageSize() * 2;

                if (margin < 20) {
                    margin = 20;
                }

                return margin;
            };

            // * event handlers
            wijgrid.prototype._onBeforeCellEdit = function (args) {
                return this._trigger("beforeCellEdit", null, args);
            };

            wijgrid.prototype._onBeforeCellUpdate = function (args) {
                return this._trigger("beforeCellUpdate", null, args);
            };

            wijgrid.prototype._onInvalidCellValue = function (args) {
                return this._trigger("invalidCellValue", null, args);
            };

            wijgrid.prototype._onAfterCellUpdate = function (args) {
                return this._trigger("afterCellUpdate", null, args);
            };

            wijgrid.prototype._onAfterCellEdit = function (args) {
                return this._trigger("afterCellEdit", null, args);
            };

            wijgrid.prototype._onColumnDropping = function (args) {
                return this._trigger("columnDropping", null, args);
            };

            wijgrid.prototype._onColumnDropped = function (args) {
                this._trigger("columnDropped", null, args);
            };

            wijgrid.prototype._onColumnGrouping = function (args) {
                return this._trigger("columnGrouping", null, args);
            };

            wijgrid.prototype._onColumnGrouped = function (args) {
                this._trigger("columnGrouped", null, args);
            };

            wijgrid.prototype._onColumnUngrouping = function (args) {
                return this._trigger("columnUngrouping", null, args);
            };

            wijgrid.prototype._onColumnUngrouped = function (args) {
                this._trigger("columnUngrouped", null, args);
            };

            wijgrid.prototype._onColumnFiltering = function (args) {
                return this._trigger("filtering", null, args);
            };

            wijgrid.prototype._onColumnFiltered = function (args) {
                this._trigger("filtered", null, args);
            };

            wijgrid.prototype._onFilterOperatorsListShowing = function (args) {
                this._trigger("filterOperatorsListShowing", null, args);
            };

            wijgrid.prototype._onColumnSorting = function (args) {
                return this._trigger("sorting", null, args);
            };

            wijgrid.prototype._onColumnSorted = function (args) {
                this._trigger("sorted", null, args);
            };

            wijgrid.prototype._onCurrentCellChanged = function (e, info) {
                var _this = this;
                var o = this.options, currentCell = this.currentCell(), rowInfo = currentCell.row(), completed = function () {
                    var currentCell = _this.currentCell(), dataRange = _this._getDataCellsRange(0 /* sketch */);

                    if (_this.options.highlightCurrentCell) {
                        var oldCell = new wijmo.grid.cellInfo(info.changingEventArgs.oldCellIndex, info.changingEventArgs.oldRowIndex, _this);

                        if (oldCell._isValid && dataRange._containsCellInfo(oldCell)) {
                            _this._highlightCellPosition(oldCell, false); // remove the old one
                        }

                        _this._highlightCellPosition(currentCell, true); // highlight the current one
                    }

                    var domCell;
                    if (info.setFocus && (domCell = currentCell.tableCell())) {
                        _this._setFocusOnCell(info.hasFocusedChild ? $(e.target) : $(domCell), info.hasFocusedChild, currentCell.columnInst());
                    }

                    _this._trigger("currentCellChanged");

                    // ** set selection
                    if (info.changeSelection) {
                        _this._updateSelection(e, info.selectionExtendMode);
                    }

                    // set selection **
                    // cell editing
                    var eventType = (e && (e.type || "").toLowerCase()) || "";
                    if (eventType === "click" && _this._editBySingleClick()) {
                        _this._beginEditInternal(e);
                    }
                };

                this.mCurrentCellLocker = true;

                // notify dataView
                this.mDataViewWrapper.currentPosition((rowInfo && (rowInfo.type & 2 /* data */)) ? rowInfo.dataItemIndex : -1);

                if (this._lgGetScrollMode() !== "none" && currentCell && !currentCell.isEqual(wijmo.grid.cellInfo.outsideValue)) {
                    var scrollToCell = currentCell, rowInfo = scrollToCell.row();

                    if (rowInfo && !(rowInfo.type & 2 /* data */) && !scrollToCell.tableCell()) {
                        scrollToCell = currentCell._clone();
                        scrollToCell.cellIndex(0);
                    }

                    this._view().scrollTo(scrollToCell, function () {
                        try  {
                            completed();
                        } finally {
                            _this.mCurrentCellLocker = false;
                        }
                    }, info);
                } else {
                    try  {
                        completed();
                    } finally {
                        this.mCurrentCellLocker = false;
                    }
                }
            };

            wijgrid.prototype._onDetailCreating = function (args) {
                this._trigger("detailCreating", null, args);
            };

            wijgrid.prototype._onDetailsLoaded = function (args) {
                this._trigger("detailsLoaded", null, args);
            };

            wijgrid.prototype._onPageIndexChanging = function (args) {
                return this._trigger("pageIndexChanging", null, args);
            };

            wijgrid.prototype._onPageIndexChanged = function (args) {
                this._trigger("pageIndexChanged", null, args);
            };

            wijgrid.prototype._onPagerWidgetPageIndexChanging = function (sender, args) {
                args.handled = true; // prevent wijpager from re-drawing
            };

            wijgrid.prototype._onPagerWidgetPageIndexChanged = function (sender, args) {
                this._setOption("pageIndex", args.newPageIndex);
            };

            wijgrid.prototype._onRendering = function (userData) {
                var view = this._view(), defCSS = wijmo.grid.wijgrid.CSS;

                this._rendered = false;

                // reset cached properties to react on options change properly (#119860)
                this.mAllowVVirtualScrolling = undefined;
                this.mAllowHVirtualScrolling = undefined;

                if (userData.virtualScrollData) {
                    //this.selection().clear(); // clear selection
                    //if (this.options.highlightCurrentCell) {
                    //	this._highlightCellPosition(this.currentCell(), false); // remove highlighning
                    //}
                } else {
                    var currentCell = this._currentCell();
                    this.mCurrentCellPrevCycle = currentCell ? { x: currentCell.cellIndex(), y: currentCell.rowIndex(), dataItemIndex: currentCell.row() ? currentCell.row().dataItemIndex : -1 } : { x: -1, y: -1, dataItemIndex: -1 };

                    this._currentCell(null);

                    if (view) {
                        view.dispose();
                    }

                    this._detachEvents(false);

                    if (this.mRenderCounter === 0) {
                        wijmo.grid.emptyTable(this.element[0]); // IE workaround: clean original table manually during first rendering to avoid memory leak (#56601).
                    }

                    if (!this.mOuterDiv[0].style.height) {
                        // #64328: If height is empty then fix it temporary to avoid jumps of the page's vertical scrollbar. Height will be restored in the _onRendered method.
                        this._isHeightTemporaryFixed = true;
                        this.mOuterDiv.height(this.mOuterDiv.height());
                    }

                    this.element.detach();

                    this.element.css({
                        "table-layout": "",
                        "width": ""
                    });

                    this.element.empty();

                    //this.mOuterDiv.empty();
                    this.mOuterDiv.children(":not(." + defCSS.spinnerMarker + ")").remove(); // remove all child nodes except the spinner.

                    this.mOuterDiv.append(this.element);

                    if (this._selectionui) {
                        this._selectionui.dispose();
                        this._selectionui = null;
                    }

                    if (this._resizerui) {
                        this._resizerui.dispose();
                        this._resizerui = null;
                    }

                    if (this._frozenerui) {
                        this._frozenerui.dispose();
                        this._frozenerui = null;
                    }

                    if (this.mKeyDownEventListener) {
                        this.mKeyDownEventListener.dispose();
                        this.mKeyDownEventListener = null;
                    }
                }

                this._trigger("rendering");
            };

            wijgrid.prototype._onRendered = function (userData) {
                var view = this._view(), currentCell, hasSelection = this.selection().selectedCells().length() > 0;

                this._rendered = true;
                this.mRenderCounter++;

                if (!userData.virtualScrollData) {
                    if (this._isHeightTemporaryFixed) {
                        this._isHeightTemporaryFixed = false;
                        this.mOuterDiv[0].style.height = "";
                    }

                    this.mSelection = null; // always recreate selection object

                    // attach events
                    this._attachEvents();

                    // ** current cell
                    this._setAttr(view.focusableElement(), "tabIndex", 0); // to handle keyboard\ focus events

                    currentCell = this._currentCellFromDataView(this.mCurrentCellPrevCycle.x);

                    if (!currentCell._isValid() && this.options.showSelectionOnRender) {
                        currentCell = this._getFirstDataRowCell(0);
                    }

                    this.currentCell(currentCell, null, true);

                    // current cell *
                    // selection ui
                    this._UISelection(true);

                    this._setSizeInternal(this.mScrollingState); // set sizes, create wijsuperpanel, restore scrolling state.
                } else {
                    var currentCell = this.currentCell();
                    this.currentCell(currentCell, null, false);

                    if (currentCell._isEdit() && !currentCell._isRendered()) {
                        currentCell._isEdit(false); // reset editing if sketchRow or column is not available (C1GridView virtual scrolling)
                    }

                    var selection = this.selection();
                    selection._ensureSelection();
                }

                // initialize resizer.
                if (!userData.virtualScrollData || this._allowHVirtualScrolling()) {
                    this._recreateResizerUI();
                }

                this._trigger("rendered");
            };

            wijgrid.prototype._recreateResizerUI = function () {
                var _this = this;
                if (this._resizerui) {
                    this._resizerui.dispose();
                }

                this._resizerui = new wijmo.grid.uiResizer(this);

                var leaves = this._allowHVirtualScrolling() ? this.columns() : this._renderedLeaves();

                $.each(leaves, function (idx, leaf) {
                    if (leaf._isRendered() && leaf.options._isLeaf) {
                        _this._resizerui.addElement(leaf);
                    }
                });
            };

            // note: can be called by the _onFocusIn method!
            wijgrid.prototype._onClick = function (e) {
                if (!this._canInteract() || !e.target) {
                    return;
                }

                var view = this._view(), clickedCell = this._findUntilOuterDiv(e.target, { td: true, th: true }), $row, clickedCellInfo, extendMode = 0 /* none */, currentCell, selection, clickedCellChanged = false, clickEvent = !!(e && (e.type === "click"));

                if (clickedCell) {
                    if (clickEvent && $(e.target).hasClass(wijmo.grid.wijgrid.CSS.groupToggleVisibilityButton)) {
                        this._onGroupBtnClick(e);

                        // #29676: stop event from bubbling up to the parent grid (if available)
                        e.stopPropagation();
                        return false;
                    }

                    $row = $(clickedCell).closest("tr");

                    if (!$row.length) {
                        return;
                    }

                    clickedCellInfo = view.getAbsoluteCellInfo(clickedCell, false);

                    if ($row.hasClass(wijmo.grid.wijgrid.CSS.dataRow) || $row.hasClass(wijmo.grid.wijgrid.CSS.headerRow) || $row.hasClass(wijmo.grid.wijgrid.CSS.filterRow)) {
                        if (clickedCellInfo.cellIndex() < 0 || clickedCellInfo.rowIndex() < 0) {
                            if (clickedCellInfo.rowIndex() >= 0) {
                                // move current cell to the first cell of the clicked row
                                if (this.options.scrollingSettings.virtualizationSettings.mode !== "none") {
                                    clickedCellInfo = view.getAbsoluteCellInfo(clickedCell, true);
                                }
                                clickedCellInfo = new wijmo.grid.cellInfo(0, clickedCellInfo.rowIndex());
                                extendMode = 2 /* row */;
                                clickedCellChanged = true;
                            } else {
                                if (clickedCellInfo.cellIndex() >= 0) {
                                    if (this._allowHVirtualScrolling()) {
                                        clickedCellInfo = view.getAbsoluteCellInfo(clickedCell, true); //get absolute cell idx (_visLeavesIdx) from rendered leaf's option when using virtualization.
                                    }

                                    // move current cell to the first data cell of the clicked column
                                    clickedCellInfo = this._getFirstDataRowCell(clickedCellInfo.cellIndex());
                                    extendMode = 1 /* column */;
                                    clickedCellChanged = true;
                                }
                            }
                        }

                        if (!clickedCellChanged) {
                            clickedCellInfo = view.getAbsoluteCellInfo(clickedCell, true);
                        }

                        // change current cell and set focus to it (if the target element is not already focused)
                        this._changeCurrentCell(e, clickedCellInfo, {
                            changeSelection: true,
                            setFocus: clickEvent,
                            selectionExtendMode: extendMode
                        });
                    }

                    if (clickEvent) {
                        var cellClickedArgs = { cell: clickedCellInfo };
                        this._trigger("cellClicked", null, cellClickedArgs);
                    }
                }
            };

            wijgrid.prototype._onDblClick = function (e) {
                if (!this._editBySingleClick() && this._testForThis(e.target)) {
                    this._beginEditInternal(e);
                }
            };

            wijgrid.prototype._onGroupBtnClick = function (e) {
                if (!this._canInteract()) {
                    return;
                }

                var $row = $(e.target).closest("tr"), gh = wijmo.grid.groupHelper, groupInfo = gh.getGroupInfo($row[0]), self = this;

                if (groupInfo) {
                    var column = gh.getColumnByGroupLevel(this._leaves(), groupInfo.level), rowsToAdjust = null;

                    if (column) {
                        var group = column.options.groupInfo.expandInfo[groupInfo.index];

                        if (group.isExpanded) {
                            group.collapse(this, column);
                        } else {
                            group.expand(this, column, e.shiftKey);
                        }

                        if (this._allowVVirtualScrolling()) {
                            this._rebuildRenderableRowsCollection();
                            this._view().vsUI._changeVisibleRowsCount(this._renderableRowsRange().capacity());

                            this._ensureLowerBoundVisible(this._viewPortBounds());

                            this._handleVerticalVirtualScrolling(this._viewPortBounds().start, 3 /* reset */);
                        } else {
                            rowsToAdjust = group.cr; // adjust heights of the rows which are belongs to the current group only (#95085, speedup group expanding\ collapsing)
                        }

                        //this._view().ensureHeight(); /*dma*/
                        this.setSize(undefined, undefined, rowsToAdjust); // recalculate sizes (#39295)
                    }
                }
            };

            wijgrid.prototype._onKeyDown = function (e) {
                var isKeyDownListenerElement = this._KeyDownEventListener().isHiddenInput($(e.target));

                if (!this._canInteract() || (isKeyDownListenerElement && this._KeyDownEventListener().canHandle(e))) {
                    return true;
                }

                var tag = e.target.tagName.toLowerCase(), $target = $(e.target), currentCell = this.currentCell(), keyCodeEnum = wijmo.getKeyCodeEnum(), $outerDiv = undefined;

                if (!isKeyDownListenerElement && (tag === "input" || tag === "option" || tag === "select" || tag === "textarea") && ($target.closest("tr.wijmo-wijgrid-datarow").length === 0)) {
                    return true;
                }

                if (this._allowCellEditing()) {
                    // ESC: cancel editing, F2: finish editing
                    if ((e.which === keyCodeEnum.ESCAPE || e.which === 113) && (currentCell._isValid() && currentCell._isEdit())) {
                        this._endEditInternal(e, e.which === keyCodeEnum.ESCAPE);
                        return false;
                    } else {
                        if (e.which === 113) {
                            this._beginEditInternal(e);
                            return false;
                        }
                    }
                }

                if (!this.options.allowKeyboardNavigation) {
                    return true;
                }

                var nextCell;

                switch (e.which) {
                    case keyCodeEnum.DOWN:
                    case keyCodeEnum.PAGE_DOWN:
                    case keyCodeEnum.UP:
                    case keyCodeEnum.PAGE_UP:
                    case keyCodeEnum.LEFT:
                    case keyCodeEnum.RIGHT:
                    case keyCodeEnum.HOME:
                    case keyCodeEnum.END:
                    case keyCodeEnum.TAB:
                        if (e.which === keyCodeEnum.TAB) {
                            var visibleLeaves = this._visibleLeaves();

                            // There is no data in the grid, will bubble the keydown event out of the grid.
                            if (!visibleLeaves || !visibleLeaves.length) {
                                return true;
                            }
                        }

                        if (isKeyDownListenerElement || this._canMoveToAnotherCell(e.target, e.which)) {
                            var dataRange = this._getDataCellsRange(2 /* renderable */);
                            nextCell = this._getNextCurrentCell(dataRange, currentCell, e.keyCode, e.shiftKey);
                        }

                        break;
                }

                if (nextCell) {
                    // change current cell and set focus to it (always set focus to change the IME mode).
                    this._changeCurrentCell(e, nextCell, { changeSelection: true, setFocus: true });
                    return false;
                } else {
                    if (e.which === keyCodeEnum.TAB) {
                        $outerDiv = $(this._view().focusableElement());
                        if (e.shiftKey) {
                            if ($outerDiv && e.target !== $outerDiv[0]) {
                                $outerDiv.focus();
                                return false;
                            }
                        } else {
                            if (e.target === $outerDiv[0] && currentCell._isValid()) {
                                this._setFocusOnCell($(currentCell.tableCell()), false, currentCell.columnInst());
                            }
                        }
                    }
                }

                return true;
            };

            wijgrid.prototype._onFocusIn = function (e) {
                if (this.options.allowKeyboardNavigation && e && e.target && $(e.target).is(":input") && !this._KeyDownEventListener().isHiddenInput($(e.target)) && this._testForThis(e.target)) {
                    this._onClick(e); // simulate a click
                }
            };

            wijgrid.prototype._onMouseMove = function (e) {
                if (!this.options.highlightOnHover || !this._canInteract() || (this._frozenerui && this._frozenerui.inProgress())) {
                    return;
                }

                var hovCell = this._findUntilOuterDiv(e.target, { td: true, th: true });

                if (hovCell) {
                    var hovRow = $(hovCell).closest("tr");

                    if (!hovRow.length || !(hovRow.hasClass(wijmo.grid.wijgrid.CSS.dataRow) || hovRow.hasClass(wijmo.grid.wijgrid.CSS.headerRow))) {
                        return;
                    }

                    var hovCellInfo = this._view().getAbsoluteCellInfo(hovCell, true), hovSketchIndex = hovCellInfo.rowIndex();

                    if (hovSketchIndex !== this._hover()) {
                        this._hover(-1); // clear previous row
                        this._hover(hovSketchIndex); // highlight current row
                    }
                }
            };

            wijgrid.prototype._onToggleHierarchy = function (e, row) {
                if (!this._canInteract()) {
                    return;
                }

                var detail = this.details()[row.dataRowIndex];

                if (detail.isExpanded()) {
                    detail.collapse();
                    //this.setSize();
                } else {
                    detail.expand();
                }
            };

            wijgrid.prototype._onMouseOut = function (e) {
                if (!this._canInteract()) {
                    return;
                }

                if (this._hover() >= 0) {
                    var firstParentRow = this._findUntilOuterDiv(e.relatedTarget, { tr: true });

                    if (!firstParentRow || !$(firstParentRow).hasClass(wijmo.grid.wijgrid.CSS.dataRow)) {
                        this._hover(-1); // clear
                    }
                }
            };

            wijgrid.prototype._onWinResize = function (e) {
                var self = this;

                if (wijmo.grid.wijgrid.IGNORE_WIN_RESIZE) {
                    return;
                }

                // reset timer
                if (this._windowResizeTimer > 0) {
                    window.clearTimeout(this._windowResizeTimer);
                    this._windowResizeTimer = 0;
                }

                if (this._windowResizeTimer !== -1) {
                    this._windowResizeTimer = window.setTimeout(function () {
                        self._windowResizeTimer = -1; // lock

                        try  {
                            if (!self.mDestroyed && self._initialized && self.element.parent().length && self.element.is(":visible")) {
                                var orientation = wijmo.grid.getWindowOrientation();

                                // #64466: ignore Android (triggers "resize" event on virtual keyboard popup) except orientation changing.
                                var resize = self.mResizeOnWindowResize && (!wijmo.grid.isMobile() || (orientation !== self._winOrientation));

                                self._winOrientation = orientation;

                                if (resize) {
                                    self._onWindowResize();
                                    self.setSize();
                                }
                            }
                        } finally {
                            self._windowResizeTimer = 0; // unlock
                        }
                    }, wijmo.grid.wijgrid.WIN_RESIZE_TIMEOUT);
                }
            };

            wijgrid.prototype._onWindowResize = function () {
            };

            // * event handlers
            // * resizing
            wijgrid.prototype._fieldResized = function (column, oldWidth, newWidth) {
                if (oldWidth < 0) {
                    oldWidth = 0;
                }

                if (newWidth <= 0) {
                    newWidth = 1;
                }

                var resizingArgs = {
                    column: column.options,
                    oldWidth: oldWidth,
                    newWidth: newWidth
                };

                if (this._trigger("columnResizing", null, resizingArgs) !== false) {
                    if (grid.isNaN(resizingArgs.newWidth) || resizingArgs.newWidth < 0) {
                        resizingArgs.newWidth = 1;
                    }

                    column.option("width", resizingArgs.newWidth); // update widget option first (tfs issue 32108)

                    if (this._allowHVirtualScrolling()) {
                        this.doRefresh();
                    } else {
                        if (this._allowVVirtualScrolling() && !this._serverSideVirtualScrolling() && (this._lgGetScrollMode() === "auto")) {
                            var view = this._view();
                            if (view._isLastItemRendered() && view._canRenderMoreItems()) {
                                this.doRefresh(); // 82576 (virtual scrolling) - when any column is resized such that vscrollbar is visible and then the grid is scrolled down and any columm is resized again so that vscrollbar is removed then the first row is not displayed.
                            }
                        }
                    }

                    var resizedArgs = { column: column.options };
                    this._trigger("columnResized", null, resizedArgs);
                }
            };

            // * resizing
            wijgrid.prototype._setFocusOnCell = function (element, focusableChild, column) {
                if (focusableChild) {
                    //if (!element.is(":focus")) {
                    //	element.focus(); // ensure that element still has focus.
                    //}
                } else {
                    this._KeyDownEventListener().focus(element, column);
                }
            };

            wijgrid.prototype._findFocusedChild = function (parent) {
                var result = parent.find(":focus");
                return result.length ? result : null;
            };

            // * currentCell
            // returns false when currentCellChanging event was cancelled, otherwise true.
            wijgrid.prototype._changeCurrentCell = function (e, cellInfo, info) {
                if (this.mCurrentCellLocker) {
                    return;
                }

                var currentCell = this.currentCell(), dataRange = this._getDataCellsRange(0 /* sketch */);

                // if cellInfo has a valid value
                if ((dataRange._isValid() && dataRange._containsCellInfo(cellInfo)) || (cellInfo.isEqual(wijmo.grid.cellInfo.outsideValue))) {
                    var $target = e && e.target && $(e.target), domCell = cellInfo.tableCell(), $container = cellInfo.container(), $focusedChild = null;

                    info.hasFocusedChild = !!(domCell && $target && ($target[0] !== domCell) && ($target[0] !== $container[0]) && !this._KeyDownEventListener().isHiddenInput($target) && ($focusedChild = this._findFocusedChild($container))); // $focusedChild can differs from $target (#56472)

                    // other cell than current cell
                    if (currentCell.cellIndex() !== cellInfo.cellIndex() || currentCell.rowIndex() !== cellInfo.rowIndex()) {
                        var currentCellChangingArgs = {
                            cellIndex: cellInfo.cellIndex(),
                            rowIndex: cellInfo.rowIndex(),
                            oldCellIndex: currentCell.cellIndex(),
                            oldRowIndex: currentCell.rowIndex()
                        };

                        if (this._trigger("currentCellChanging", null, currentCellChangingArgs)) {
                            var cellEditCompleted = false;

                            if (!this._allowCellEditing() || !currentCell._isEdit() || (cellEditCompleted = this._endEditInternal(null))) {
                                info.changingEventArgs = currentCellChangingArgs;

                                currentCell = cellInfo._clone();
                                currentCell._setGridView(this);

                                this._currentCell(currentCell); // set currentCell

                                this._onCurrentCellChanged(e, info);
                            }
                        } else {
                            return false;
                        }
                    } else {
                        if (this.options.highlightCurrentCell) {
                            this._highlightCellPosition(currentCell, true); // ensure
                        }

                        if (info.changeSelection) {
                            this._updateSelection(e, info.selectionExtendMode); // ensure selection
                        }

                        if (domCell && !currentCell._isEdit()) {
                            if (e && this._editBySingleClick()) {
                                this.mCurrentCellLocker = true; // avoid focusin-click recursion if editingInitOption="click" and currentCell is clicked.
                                this._beginEditInternal(e);
                                this.mCurrentCellLocker = false;
                            } else {
                                if (info.setFocus) {
                                    this._setFocusOnCell(info.hasFocusedChild ? $focusedChild : $(domCell), info.hasFocusedChild, currentCell.columnInst());
                                }
                            }
                        }
                    }
                } else {
                    // do nothing
                    // this._highlightCellPosition(currentCell, false);
                    // this._field("currentCell", currentCell.outsideValue); // set currentCell
                }

                return true;
            };

            wijgrid.prototype._highlightCellPosition = function (cellInfo, add) {
                if (cellInfo && cellInfo._isValid()) {
                    var x = cellInfo.cellIndexAbs(), y = cellInfo.rowIndexAbs(), $rs = wijmo.grid.renderState, view = this._view(), rowInfo, obj, state;

                    // * column header cell * - change even if the cell is not rendered.
                    obj = view.getHeaderCell(x);
                    if (obj) {
                        rowInfo = view._getRowInfo(this._headerRows().item(cellInfo.column()._thY));

                        obj = $(obj);
                        state = view._changeCellRenderState(obj, 2 /* current */, add);

                        // highlight column header cell
                        this.mCellStyleFormatter.format(obj, x, cellInfo.columnInst(), rowInfo, state);
                    }

                    if (cellInfo._isRendered()) {
                        // * row header cell *
                        obj = view.getJoinedRows(y, 0);
                        if (obj) {
                            // change row state
                            rowInfo = view._getRowInfo(obj);
                            view._changeRowRenderState(rowInfo, 2 /* current */, add);

                            // highlight row header cell
                            this.mRowStyleFormatter.format(rowInfo);
                        }

                        // * data cell *
                        obj = view.getCell(x, y);
                        if (obj) {
                            obj = $(obj);
                            state = view._changeCellRenderState(obj, 2 /* current */, add);

                            // highlight data cell
                            this.mCellStyleFormatter.format(obj, x, cellInfo.columnInst(), rowInfo, state); // rowInfo is taken from the previous step
                        }
                    }
                }
            };

            wijgrid.prototype._hover = function (sketchRowIndex) {
                if (arguments.length) {
                    if (sketchRowIndex >= 0) {
                        this._hoverRowCss(sketchRowIndex, true); // highlight
                        this._prevHoveredSketchRowIndex = sketchRowIndex;
                    } else {
                        this._hoverRowCss(this._prevHoveredSketchRowIndex, false); // clear
                        this._prevHoveredSketchRowIndex = -1;
                    }
                }

                return this._prevHoveredSketchRowIndex;
            };

            wijgrid.prototype._hoverRowCss = function (sketchRowIndex, add) {
                if (sketchRowIndex >= 0) {
                    var view = this._view(), row = view._getRowInfoBySketchRowIndex(sketchRowIndex);

                    if (row) {
                        view._changeRowRenderState(row, 4 /* hovered */, add);

                        if (row.$rows) {
                            this.mRowStyleFormatter.format(row);
                        }
                    }
                }
            };

            // * currentCell
            // * editing
            wijgrid.prototype._beginEditInternal = function (e) {
                if (this._canInteract() && this._allowCellEditing()) {
                    var cell = this.currentCell(), column = cell.column(), res;

                    if (column && !column.readOnly) {
                        res = new wijmo.grid.cellEditorHelper().cellEditStart(this, cell, e);

                        //if (res) {
                        //	this._view().ensureWidth(undefined, column._visLeavesIdx);
                        //}
                        return res;
                    }
                }

                return false;
            };

            wijgrid.prototype._endEditInternal = function (e, reject) {
                if (typeof reject === "undefined") { reject = false; }
                if (this._canInteract() && this._allowCellEditing()) {
                    var cell = this.currentCell(), cellEditor = new wijmo.grid.cellEditorHelper();

                    // Fix the TFS issue #87950
                    var row = cell.row();
                    if (row && !row.data) {
                        return false;
                    }

                    // Fix the TFS issue #87950
                    var updateRes = cellEditor.updateCell(this, cell, e, reject);

                    if (updateRes & 2 /* success */) {
                        if (updateRes & 8 /* notEdited */) {
                            return true;
                        }

                        cellEditor.cellEditEnd(this, cell, e);

                        cell = this.currentCell();

                        // set focus to listen keypress\ keydown event.
                        var domCell = cell.tableCell();
                        if (domCell) {
                            this._KeyDownEventListener().focus($(domCell), cell.columnInst());
                        } else {
                            $(this._view().focusableElement()).focus();
                        }

                        if (!this._allowVVirtualScrolling() && !(cell.columnInst() instanceof grid.c1booleanfield)) {
                            this._view().ensureHeight(cell.rowIndex());
                        }

                        return true;
                    }
                }

                return false;
            };

            // * editing
            // * view handlers
            wijgrid.prototype._onViewInsertEmptyRow = function (rowType, renderState, sectionRowIndex, dataRowIndex, dataItemIndex, virtualDataItemIndex, sketchRowIndex, groupByValue) {
                return null;
            };

            wijgrid.prototype._onViewCreateEmptyCell = function (rowInfo, dataCellIndex, column) {
                return null;
            };

            wijgrid.prototype._onViewCellRendered = function (cell, container, row, cellIndex, column) {
            };

            wijgrid.prototype._onViewRowRendered = function (rowInfo, rowAttr, rowStyle) {
            };

            wijgrid.prototype._readTableSection = function (table, scope, readAttributes) {
                var decodeHTML = (scope === 2 /* body */) && (this._serverShaping()), trim = this.options._htmlTrimMethod;

                return wijmo.grid.readTableSection(table, scope, decodeHTML, trim, readAttributes);
            };

            wijgrid.prototype._getDataParser = function (column) {
                return column.dataParser || wijmo.data.defaultParsers[column.dataType] || wijmo.data.defaultParsers.string;
            };

            wijgrid.prototype._needParseColumnDOM = function (column) {
                return (wijmo.grid.getDataType(column) !== "string" && wijmo.grid.validDataKey(column.dataKey));
            };

            wijgrid.prototype._getDOMReaderCulture = function () {
                return null;
            };

            /** @ignore */
            wijgrid.prototype.parseCtx = function (column, value, dataItem, cell, forcedCulture) {
                return this.parse(column, value, forcedCulture);
            };

            /** @ignore */
            wijgrid.prototype.parseCtxFailed = function (column, value, dataItem, cell, forcedCulture) {
                return value;
            };

            /** @ignore */
            wijgrid.prototype.parse = function (column, value, forcedCulture) {
                //// old behaviour
                //var parser = this._getDataParser(column);
                //return parser.parse(value, this._field("closestCulture"), column.dataFormatString, this.options.nullString, true);
                var fromType = wijmo.grid.getDataType(column), toType = wijmo.grid.getDataType(column);

                if ($.isFunction(value)) {
                    value = value(); // observable
                }

                value = wijmo.data.convert(value, fromType, toType, {
                    culture: forcedCulture || this.mClosestCulture,
                    format: column.dataFormatString,
                    nullString: this.options.nullString,
                    parser: column.dataParser
                });

                return value;
            };

            /** @ignore */
            wijgrid.prototype.toStr = function (column, value, forcedCulture) {
                //// old behaviour
                //var parser = this._getDataParser(column);
                //return parser.toStr(value, this._field("closestCulture"), column.dataFormatString, this.options.nullString, true);
                var dataView = this.mDataViewWrapper.dataView(), fromType = wijmo.grid.getDataType(column), toType = "string";

                value = wijmo.data.convert(value, fromType, toType, {
                    culture: forcedCulture || this.mClosestCulture,
                    format: column.dataFormatString,
                    nullString: this.options.nullString,
                    parser: column.dataParser
                });

                return value;
            };

            wijgrid.prototype._funcOptions = function () {
                return [
                    "cellStyleFormatter", "rowStyleFormatter", "afterCellEdit", "afterCellUpdate", "beforeCellEdit", "beforeCellUpdate",
                    "cellClicked",
                    "columnDragging", "columnDragged", "columnDropping", "columnDropped", "columnResizing", "columnResized",
                    "columnGrouping", "columnGrouped", "columnUngrouping", "columnUngrouped",
                    "currentCellChanging", "currentCellChanged",
                    "detailCreating",
                    "filtering", "filtered",
                    "filterOperatorsListShowing", "groupAggregate", "groupText", "invalidCellValue", "pageIndexChanging", "pageIndexChanged",
                    "selectionChanged", "sorting", "sorted", "dataLoading", "dataLoaded", "loading", "loaded", "rendering", "rendered"];
            };

            wijgrid.prototype._canInteract = function () {
                return !this.options.disabled && this.mLoadingDetails === 0;
            };

            wijgrid.prototype._canMoveToAnotherCell = function (domElement, keyCode) {
                var tag = domElement.tagName.toLowerCase(), len, selectionRange, kc, res;

                switch (tag) {
                    case "input":
                        if ($(domElement).hasClass(wijmo.grid.wijgrid.CSS.inputMarker)) {
                            var input = domElement;

                            if (input.type === "text") {
                                len = input.value.length;
                                selectionRange = new wijmo.grid.domSelection(input).getSelection();

                                kc = wijmo.getKeyCodeEnum();

                                res = ((keyCode === kc.TAB) || (keyCode === kc.UP || keyCode === kc.DOWN || keyCode === kc.PAGE_DOWN || keyCode === kc.PAGE_UP) || (selectionRange.length === 0 && ((selectionRange.start === 0 && (keyCode === kc.LEFT || keyCode === kc.HOME)) || (selectionRange.end >= len && (keyCode === kc.RIGHT || keyCode === kc.END)))));

                                return res;
                            }

                            return true;
                        }

                        return false;

                    case "textarea":
                    case "select":
                        return false;
                }

                return true;
            };

            wijgrid.prototype._editBySingleClick = function () {
                var value = (this.options.editingInitOption || "").toLowerCase();

                switch (value) {
                    case "click":
                    case "doubleclick":
                        break;

                    case "auto":
                    default:
                        value = this._isMobileEnv() ? "click" : "doubleclick";
                        break;
                }

                return value === "click";
            };

            wijgrid.prototype._getDataToAbsOffset = function () {
                var x = 0, y = 0, headerRows = this._headerRows();

                x += this._virtualLeaves().length;

                if (headerRows) {
                    y += headerRows.length();
                }

                if (this._filterRow()) {
                    y++;
                }

                return {
                    x: x,
                    y: y
                };
            };

            wijgrid.prototype._currentCellFromDataView = function (cellIndex) {
                var dataViewRowIndex = this.mDataViewWrapper.currentPosition(), cellInfo = new wijmo.grid.cellInfo(cellIndex, this._dataViewDataRowIndexToGrid(dataViewRowIndex), null);

                // normalize
                if (cellInfo.rowIndex() < 0) {
                    cellInfo.cellIndex(-1);
                } else {
                    if (cellInfo.cellIndex() < 0) {
                        cellInfo.cellIndex(0);
                    }
                }

                return cellInfo;
            };

            wijgrid.prototype._dataViewDataRowIndexToGrid = function (rowIndex) {
                if ((rowIndex >= 0) && this.mSketchTable) {
                    for (var i = 0; i < this.mSketchTable.count(); i++) {
                        var sketchRow = this.mSketchTable.row(i);

                        if (sketchRow.isDataRow() && sketchRow.dataItemIndex() === rowIndex) {
                            return i;
                        }
                    }
                }

                return -1;
            };

            wijgrid.prototype._getDataCellsRange = function (mode, lastRowEntirelyVisible) {
                if (typeof lastRowEntirelyVisible === "undefined") { lastRowEntirelyVisible = false; }
                var minCol = 0, minRow = 0, maxCol = this._visibleLeaves().length - 1, maxRow;

                switch (mode) {
                    case 1 /* rendered */:
                        if (this._rendered) {
                            maxRow = this._rows().length() - 1;
                            break;
                        }

                    case 0 /* sketch */:
                        maxRow = this._totalRowsCount() - 1;
                        break;

                    case 2 /* renderable */:
                        maxRow = this._renderableRowsCount() - 1;
                        break;
                }

                maxCol -= this._virtualLeaves().length;

                if (lastRowEntirelyVisible && maxRow > 0) {
                    maxRow--;
                }

                if (maxCol < 0 || maxRow < 0) {
                    minCol = minRow = maxCol = maxRow = -1;
                }

                return new wijmo.grid.cellInfoRange(new wijmo.grid.cellInfo(minCol, minRow, null), new wijmo.grid.cellInfo(maxCol, maxRow, null));
            };

            wijgrid.prototype._getDataItem = function (dataItemIndex) {
                return this.dataView().item(dataItemIndex);
            };

            wijgrid.prototype._getFirstDataRowCell = function (absCellIndex) {
                var rowIndex, len, rowInfo, view = this._view(), rows = this._rows(), $rt = wijmo.grid.rowType;

                for (rowIndex = 0, len = rows.length(); rowIndex < len; rowIndex++) {
                    rowInfo = view._getRowInfo(rows.item(rowIndex));

                    if (rowInfo.type & 2 /* data */) {
                        return new wijmo.grid.cellInfo(absCellIndex, rowIndex);
                    }
                }

                return wijmo.grid.cellInfo.outsideValue;
            };

            wijgrid.prototype._getNextCurrentCell = function (dataRange, cellInfo, keyCode, shiftKeyPressed) {
                var cellIndex = cellInfo.cellIndex(), rowIndex = cellInfo.rowIndex(), keyCodeEnum = wijmo.getKeyCodeEnum(), sketchTable = this.mSketchTable, renderedRowIndex = this._renderableRowsRange().getRenderedIndex(rowIndex), rbc = this._renderableRowsRange(), tmp, dataRowsOnly = (keyCode === keyCodeEnum.TAB), self = this, sss = self._serverSideVirtualScrolling(), nextCell = null, column = null, findNextVisibleRow = function (further, startFrom, maxRowsToTouch, dataRowsOnly) {
                    if (typeof dataRowsOnly === "undefined") { dataRowsOnly = false; }
                    var iterator = further ? rbc.forEachIndex : rbc.forEachIndexBackward, cnt = 0, result = null;

                    iterator.call(rbc, startFrom, -1, function (absIdx) {
                        var sketchIdx = absIdx - self.mDataOffset;

                        if (sss && (sketchIdx < 0 || sketchIdx >= sketchTable.count())) {
                            result = absIdx;
                            return false;
                        }

                        var sketchRow = sketchTable.row(sketchIdx), isDataRow = sketchRow.isDataRow();

                        // test dataType and visibility
                        if ((!dataRowsOnly || isDataRow) && (!(sketchRow.extInfo.state & 1 /* hidden */))) {
                            result = absIdx;

                            if (++cnt >= maxRowsToTouch) {
                                return false;
                            }
                        }
                    });

                    return result;
                };

                switch (keyCode) {
                    case keyCodeEnum.ENTER:
                    case keyCodeEnum.DOWN:
                        if ((tmp = findNextVisibleRow(true, renderedRowIndex + 1, 1)) != null) {
                            rowIndex = tmp;
                        }
                        break;

                    case keyCodeEnum.PAGE_DOWN:
                        if ((tmp = findNextVisibleRow(true, renderedRowIndex + 1, this.mPageSizeKey)) != null) {
                            rowIndex = tmp;
                        }
                        break;

                    case keyCodeEnum.UP:
                        if ((tmp = findNextVisibleRow(false, renderedRowIndex - 1, 1)) != null) {
                            rowIndex = tmp;
                        }
                        break;

                    case keyCodeEnum.PAGE_UP:
                        if ((tmp = findNextVisibleRow(false, renderedRowIndex - 1, this.mPageSizeKey)) != null) {
                            rowIndex = tmp;
                        }
                        break;

                    case keyCodeEnum.TAB:
                        // note: iterate through data rows only
                        if (shiftKeyPressed) {
                            cellIndex--;

                            if (cellIndex < dataRange.topLeft().cellIndex()) {
                                cellIndex = dataRange.bottomRight().cellIndex();

                                if ((tmp = findNextVisibleRow(false, renderedRowIndex - 1, 1, true)) != null) {
                                    rowIndex = tmp;
                                } else {
                                    if (self.options.keyActionTab === "moveAcross") {
                                        if ((tmp = findNextVisibleRow(false, rbc.capacity() - 1, 1, true)) != null) {
                                            rowIndex = tmp;
                                        }
                                    } else {
                                        rowIndex = -1; //invalid rowIndex ,then return null for bubbling ( Roadmap 2015 V2 )
                                    }
                                }
                            }
                        } else {
                            cellIndex++;

                            if (cellIndex > dataRange.bottomRight().cellIndex()) {
                                cellIndex = dataRange.topLeft().cellIndex();

                                if ((tmp = findNextVisibleRow(true, renderedRowIndex + 1, 1, true)) != null) {
                                    rowIndex = tmp;
                                } else {
                                    if (self.options.keyActionTab === "moveAcross") {
                                        if ((tmp = findNextVisibleRow(true, 0, 1, true)) != null) {
                                            rowIndex = tmp;
                                        }
                                    } else {
                                        rowIndex = -1; //invalid rowIndex ,then return null for bubbling
                                    }
                                }
                            }
                        }

                        break;

                    case keyCodeEnum.END:
                        cellIndex = dataRange.bottomRight().cellIndex();
                        break;

                    case keyCodeEnum.HOME:
                        cellIndex = dataRange.topLeft().cellIndex();

                        break;

                    case keyCodeEnum.LEFT:
                        if (cellIndex > dataRange.topLeft().cellIndex()) {
                            cellIndex--;
                        }

                        break;

                    case keyCodeEnum.RIGHT:
                        if (cellIndex < dataRange.bottomRight().cellIndex()) {
                            cellIndex++;
                        }

                        break;
                }

                if (rowIndex >= 0) {
                    nextCell = new wijmo.grid.cellInfo(cellIndex, rowIndex, this), column = nextCell.column();

                    if (column && column.rowMerge && (column.rowMerge !== "none")) {
                        var lookDown = (keyCode == keyCodeEnum.ENTER || keyCode == keyCodeEnum.DOWN || keyCode == keyCodeEnum.PAGE_DOWN), test = nextCell._clone(), cell = null;

                        while (!(cell = test.tableCell()) && test._isRendered()) {
                            rowIndex = (lookDown) ? rowIndex + 1 : rowIndex - 1;
                            test = new wijmo.grid.cellInfo(cellIndex, rowIndex, this);
                        }

                        if (cell) {
                            nextCell = test;
                        }
                    }
                }

                return nextCell;
            };

            // test whether element is a part of this wijgrid's instance or not
            wijgrid.prototype._testForThis = function (element) {
                var marker = wijgrid.CSS.outerDivMarker;

                while (element) {
                    if (element.className && element.className.indexOf && element.className.indexOf(marker) >= 0) {
                        return this.mOuterDiv[0] === element;
                    }

                    element = element.parentNode;
                }

                return false;
            };

            wijgrid.prototype._findUntilOuterDiv = function (start, tagsToFind) {
                var current = start, outerDiv = this.mOuterDiv[0], stopper, nodeName, item = null;

                for (; current; current = current.parentNode) {
                    nodeName = current.nodeName && current.nodeName.toLowerCase();

                    if (nodeName) {
                        if (current === outerDiv) {
                            stopper = current;
                            break;
                        }

                        if (tagsToFind[nodeName]) {
                            item = current;
                        }
                    }
                }

                return stopper ? item : null;
            };

            wijgrid.prototype._freezingAllowed = function () {
                return this._lgGetScrollMode() !== "none" && !this._hasSpannedCells();
            };

            wijgrid.prototype._getStaticIndex = function (bRow) {
                if (!this._freezingAllowed()) {
                    return -1;
                }

                var result, dataRange = this._getDataCellsRange(1 /* rendered */);

                if (bRow) {
                    result = Math.min(this._lgGetStaticRowIndex(), dataRange.bottomRight().rowIndex());
                } else {
                    result = Math.min(this._lgGetStaticColumnIndex(), dataRange.bottomRight().cellIndex());
                }

                if (result < -1) {
                    result = -1;
                }

                return result;
            };

            wijgrid.prototype._getStaticOffsetIndex = function (isColumn) {
                var index = 0;

                if (isColumn) {
                    index += this._virtualLeaves().length; // row headers are always fixed
                } else {
                    index = this._columnsHeadersTable().length; //the whole header is fixed in case of staticRowIndex >= 0.

                    if (this.options.showFilter) {
                        index++; // filter row is placed inside the header, so it is fixed too.
                    }
                }

                return index;
            };

            // index of the fixed leaf inside the visibleLeaves collection. rowHeader is always fixed.
            wijgrid.prototype._getRealStaticColumnIndex = function () {
                var offsetStaticIndex = this._getStaticOffsetIndex(true), staticColumnIndex = this._getStaticIndex(false), realIndex = staticColumnIndex + offsetStaticIndex;

                if (staticColumnIndex >= 0) {
                    var leaves = this._visibleLeaves(), allColumns = this._allColumns(), len = leaves.length;

                    if (offsetStaticIndex > 0) {
                        allColumns = allColumns.slice(offsetStaticIndex - 1, -1); // remove rowHeader
                    }

                    if (realIndex < len - 1) {
                        var parent = wijmo.grid.getTompostParent(leaves[realIndex], allColumns);

                        // If child column of some band is fixed then the top and right-most column of the root band contained current column will be fixed.
                        if (parent) {
                            for (realIndex++; realIndex < len; realIndex++) {
                                var nextParent = wijmo.grid.getTompostParent(leaves[realIndex], allColumns);
                                if (nextParent !== parent) {
                                    realIndex--;
                                    break;
                                }
                            }
                        }
                    }

                    if (realIndex >= len) {
                        realIndex = len - 1;
                    }
                }

                return realIndex;
            };

            // header is always fixed
            wijgrid.prototype._getRealStaticRowIndex = function () {
                var offsetStaticIndex = this._getStaticOffsetIndex(false);

                return this._getStaticIndex(true) + offsetStaticIndex;
            };

            wijgrid.prototype._hasMerging = function () {
                var leaves = this._leaves(), result = false;

                for (var i = 0, len = leaves.length; (i < len) && !result; i++) {
                    var leafOpt = leaves[i].options;
                    result = result || (leafOpt._parentVis && (leafOpt.rowMerge && (leafOpt.rowMerge !== "none"))); // merged visible column?
                }

                return result;
            };

            wijgrid.prototype._hasBands = function () {
                var columns = this._allColumns();

                for (var i = 0; i < columns.length; i++) {
                    if (columns[i] instanceof wijmo.grid.c1bandfield) {
                        return true;
                    }
                }

                return false;
            };

            wijgrid.prototype._hasDetail = function () {
                var d = this.options.detail;
                return d && d.relation && d.relation.length ? d : null;
            };

            wijgrid.prototype._hasGrouping = function () {
                var leaves = this._leaves(), result = false;

                for (var i = 0, len = leaves.length; (i < len) && !result; i++) {
                    var leafOpt = leaves[i].options;
                    result = leafOpt.groupInfo && (leafOpt.groupInfo.position !== "none"); // grouped column?
                }

                return result;
            };

            wijgrid.prototype._hasSpannedCells = function () {
                return this._hasGrouping() || this._hasMerging() || (this._hasDetail() !== null);
            };

            wijgrid.prototype._columnsHeadersTable = function (value) {
                if (arguments.length) {
                    this.mColumnsHeadersTable = value;
                    ;
                }

                return this.mColumnsHeadersTable;
            };

            wijgrid.prototype._view = function () {
                return this.mView;
            };

            wijgrid.prototype._originalFooterRowData = function () {
                var footer = this.mTFoot;

                return (footer && footer.length) ? footer[0] : null;
            };

            wijgrid.prototype._originalHeaderRowData = function () {
                var header = this.mTHead;

                return (header && header.length) ? header[header.length - 1] : null;
            };

            // set one or more attribute and store original values in the this._originalAttr object if $element == this.element.
            // (key, value), (map)
            wijgrid.prototype._setAttr = function ($element, key, value) {
                var self = this;

                if ($element === this.element) {
                    if (arguments.length === 2) {
                        $.each(key, function (k, v) {
                            if (!(k in self._originalAttr)) {
                                self._originalAttr[k] = $element.attr(k);
                            }
                        });

                        return $element.attr(key);
                    } else {
                        if (!(key in this._originalAttr)) {
                            this._originalAttr[key] = $element.attr(key);
                        }

                        return $element.attr(key, value);
                    }
                } else {
                    return (arguments.length === 3) ? $element.attr(key, value) : $element.attr(key);
                }

                return this;
            };

            // used by virtual scrolling
            wijgrid.prototype._totalRowsCount = function () {
                /*if (this._dataStore.isDynamic()) {
                return this._dataStore.totalCount();
                }*/
                return this.mSketchTable.count();
            };

            wijgrid.prototype._renderableRowsCount = function () {
                return this._renderableRowsRange().capacity();
            };

            wijgrid.prototype._trackScrollingPosition = function (x, y, scrollLeft) {
                this.mScrollingState.x = x;
                this.mScrollingState.y = y;

                if (scrollLeft != null) {
                    this.mScrollingState.scrollLeft = scrollLeft;
                }
            };

            wijgrid.prototype._trackScrollingIndex = function (index) {
                this.mScrollingState.index = index;
            };

            wijgrid.prototype._uid = function () {
                if (this.mUID === undefined) {
                    this.mUID = wijmo.grid.getUID();
                }

                return "wijgrid" + this.mUID;
            };

            wijgrid.prototype._updateSelection = function (e, extendMode) {
                var eventType = (e && (e.type || "").toLowerCase()) || "", selection = this.selection(), currentCell = this.currentCell();

                extendMode = extendMode || 0 /* none */;

                selection.beginUpdate();

                if (eventType) {
                    if (currentCell._isValid()) {
                        if (!selection._anchorCell()) {
                            selection._startNewTransaction(currentCell); // attach selection to the current cell
                        }

                        switch (eventType) {
                            case "focusin":
                            case "click":
                                if (!e.shiftKey || !selection._multipleEntitiesAllowed()) {
                                    selection._startNewTransaction(currentCell);
                                }

                                if (e.shiftKey && e.ctrlKey) {
                                    selection._clearRange(new wijmo.grid.cellInfoRange(currentCell, currentCell), extendMode);
                                } else {
                                    selection._selectRange(new wijmo.grid.cellInfoRange(selection._anchorCell(), currentCell), e.ctrlKey, e.shiftKey, extendMode, null);
                                }

                                break;

                            case "keydown":
                                if (!e.shiftKey || !selection._multipleEntitiesAllowed()) {
                                    selection._startNewTransaction(currentCell);
                                }

                                selection._selectRange(new wijmo.grid.cellInfoRange(selection._anchorCell(), currentCell), false, e.shiftKey, 0 /* none */, null);

                                break;
                        }
                    }
                } else {
                    // * move selection to the current position *
                    selection.clear();

                    if (currentCell._isValid()) {
                        selection._startNewTransaction(currentCell); // attach selection to the current cell
                        selection._selectRange(new wijmo.grid.cellInfoRange(currentCell, currentCell), false, false, 0 /* none */, null);
                    }
                }

                selection.endUpdate(e);
            };

            wijgrid.prototype._viewPortBounds = function (value) {
                if (arguments.length) {
                    this.mViewPortBounds = value;
                }

                return this.mViewPortBounds;
            };

            //_viewPortBoundsOfEntirelyShownRows() {
            //	var bounds = this._viewPortBounds(),
            //		isLast = false,
            //		count = bounds.end - bounds.start + 1;
            //	if (this._allowVVirtualScrolling()) {
            //		var view = <fixedView> this._view();
            //		if (count < view.getVirtualPageSize()) {
            //			isLast = true;
            //		}
            //	}
            //	if (!isLast) {
            //		bounds = <IRenderBounds> $.extend({}, bounds);
            //		bounds.end--;
            //	}
            //	return bounds;
            //}
            //#region legacy
            // to support legacy scrolling properties.
            wijgrid.prototype._lgGetFreezingMode = function () {
                return this.options.freezingMode || this.options.scrollingSettings.freezingMode;
            };

            wijgrid.prototype._lgGetRowHeight = function () {
                if (this.options.rowHeight !== undefined) {
                    return this.options.rowHeight;
                }

                return this.options.scrollingSettings.virtualizationSettings.rowHeight;
            };

            wijgrid.prototype._lgGetStaticColumnsAlignment = function () {
                return this.options.staticColumnsAlignment || this.options.scrollingSettings.staticColumnsAlignment;
            };

            wijgrid.prototype._lgGetScrollMode = function () {
                return this.options.scrollMode || this.options.scrollingSettings.mode;
            };

            wijgrid.prototype._lgGetStaticColumnIndex = function () {
                if (this.options.staticColumnIndex !== undefined) {
                    return this.options.staticColumnIndex;
                }

                return this.options.scrollingSettings.staticColumnIndex;
            };

            wijgrid.prototype._lgGetStaticRowIndex = function () {
                if (this.options.staticRowIndex !== undefined) {
                    return this.options.staticRowIndex;
                }

                return this.options.scrollingSettings.staticRowIndex;
            };

            //#endregion legacy
            wijgrid.prototype._hideAllFilterDropDownLists = function () {
                $.each(this._visibleLeaves(), function (idx, leaf) {
                    if (leaf instanceof grid.c1field) {
                        leaf._hideDropDownList();
                    }
                });
            };
            wijgrid.WIN_RESIZE_TIMEOUT = 200;

            wijgrid.IGNORE_WIN_RESIZE = false;

            wijgrid.JQDATA_MASTER_INFO_KEY = "masterinfo";

            wijgrid.CSS = {
                wijgrid: "wijmo-wijgrid",
                root: "wijmo-wijgrid-root",
                editedCellMarker: "wijmo-wijgrid-cell-edit",
                outerDivMarker: "wijgridouterdiv",
                inputMarker: "wijgridinput",
                spinnerMarker: "wijgridspinner",
                table: "wijmo-wijgrid-table",
                TH: "wijgridth",
                TD: "wijgridtd",
                cellContainer: "wijmo-wijgrid-innercell",
                aggregateContainer: "wijmo-wijgrid-aggregate",
                rowHeader: "wijmo-wijgrid-rowheader",
                currentRowHeaderCell: "wijmo-wijgrid-current-rowheadercell",
                currentHeaderCell: "wijmo-wijgrid-current-headercell",
                currentCell: "wijmo-wijgrid-current-cell",
                cellAlignLeft: "wijalign-left",
                cellAlignRight: "wijalign-right",
                cellAlignCenter: "wijalign-center",
                filterList: "wijmo-wijgrid-filterlist",
                filter: "wijmo-wijgrid-filter",
                filterInput: "wijmo-wijgrid-filter-input",
                filterTrigger: "wijmo-wijgrid-filter-trigger",
                filterNativeHtmlEditorWrapper: "wijgrid-input-wrapper",
                headerArea: "wijmo-wijgrid-header",
                footerArea: "wijmo-wijgrid-footer",
                headerRow: "wijmo-wijgrid-headerrow",
                row: "wijmo-wijgrid-row",
                dataRow: "wijmo-wijgrid-datarow",
                altRow: "wijmo-wijgrid-alternatingrow",
                emptyDataRow: "wijmo-wijgrid-emptydatarow",
                filterRow: "wijmo-wijgrid-filterrow",
                groupHeaderRow: "wijmo-wijgrid-groupheaderrow",
                groupFooterRow: "wijmo-wijgrid-groupfooterrow",
                groupHeaderRowCollapsed: "wijmo-wijgrid-groupheaderrow-collapsed",
                groupHeaderRowExpanded: "wijmo-wijgrid-groupheaderrow-expanded",
                footerRow: "wijmo-wijgrid-footerrow",
                detailRow: "wijmo-wijgrid-hierarchy-detailrow",
                loadingOverlay: "wijmo-wijgrid-overlay",
                loadingText: "wijmo-wijgrid-loadingtext",
                groupArea: "wijmo-wijgrid-group-area",
                groupAreaEmpty: "wijmo-wijgrid-group-area-empty",
                groupAreaButton: "wijmo-wijgrid-group-button",
                groupAreaButtonSort: "wijmo-wijgrid-group-button-sort",
                groupAreaButtonClose: "wijmo-wijgrid-group-button-close",
                groupToggleVisibilityButton: "wijmo-wijgrid-grouptogglebtn",
                fixedView: "wijmo-wijgrid-fixedview",
                scroller: "wijmo-wijgrid-scroller",
                scrollableContent: "wijmo-wijgrid-scrollable-content",
                dndHelper: "wijmo-wijgrid-dnd-helper",
                dndArrowTopContainer: "wijmo-wijgrid-dnd-arrow-top",
                dndArrowBottomContainer: "wijmo-wijgrid-dnd-arrow-bottom",
                freezingHandleV: "wijmo-wijgrid-freezing-handle-v",
                freezingHandleH: "wijmo-wijgrid-freezing-handle-h",
                freezingHandleContent: "wijmo-wijgrid-freezing-handle-content",
                resizingHandle: "wijmo-wijgrid-resizehandle",
                headerCellSortIcon: "wijmo-wijgrid-sort-icon",
                headerCellText: "wijmo-wijgrid-headertext",
                detailContainerCell: "wijgrid-detail-cell",
                c1basefield: "wijmo-c1basefield",
                c1band: "wijmo-c1band",
                c1field: "wijmo-c1field"
            };
            return wijgrid;
        })(wijmo.wijmoWidget);
        grid.wijgrid = wijgrid;

        wijgrid.prototype.widgetEventPrefix = "wijgrid";
        wijgrid.prototype.mDataPrefix = "wijgrid";
        wijgrid.prototype.mCustomSortOrder = 1000;
        wijgrid.prototype.mPageSizeKey = 10;

        var wijgrid_options = (function () {
            function wijgrid_options() {
                /** @ignore */
                this._htmlTrimMethod = 2 /* all */;
                /** @ignore */
                this.wijMobileCSS = {
                    header: "ui-header ui-bar-a",
                    content: "ui-body-b",
                    stateHover: "ui-btn-down-c",
                    stateActive: "ui-btn-down-c",
                    stateHighlight: "ui-btn-down-e"
                };
                /** @ignore */
                this.wijCSS = {
                    wijgrid: "",
                    wijgridTable: "",
                    wijgridTH: "",
                    wijgridTD: "",
                    wijgridCellContainer: "",
                    wijgridRowHeader: "",
                    wijgridCurrentRowHeaderCell: "",
                    wijgridCurrentHeaderCell: "",
                    wijgridCurrentCell: "",
                    wijgridCellAlignLeft: "",
                    wijgridCellAlignRight: "",
                    wijgridCellAlignCenter: "",
                    wijgridFilterList: "",
                    wijgridFilter: "",
                    wijgridFilterInput: "",
                    wijgridFilterTrigger: "",
                    wijgridFilterNativeHtmlEditorWrapper: "",
                    wijgridHeaderArea: "",
                    wijgridFooterArea: "",
                    wijgridHeaderRow: "",
                    wijgridRow: "",
                    wijgridDataRow: "",
                    wijgridAltRow: "",
                    wijgridEmptyDataRow: "",
                    wijgridFilterRow: "",
                    wijgridGroupHeaderRow: "",
                    wijgridGroupFooterRow: "",
                    wijgridGroupHeaderRowCollapsed: "",
                    wijgridGroupHeaderRowExpanded: "",
                    wijgridFooterRow: "",
                    wijgridDetailRow: "",
                    wijgridLoadingOverlay: "",
                    wijgridLoadingText: "",
                    wijgridGroupArea: "",
                    wijgridGroupAreaButton: "",
                    wijgridGroupAreaButtonSort: "",
                    wijgridGroupAreaButtonClose: "",
                    wijgridGroupToggleVisibilityButton: "",
                    wijgridFixedView: "",
                    wijgridScroller: "",
                    wijgridDndHelper: "",
                    wijgridDndArrowTopContainer: "",
                    wijgridDndArrowBottomContainer: "",
                    wijgridFreezingHandleV: "",
                    wijgridFreezingHandleH: "",
                    wijgridResizingHandle: "",
                    wijgridHeaderCellSortIcon: "",
                    wijgridHeaderCellText: ""
                };
                /** A value indicating whether columns can be moved.
                * @example
                * // Columns cannot be dragged and moved if this option is set to false
                * $("#element").wijgrid({ allowColMoving: false });
                * @remarks
                * This option must be set to true in order to drag column headers to the group area.
                */
                this.allowColMoving = false;
                /** Determines whether the column width can be increased and decreased by dragging the sizing handle, or the edge of the column header, with the mouse.
                * @example
                * // The sizing handle cannot be dragged and column width cannot be changed if this option is set to false
                * $("#element").wijgrid({ allowColSizing: false });
                */
                this.allowColSizing = false;
                /** Determines whether the user can make changes to cell contents in the grid.
                * This option is obsolete. Use the editingMode option instead.
                * @example
                * // Users cannot change cell contents in the grid if this option is set to false
                * $("#element").wijgrid({ allowEditing: false });
                */
                this.allowEditing = false;
                /** Determines whether the user can move the current cell using the arrow keys.
                * @example
                * // Users cannot move the selection using arrow keys if this option is set to false
                * $("#element").wijgrid({ allowKeyboardNavigation: false });
                */
                this.allowKeyboardNavigation = true;
                /** Determines the action to be performed when the user presses the TAB key.
                * @example
                * $("#element").wijgrid({ keyActionTab: "moveAcross" });
                * @remarks
                * This option is invalid when the allowKeyboardNavigation is set to false.
                * Possible values are:
                * "moveAcross": The focus will be kept inside the grid and current selected cell will move cyclically between grid cells when user press TAB or SHIFT+TAB key.
                * "moveAcrossOut": The focus will be able to be moved from the grid to the next focusable element in the tab order when user press TAB key and the current selected cell is the last cell (or press SHIFT+TAB and the current selected cell is the first cell).
                */
                this.keyActionTab = "moveAcross";
                /** Determines whether the grid should display paging buttons. The number of rows on a page is determined by the pageSize option.
                * @example
                * // Grid displays paging buttons when allowPaging is true. The pageSize here sets 5 rows to a page.
                * $("#element").wijgrid({ allowPaging: false, pageSize: 5 });
                */
                this.allowPaging = false;
                /** Determines whether the widget can be sorted by clicking the column header.
                * @example
                * // Sort a column by clicking its header when allowSorting is set to true
                * $("#element").wijgrid({ allowSorting: false });
                */
                this.allowSorting = false;
                /** A value that indicates whether virtual scrolling is allowed. Set allowVirtualScrolling to true when using large amounts of data to improve efficiency.
                * Obsoleted, set the scrollingSettings.virtualization.mode property to "rows" instead.
                * @example
                * $("#element").wijgrid({ allowVirtualScrolling: false });
                * @remarks
                * This option is ignored if the grid uses paging, columns merging or fixed rows. This option cannot be enabled when using dynamic wijdatasource.
                */
                this.allowVirtualScrolling = false;
                /** A value that indicates calendar's options in grid. It works for calendar in inputdate.
                * @remarks Its value is wijcalendar's option, visit
                * http://wijmo.com/docs/wijmo/#Wijmo~jQuery.fn.-~wijcalendar.html for more details.
                * @type {object}
                * @example
                *      $("#eventscalendar").wijgrid(
                *      { calendar: { prevTooltip: "Previous", nextTooltip: "Next" } });
                */
                this.calendar = null;
                /** This function is called each time wijgrid needs to change cell appearence, for example, when the current cell position is changed or cell is selected.
                * Can be used for customization of cell style depending on its state.
                * @example
                * // Make the text of the current cell italic.
                * $("#element").wijgrid({
                *		highlightCurrentCell: true,
                *		cellStyleFormatter: function(args) {
                *			if ((args.row.type & wijmo.grid.rowType.data)) {
                *				if (args.state & wijmo.grid.renderState.current) {
                *					args.$cell.css("font-style", "italic");
                *				} else {
                *					args.$cell.css("font-style", "normal");
                *				}
                *			}
                *		}
                * });
                * @param {wijmo.grid.ICellStyleFormaterArgs} args The data with this function.
                * @remarks
                * The args.state parameters equal to wijmo.grid.renderState.rendering means that the cell is being created,
                * at this moment you can apply general formatting to it indepentant of any particular state, like "current" or "selected".
                */
                this.cellStyleFormatter = undefined;
                /** An array of column options.
                * @example
                * $("#element").wijgrid({ columns: [ { headerText: "column0", allowSort: false }, { headerText: "column1", dataType: "number" } ] });
                */
                this.columns = [];
                /** Determines behavior for column autogeneration. Possible values are: "none", "append", "merge".
                * @example
                * $("#element").wijgrid({ columnsAutogenerationMode: "merge" });
                * @remarks
                * Possible values are:
                * "none": Column auto-generation is turned off.
                * "append": A column will be generated for each data field and added to the end of the columns collection.
                * "merge": Each column having dataKey option not specified will be automatically bound to the first unreserved data field.For each data field not bound to any column a new column will be generated and added to the end of the columns collection.
                *
                * To prevent automatic binding of a column to a data field set its dataKey option to null.
                *
                * Note: columns autogeneration process affects the options of columns and the columns option itself.
                */
                this.columnsAutogenerationMode = "merge";
                /** Determines the culture ID.
                * @example
                * // This code sets the culture to English.
                * $("#element").wijgrid({ culture: "en" });
                * @remarks
                * Please see the https://github.com/jquery/globalize for more information.
                */
                this.culture = "";
                /** A value that indicators the culture calendar to format the text.
                * This option must work with culture option.
                * @example
                * // This code sets the culture and calendar to Japanese.
                * $("#element").wijgrid({ culture: "ja-jp", cultureCalendar: "Japanese" });
                */
                this.cultureCalendar = "";
                /** An array of custom user filters. Use this option if you want to extend the default set of filter operators with your own. Custom filters will be shown in the filter dropdown.
                * @example
                * var oddFilterOp = {
                *	name: "customOperator-Odd",
                *	arity: 1,
                *	applicableTo: ["number"],
                *	operator: function(dataVal) { return (dataVal % 2 !== 0); }
                * }
                *
                * $("#element").wijgrid({ customFilterOperators: [oddFilterOp] });
                */
                this.customFilterOperators = [];
                /** Determines the datasource.
                * Possible datasources include:
                *		1. A DOM table. This is the default datasource, used if the data option is null. Table must have no cells with rowSpan and colSpan attributes.
                *		2. A two-dimensional array, such as [[0, "a"], [1, "b"]].
                *		3. An array of objects, such as [{field0: 0, field1: "a"}, {field0: 1, field1: "b'}].
                *		4. A wijdatasource.
                *		5. A wijdataview.
                * @example
                * // DOM table
                * $("#element").wijgrid();
                * // two-dimensional array
                * $("#element").wijgrid({ data: [[0, "a"], [1, "b"]] });
                */
                this.data = null;
                /**
                * Determines the detail grid settings in a hierarchy grid, which is used as a template for populating detail grids in a hierarchical grid.
                * @remarks
                * Limitations:
                * The following datasources are supported (can be used as a detail.data option): arrays, ArrayDataView, AjaxDataView, ODataView, BreezeDataView.
                * It is not possible to use columns grouping and master-detail hierarchy simultaneously.
                * It is not possible to use virtual scrolling and master-detail hierarchy simultaneously.
                * In a detail grid the filtering ability is disabled for columns which are bounded to detailDataKey fields.
                * @example
                * $("#element").wijgrid({
                *    data: customers,
                *    detail: {
                *       data: orders,
                *       relation: [
                *          { masterDataKey: "ID", detailDataKey: "CUST_ID" }
                *       ]
                *    }
                * });
                */
                this.detail = undefined;
                /** Determines an action to bring a cell in the editing mode when the editingMode option is set to "cell". Possible values are: "click", "doubleClick", "auto".
                * @example
                * $("#element").wijgrid({ editingInitOption: "auto" });
                * @remarks
                * Possible values are:
                *	"click": cell is edited via a single click.
                *	"doubleClick": cell is edited via a double click.
                *	"auto": action is determined automatically depending upon user environment. If user has a mobile platform then "click" is used, "doubleClick" otherwise.
                */
                this.editingInitOption = "auto";
                /** Determines the editing mode. Possible values are: "none", "row", "cell",
                * @example
                * $("#element").wijgrid({
                *    editingMode: "row",
                *    columns: [{
                *       showEditButton: true
                *    }]
                * });
                * @remarks
                * Possible values are:
                * "none": the editing ability is disabled.
                *	"cell": a single cell can be edited via a double click.
                *	"row": a whole row can be edited via a command column.
                */
                this.editingMode = "none";
                /** Determines if the exact column width, in pixels, is used.
                * @example
                * $("#element").wijgrid({ ensureColumnsPxWidth: true });
                * @remarks
                * By default, wijgrid emulates the table element behavior when using a number as the width. This means wijgrid may not have the exact width specified. If exact width is needed, please set the ensureColumnsPxWidth option of wijgrid to true. If this option is set to true, wijgrid will not expand itself to fit the available space.Instead, it will use the width option of each column widget.
                */
                this.ensureColumnsPxWidth = false;
                /** Determines the order of items in the filter drop-down list.
                * Possible values are: "none", "alphabetical", "alphabeticalCustomFirst" and "alphabeticalEmbeddedFirst"
                * @example
                * $("#element").wijgrid({ filterOperatorsSortMode: "alphabeticalCustomFirst" });
                * @remarks
                * Possible values are:
                *	"none": Operators follow the order of addition; built-in operators appear before custom ones.
                *	"alphabetical": Operators are sorted alphabetically.
                *	"alphabeticalCustomFirst": Operators are sorted alphabetically with custom operators appearing before built-in ones.
                *	"alphabeticalEmbeddedFirst": Operators are sorted alphabetically with built-in operators appearing before custom operators.
                *
                * "NoFilter" operator is always first.
                */
                this.filterOperatorsSortMode = "alphabeticalCustomFirst";
                /** Determines whether the user can change position of the static column or row by dragging the vertical or horizontal freezing handle with the mouse. Possible values are: "none", "columns", "rows", "both".
                * Obsoleted, use the scrollingSettings.freezingMode property instead.
                * @example
                * $("#element").wijgrid({ freezingMode: "both" });
                * @remarks
                * Possible values are:
                * "none": The freezing handle cannot be dragged.
                * "columns": The user can drag the vertical freezing handle to change position of the static column.
                * "rows": The user can drag the horizontal freezing handle to change position of the static row.
                * "both": The user can drag both horizontal and vertical freezing handles.
                */
                this.freezingMode = undefined;
                /** Determines the caption of the group area.
                * @example
                * // Set the groupAreaCaption to a string and the text appears above the grid
                * $("#element").wijgrid({ groupAreaCaption: "Drag a column here to group by that column." });
                */
                this.groupAreaCaption = "Drag a column here to group by that column.";
                /** Determines the indentation of the groups, in pixels.
                * @example
                * // Set the groupIndent option to the number of pixels to indent data when grouping.
                * $("#element").wijgrid({ groupIndent: 15 });
                */
                this.groupIndent = 10;
                /** Determines whether the position of the current cell is highlighted or not.
                * @example
                * $("#element").wijgrid({ highlightCurrentCell: false });
                */
                this.highlightCurrentCell = false;
                /** Determines whether hovered row is highlighted or not.
                * @example
                * $("#element").wijgrid({ highlightCurrentCell: true });
                */
                this.highlightOnHover = true;
                /** Determines the text to be displayed when the grid is loading.
                * @example
                * $("#element").wijgrid({ loadingText: "Loading..."});
                */
                this.loadingText = "Loading...";
                /** Cell values equal to this property value are considered null values. Use this option if you want to change default representation of null values (empty strings) with something else.
                * @example
                * $("#element").wijgrid({ nullString: "" });
                * @remarks
                * Case-sensitive for built-in parsers.
                */
                this.nullString = "";
                /** Determines the zero-based index of the current page. You can use this to access a specific page, for example, when using the paging feature.
                * @example
                * $("#element").wijgrid({ pageIndex: 0 });
                */
                this.pageIndex = 0;
                /** Number of rows to place on a single page.
                * The default value is 10.
                * @example
                * // The pageSize here sets 10 rows to a page. The allowPaging option is set to true so paging buttons appear.
                * $("#element").wijgrid({ pageSize: 10 });
                */
                this.pageSize = 10;
                /** Determines the pager settings for the grid including the mode (page buttons or next/previous buttons), number of page buttons, and position where the buttons appear.
                * @example
                * // Display the pager at the top of the wijgrid.
                * $("#element").wijgrid({ pagerSettings: { position: "top" } });
                * @remarks
                * See the wijpager documentation for more information on pager settings.
                */
                this.pagerSettings = {
                    mode: "numeric",
                    pageButtonCount: 10,
                    position: "bottom"
                };
                /** A value indicating whether DOM cell attributes can be passed within a data value.
                * @example
                * // Render the style attribute passed within the data.
                * $("#element").wijgrid({
                *		readAttributesFromData: false });
                *		data: [
                *			[ [1, { "style": "color: red" } ], a ]
                *		]
                * });
                * @remarks
                * This option allows binding collection of values to data and automatically converting them as attributes of corresponded DOM table cells during rendering.
                * Values should be passed as an array of two items, where first item is a value of the data field, the second item is a list of values:
                * $("#element").wijgrid({
                *		data: [
                *			[ [1, { "style": "color: red", "class": "myclass" } ], a ]
                *		]
                * });
                *
                * or
                *
                * $("#element").wijgrid({
                *		data: [
                *			{ col0: [1, { "style": "color: red", "class": "myclass" }], col1: "a" }
                *		]
                * });
                *
                * Note: during conversion wijgrid extracts the first item value and makes it data field value, the second item (list of values) is removed:
                * [ { col0: 1, col1: "a" } ]
                *
                * If DOM table is used as a datasource then attributes belonging to the cells in tBody section of the original table will be read and applied to the new cells.
                *
                * rowSpan and colSpan attributes are not allowed.
                */
                this.readAttributesFromData = false;
                /** Determines the height of a rows when virtual scrolling is used.
                * Obsoleted, use the scrollingSettings.virtualization.rowHeight property instead.
                * @example
                * $("#element").wijgrid({ rowHeight: 20 });
                * @remarks
                * Can be set only during creation
                */
                this.rowHeight = undefined;
                /** Function used for styling rows in wijgrid.
                * @example
                * // Make text of the alternating rows italic.
                * $("#demo").wijgrid({
                *		data: [
                *			[0, "Nancy"], [1, "Susan"], [2, "Alice"], [3, "Kate"]
                *		],
                *		rowStyleFormatter: function (args) {
                *			if ((args.state & wijmo.grid.renderState.rendering) && (args.type & wijmo.grid.rowType.dataAlt)) {
                *				args.$rows.find("td").css("font-style", "italic");
                *			}
                *		}
                * });
                * @param {wijmo.grid.IRowInfo} args The data with this function.
                */
                this.rowStyleFormatter = undefined;
                /** Determines which scrollbars are active and if they appear automatically based on content size.
                * Possbile values are: "none", "auto", "horizontal", "vertical", "both".
                * Obsoleted, use the scrollingSettings.mode property instead.
                * @example
                * // The horizontal and vertical scrollbars are active when the scrollMode is set to both.
                * $("#element").wijgrid({ scrollMode: "both" });
                * @remarks
                * Possible values are:
                *	"none": Scrolling is not used; the staticRowIndex and staticColumnIndex values are ignored.
                *	"auto": Scrollbars appear automatically depending upon content size.
                *	"horizontal": The horizontal scrollbar is active.
                *	"vertical": The vertical scrollbar is active.
                *	"both": Both horizontal and vertical scrollbars are active.
                */
                this.scrollMode = undefined;
                /** Determines the scrolling settings.
                * @example
                * // The horizontal and vertical scrollbars are active when the scrollMode is set to both.
                * $("#element").wijgrid({ scrollingSettings: { mode: "both" } });
                */
                this.scrollingSettings = {
                    freezingMode: "none",
                    mode: "none",
                    staticColumnIndex: -1,
                    staticRowIndex: -1,
                    staticColumnsAlignment: "left",
                    virtualizationSettings: {
                        mode: "none",
                        rowHeight: 19,
                        columnWidth: 100
                    }
                };
                /** Determines which cells, range of cells, columns, or rows can be selected at one time.
                * Possible values are: "none", "singleCell", "singleColumn", "singleRow", "singleRange", "multiColumn", "multiRow" and "multiRange".
                * @example
                * // Set selectionMode to muliColumn and users can select more than one column using the CTRL or SHIFT keys.
                * $("#element").wijgrid({ selectionMode: "multiColumn" });
                * @remarks
                * Possible values are:
                * "none": Selection is turned off.
                * "singleCell": Only a single cell can be selected at a time.
                * "singleColumn": Only a single column can be selected at a time.
                * "singleRow": Only a single row can be selected at a time.
                * "singleRange": Only a single range of cells can be selected at a time.
                * "multiColumn": It is possible to select more than one row at the same time using the mouse and the CTRL or SHIFT keys.
                * "multiRow": It is possible to select more than one row at the same time using the mouse and the CTRL or SHIFT keys.
                * "multiRange": It is possible to select more than one cells range at the same time using the mouse and the CTRL or SHIFT keys.
                */
                this.selectionMode = "singleRow";
                /** A value indicating whether the filter row is visible.
                * Filter row is used to display column filtering interface.
                * @example
                * // Set showFilter to true to view the filter row.
                * $("#element").wijgrid({ showFilter: true });
                */
                this.showFilter = false;
                /** A value indicating whether the footer row is visible.
                * Footer row is used for displaying of tfoot section of original table, and to show totals.
                * @example
                * // Set showFooter to true to view the footer row.
                * $("#element").wijgrid({ showFooter: true });
                */
                this.showFooter = false;
                /** A value indicating whether group area is visible.
                * Group area is used to display headers of groupped columns. User can drag columns from/to group area by dragging column headers with mouse, if allowColMoving option is on.
                * @example
                * // Set showGroupArea to true to display the group area.
                * $("#element").wijgrid({ showGroupArea: true });
                */
                this.showGroupArea = false;
                /** A value indicating whether a selection will be automatically displayed at the current cell position when the wijgrid is rendered.
                * Set this option to false if you want to prevent wijgrid from selecting the currentCell automatically.
                * @example
                * $("#element").wijgrid({ showSelectionOnRender: true });
                */
                this.showSelectionOnRender = true;
                /** A value indicating whether the row header is visible.
                * @example
                * $("#element").wijgrid({ showRowHeader: true });
                */
                this.showRowHeader = false;
                /** Indicates the index of columns that will always be shown on the left when the grid view is scrolled horizontally.
                * Obsoleted, use the scrollingSettings.staticColumnIndex property instead.
                * @example
                * $("#element").wijgrid({ staticColumnIndex: -1 });
                * @remarks
                * Note that all columns before the static column will be automatically marked as static, too.
                * This can only take effect when the scrollMode option is not set to "none".
                * It will be considered "-1" when grouping or row merging is enabled. A "-1" means there is no data column but the row header is static. A zero (0) means one data column and row header are static.
                */
                this.staticColumnIndex = undefined;
                /** Gets or sets the alignment of the static columns area. Possible values are "left", "right".
                * Obsoleted, use the scrollingSettings.staticColumnsAlignment property instead.
                * @example
                * $("#element").wijgrid({ staticColumnsAlignment: "left" });
                * @remarks
                * The "right" mode has limited functionality:
                *  - The showRowHeader value is ignored.
                *  - Changing staticColumnIndex at run-time by dragging the vertical bar is disabled.
                */
                this.staticColumnsAlignment = undefined;
                /** Indicates the index of data rows that will always be shown on the top when the wijgrid is scrolled vertically.
                * Obsoleted, use the scrollingSettings.staticRowIndext property instead.
                * @example
                * $("#element").wijgrid({ staticRowIndex: -1 });
                * @remarks
                * Note, that all rows before the static row will be automatically marked as static, too.
                * This can only take effect when the scrollMode option is not set to "none". This will be considered "-1" when grouping or row merging is enabled.
                * A "-1" means there is no data row but the header row is static.A zero (0) means one data row and the row header are static.
                */
                this.staticRowIndex = undefined;
                /** Gets or sets the virtual number of items in the wijgrid and enables custom paging.
                * Setting option to a positive value activates custom paging, the number of displayed rows and the total number of pages will be determined by the totalRows and pageSize values.
                * @example
                * $("#element").wijgrid({ totalRows: -1 });
                * @remarks
                * In custom paging mode sorting, paging and filtering are not performed automatically.
                * This must be handled manually using the sorted, pageIndexChanged, and filtered events. Load the new portion of data there followed by the ensureControl(true) method call.
                */
                this.totalRows = -1;
                /* --- events */
                /** The afterCellEdit event handler is a function called after cell editing is completed.
                * This function can assist you in completing many tasks, such as in making changes once editing is completed; in tracking changes in cells, columns, or rows; or in integrating custom editing functions on the front end.
                * @event
                * @example
                * // Once cell editing is complete, the function calls the destroy method to destroy the wijcombobox widget and the wijinputnumber widget which are used as the custom editors.
                * $("#element").wijgrid({
                *		afterCellEdit: function(e, args) {
                *			switch (args.cell.column().dataKey) {
                *				case "Position":
                *					args.cell.container().find("input").wijcombobox("destroy");
                *					break;
                *				case "Acquired":
                *					args.cell.container().find("input").wijinputnumber("destroy");
                *					break;
                *			}
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ afterCellEdit: function (e, args) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridaftercelledit", function (e, args) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.IAfterCellEditEventArgs} args The data with this event.
                */
                this.afterCellEdit = null;
                /** The afterCellUpdate event handler is a function that is called after a cell has been updated. Among other functions, this event allows you to track and store the indices of changed rows or columns.
                * @event
                * @example
                * // Once the cell has been updated, the information from the underlying data is dumped into the "#log" element.
                * $("#element").wijgrid({
                *		afterCellUpdate: function(e, args) {
                *			$("#log").html(dump($("#demo").wijgrid("data")));
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ afterCellUpdate: function (e, args) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridaftercellupdate", function (e, args) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.IAfterCellUpdateEventArgs} args The data with this event.
                */
                this.afterCellUpdate = null;
                /** The beforeCellEdit event handler is a function that is called before a cell enters edit mode.
                * The beforeCellEdit event handler assists you in appending a widget, data, or other item to a wijgrid's cells before the cells enter edit mode. This event is cancellable if the editigMode options is set to "cell".
                * @event
                * @example
                * // Allow the user to change the price only if the product hasn't been discontinued:
                * $("#element").wijgrid({
                *		beforeCellEdit: function(e, args) {
                *			return !((args.cell.column().dataKey === "Price") && args.cell.row().data.Discontinued);
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ beforeCellEdit: function (e, args) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridbeforecelledit", function (e, args) {
                *		// some code here
                * });
                *
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.IBeforeCellEditEventArgs} args The data with this event.
                */
                this.beforeCellEdit = null;
                /** The beforeCellUpdate event handler is a function that is called before the cell is updated with new or user-entered data. This event is cancellable if the editingMode options is set to "cell".
                * There are many instances where this event is helpful, such as when you need to check a cell's value before the update occurs or when you need to apply an alert message based on the cell's value.
                * @event
                * @example
                * // In this sample, you use args.value to check the year that the user enters in the "Acquired" column.
                * // If it's less than 1990 or greater than the current year, then the event handler will return false to cancel updating and show the user an alert message.
                * $("#element").wijgrid({
                *		beforeCellUpdate: function(e, args) {
                *			switch (args.cell.column().dataKey) {
                *				case "Acquired":
                *					var $editor = args.cell.container().find("input"),
                *						value = $editor.wijinputnumber("getValue"),
                *						curYear = new Date().getFullYear();
                *
                *					if (value < 1990 || value > curYear) {
                *						$editor.addClass("ui-state-error");
                *						alert("value must be between 1990 and " + curYear);
                *						$editor.focus();
                *						return false;
                *					}
                *
                *					args.value = value;
                *					break;
                *			}
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ beforeCellUpdate: function (e, args) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridbeforecellupdate", function (e, args) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.IBeforeCellUpdateEventArgs} args The data with this event.
                */
                this.beforeCellUpdate = null;
                /** The cellClicked event handler is a function that is called when a cell is clicked. You can use this event to get the information of a clicked cell using the args parameter.
                * @event
                * @example
                * // The sample uses the cellClicked event to trigger an alert when the cell is clicked.
                * $("#element").wijgrid({
                *		cellClicked: function (e, args) {
                *			alert(args.cell.value());
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ cellClicked: function (e, args) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridcellclicked", function (e, args) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.ICellClickedEventArgs} args The data with this event.
                */
                this.cellClicked = null;
                /** The columnDragging event handler is a function that is called when column dragging has been started, but before the wijgrid handles the operation. This event is cancellable.
                * @event
                * @example
                * // Preventing a user from dragging a specific column
                * $("#element").wijgrid({
                *		columnDragging: function (e, args) {
                *			return !(args.drag.dataKey == "ID");
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ columnDragging: function (e, args) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridcolumndragging", function (e, args) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.IColumnDraggingEventArgs} args The data with this event.
                */
                this.columnDragging = null;
                /** The columnDragged event handler is a function that is called when column dragging has been started. You can use this event to find the column being dragged or the dragged column's location.
                * @event
                * @example
                * // Supply a callback function to handle the columnDragged event:
                * $("#element").wijgrid({
                *		columnDragged: function (e, args) {
                *			alert("The '" + args.drag.headerText + "' column is being dragged from the '" + args.dragSource + "' location");
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ columnDragged: function (e, args) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridcolumndragged", function (e, args) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.IColumnDraggedEventArgs} args The data with this event.
                */
                this.columnDragged = null;
                /** The columnDropping event handler is a function that is called when a column is dropped into the columns area, but before wijgrid handles the operation. This event is cancellable.
                * @event
                * @example
                * // Preventing user from dropping any column before the "ID" column.
                * $("#element").wijgrid({
                *		columnDropping: function (e, args) {
                *			return !(args.drop.dataKey == "ID" && args.at == "left");
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ columnDropping: function (e, args) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridcolumndropping", function (e, args) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.IColumnDroppingEventArgs} args The data with this event.
                */
                this.columnDropping = null;
                /** The columnDropped event handler is a function that is called when a column has been dropped into the columns area.
                * @event
                * @example
                * // Supply a callback function to handle the columnDropped event:
                * $("#element").wijgrid({
                *		columnDropped: function (e, args) {
                *			"The '" + args.drag.headerText + "' column has been dropped onto the '" + args.drop.headerText + "' column at the '" + args.at + "' position"
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ columnDropped: function (e, args) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridcolumndropped", function (e, args) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.IColumnDroppedEventArgs} args The data with this event.
                */
                this.columnDropped = null;
                /** The columnGrouping event handler is a function that is called when a column is dropped into the group area, but before the wijgrid handles the operation. This event is cancellable.
                * @event
                * @example
                * // Preventing user from grouping the "UnitPrice" column.
                * $("#element").wijgrid({
                *		columnGrouping: function (e, args) {
                *			return !(args.drag.headerText == "UnitPrice");
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ columnGrouping: function (e, args) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridcolumngrouping", function (e, args) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.IColumnGroupingEventArgs} args The data with this event.
                */
                this.columnGrouping = null;
                /** The columnGrouped event handler is a function that is called when a column has been dropped into the group area.
                * @event
                * @example
                * // Supply a callback function to handle the columnGrouped event:
                * $("#element").wijgrid({
                *		columnGrouped: function (e, args) {
                *			alert("The '" + args.drag.headerText "' column has been grouped");
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ columnGrouped: function (e, args) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridcolumngrouped", function (e, args) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.IColumnGroupedEventArgs} args The data with this event.
                */
                this.columnGrouped = null;
                /** The columnResizing event handler is called when a user resizes the column but before the wijgrid handles the operation. This event is cancellable.
                * @event
                * @example
                * // Prevent setting the width of "ID" column less than 100 pixels
                * $("#element").wijgrid({
                *		columnResizing: function (e, args) {
                *			if (args.column.dataKey == "ID" && args.newWidth < 100) {
                *				args.newWidth = 100;
                *			}
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ columnResizing: function (e, args) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridcolumnresizing", function (e, args) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.IColumnResizingEventArgs} args The data with this event.
                */
                this.columnResizing = null;
                /** The columnResized event handler is called when a user has changed a column's size.
                * @event
                * @example
                * // Supply a callback function to handle the columnGrouped event:
                * $("#element").wijgrid({
                *		columnResized: function (e, args) {
                *			alert("The '" + args.column.headerText + "' has been resized");
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ columnResized: function (e, args) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridcolumnresized", function (e, args) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.IColumnResizedEventArgs} args The data with this event.
                */
                this.columnResized = null;
                /** The columnUngrouping event handler is called when a column has been removed from the group area but before the wjgrid handles the operation. This event is cancellable.
                * @event
                * @example
                * // Preventing user from ungrouping the "UnitPrice" column.
                * $("#element").wijgrid({
                *		columnUngrouping: function (e, args) {
                *			return !(args.column.headerText == "UnitPrice");
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ columnUngrouping: function (e, args) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridcolumnungrouping", function (e, args) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.IColumnUngroupingEventArgs} args The data with this event.
                */
                this.columnUngrouping = null;
                /** The columnUngrouped event handler is called when a column has been removed from the group area.
                * @event
                * @example
                * // Supply a callback function to handle the columnGrouped event:
                * $("#element").wijgrid({
                *		columnUngrouped: function (e, args) {
                *			alert("The '" + args.column.headerText + "' has been ungrouped");
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ columnUngrouped: function (e, args) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridcolumnungrouped", function (e, args) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.IColumnUngroupedEventArgs} args The data with this event.
                */
                this.columnUngrouped = null;
                /** The currentCellChanging event handler is called before the cell is changed. You can use this event to get a selected row or column or to get a data row bound to the current cell. This event is cancellable.
                * @event
                * @example
                * // Gets the data row bound to the current cell.
                * $("#element").wijgrid({
                *		currentCellChanging: function (e, args) {
                *			var rowObj = $(e.target).wijgrid("currentCell").row();
                *			if (rowObj) {
                *				var dataItem = rowObj.data; // current data item (before the cell is changed).
                *			}
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ currentCellChanging: function (e, args) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridcurrentcellchanging", function (e, args) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.ICurrentCellChangingEventArgs} args The data with this event.
                */
                this.currentCellChanging = null;
                /** The currentCellChanged event handler is called after the current cell is changed.
                * @event
                * @example
                * // Gets the data row bound to the current cell.
                * $("#element").wijgrid({
                *		currentCellChanged: function (e, args) {
                *			var rowObj = $(e.target).wijgrid("currentCell").row();
                *			if (rowObj) {
                *				var dataItem = rowObj.data; // current data item (after the cell is changed).
                *			}
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ currentCellChanged: function (e) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridcurrentcellchanged", function (e) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                */
                this.currentCellChanged = null;
                /** The detailCreating event handler is called when wijgrid requires to create a new detail wijgrid.
                * @event
                * @remarks
                * Event receives options of a detail grid to create, which were obtained by cloning the detail option of the master grid.
                * User can alter the detail grid options here and provide a specific datasource within the args.options.data option to implement run-time hierarachy.
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ detailCreating: function (e, args) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgriddetailcreating", function (e, args) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.IDetailCreatingEventArgs} args The data with this event.
                */
                this.detailCreating = null;
                /** The filterOperatorsListShowing event handler is a function that is called before the filter drop-down list is shown. You can use this event to customize the list of filter operators for your users.
                * @event
                * @example
                * // Limit the filters that will be shown to the "Equals" filter operator
                * $("#element").wijgrid({
                *		filterOperatorsListShowing: function (e, args) {
                *			args.operators = $.grep(args.operators, function(op) {
                *				return op.name === "Equals" || op.name === "NoFilter";
                *			}
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ filterOperatorsListShowing: function (e, args) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridfilteroperatorslistshowing", function (e, args) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.IFilterOperatorsListShowingEventArgs} args The data with this event.
                */
                this.filterOperatorsListShowing = null;
                /** The filtering event handler is a function that is called before the filtering operation is started. For example, you can use this event to change a filtering condition before a filter will be applied to the data. This event is cancellable.
                * @event
                * @example
                * // Prevents filtering by negative values
                * $("#element").wijgrid({
                *		filtering: function (e, args) {
                *			if (args.column.dataKey == "Price" && args.value < 0) {
                *				args.value = 0;
                *			}
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ filtering: function (e, args) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridfiltering", function (e, args) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.IFilteringEventArgs} args The data with this event.
                */
                this.filtering = null;
                /** The filtered event handler is a function that is called after the wijgrid is filtered.
                * @event
                * @example
                * //
                * $("#element").wijgrid({
                *		filtered: function (e, args) {
                *			alert("The filtered data contains: " + $(this).wijgrid("dataView").count() + " rows");
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ filtered: function (e, args) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridfiltered", function (e, args) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.IFilteredEventArgs} args The data with this event.
                */
                this.filtered = null;
                /** The groupAggregate event handler is a function that is called when groups are being created and the column object's aggregate option has been set to "custom". This event is useful when you want to calculate custom aggregate values.
                * @event
                * @example
                * // This sample demonstrates using the groupAggregate event handler to calculate an average in a custom aggregate:
                * $("#element").wijgrid({
                *		groupAggregate: function (e, args) {
                *			if (args.column.dataKey == "Price") {
                *				var aggregate = 0;
                *
                *				for (var i = args.groupingStart; i <= args.groupingEnd; i++) {
                *					aggregate += args.data[i].valueCell(args.column.dataIndex).value;
                *				}
                *
                *				aggregate = aggregate/ (args.groupingEnd - args.groupingStart + 1);
                *				args.text = aggregate;
                *			}
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ groupAggregate: function (e, args) {
                *		// some code here
                * }});
                * Bind to the event by type:
                *
                * $("#element").bind("wijgridgroupaggregate", function (e, args) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.IGroupAggregateEventArgs} args The data with this event.
                */
                this.groupAggregate = null;
                /** The groupText event handler is a function that is called when groups are being created and the groupInfo option has the groupInfo.headerText or the groupInfo.footerText options set to "custom". This event can be used to customize group headers and group footers.
                * @event
                * @example
                * // The following sample sets the groupText event handler to avoid empty cells. The custom formatting applied to group headers left certain cells appearing as if they were empty. This code avoids that:
                * $("#element").wijgrid({
                *		groupText: function (e, args) {
                *			if (!args.groupText) {
                *				args.text = "null";
                *			}
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ groupText: function (e, args) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridgrouptext", function (e, args) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.IGroupTextEventArgs} args The data with this event.
                */
                this.groupText = null;
                /** The invalidCellValue event handler is a function called when a cell needs to start updating but the cell value is invalid. So if the value in a wijgrid cell can't be converted to the column target type, the invalidCellValue event will fire.
                * @event
                * @example
                * // Adds a style to the cell if the value entered is invalid
                * $("#element").wijgrid({
                *		invalidCellValue: function (e, args) {
                *			$(args.cell.container()).addClass("ui-state-error");
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ invalidCellValue: function (e, args) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridinvalidcellvalue", function (e, args) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.IInvalidCellValueEventArgs} args The data with this event.
                */
                this.invalidCellValue = null;
                /** The pageIndexChanging event handler is a function that is called before the page index is changed. This event is cancellable.
                * @event
                * @example
                * // Cancel the event by returning false
                * $("#element").wijgrid({
                *		pageIndexChanging: function (e, args) {
                *			return false;
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ pageIndexChanging: function (e, args) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridpageindexchanging", function (e, args) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.IPageIndexChangingEventArgs} args The data with this event.
                */
                this.pageIndexChanging = null;
                /** The pageIndexChanged event handler is a function that is called after the page index is changed, such as when you use the numeric buttons to swtich between pages or assign a new value to the pageIndex option.
                * @event
                * @example
                * // Supply a callback function to handle the pageIndexChanged event:
                * $("#element").wijgrid({
                *		pageIndexChanged: function (e, args) {
                *			alert("The new pageIndex is: " + args.newPageIndex);
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ pageIndexChanged: function (e, args) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridpageindexchanged", function (e, args) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.IPageIndexChangedEventArgs} args The data with this event.
                */
                this.pageIndexChanged = null;
                /** The selectionChanged event handler is a function that is called after the selection is changed.
                * @event
                * @example
                * // Get the value of the first cell of the selected row.
                * $("#element").wijgrid({
                *		selectionMode: "singleRow",
                *		selectionChanged: function (e, args) {
                *			alert(args.addedCells.item(0).value());
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ selectionChanged: function (e, args) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridselectionchanged", function (e, args) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.ISelectionChangedEventArgs} args The data with this event.
                */
                this.selectionChanged = null;
                /** The sorting event handler is a function that is called before the sorting operation is started. This event is cancellable.
                * The allowSorting option must be set to "true" for this event to fire.
                * @event
                * @example
                * // Preventing user from sorting the "ID" column.
                * $("#element").wijgrid({
                *		sorting: function (e, args) {
                *			return !(args.column.headerText === "ID");
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ sorting: function (e, args) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridsorting", function (e, args) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.ISortingEventArgs} args The data with this event.
                */
                this.sorting = null;
                /** The sorted event handler is a function that is called after the widget is sorted. The allowSorting option must be set to "true" to allow this event to fire.
                * @event
                * @example
                * // The following code handles the sorted event and will give you access to the column and the sort direction
                * $("#element").wijgrid({
                *		sorted: function (e, args) {
                *			alert("Column " + args.column.headerText + " sorted in " + args.sortDirection + " order");
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ sorted: function (e, args) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridsorted", function (e, args) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                * @param {wijmo.grid.ISortedEventArgs} args The data with this event.
                */
                this.sorted = null;
                /* events --- */
                /* --- life-cycle events */
                //			/// <summary>
                //			/// The ajaxError event handler. A function called when wijgrid is bound to remote data and
                //			/// the ajax request fails.
                //			/// Default: null.
                //			/// Type: Function.
                //			/// Code example:
                //			/// Supply a callback function to handle the ajaxError event:
                //			/// $("#element").wijgrid({ ajaxError: function (e, args) { } });
                //			/// Bind to the event by type:
                //			/// $("#element").bind("wijgridajaxerror", function (e, args) { });
                //			/// </summary>
                //			/// <param name="e" type="Object">The jQuery.Event object.</param>
                //			/// <param name="args" type="Object">
                //			/// The data corresponded with this event.
                //			/// args.XMLHttpRequest: the XMLHttpRequest object.
                //			/// args.textStatus: a string describing the error type.
                //			/// args.errorThrown: an exception object.
                //			///
                //			/// Refer to the jQuery.ajax.error event documentation for more details on this arguments.
                //			/// </param>
                //			ajaxError: null,
                /** The dataLoading event handler is a function that is called when the wijgrid loads a portion of data from the underlying datasource. This can be used for modification of data sent to server if using dynamic remote wijdatasource.
                * @event
                * @example
                * // This sample allows you to set the session ID when loading a portion of data from the remote wijdatasource:
                * $("#element").wijgrid({
                *		data: new wijdatasource({
                *			proxy: new wijhttpproxy({
                *				// some code here
                *			})
                *		}),
                *		dataLoading: function (e) {
                *			var dataSource = $(this).wijgrid("option", "data");
                *			dataSource.proxy.options.data.sessionID = getSessionID();
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ dataLoading: function (e) {
                * // some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgriddataloading", function (e) {
                * // some code here
                * });
                * @param {Object} e The jQuery.Event object.
                */
                this.dataLoading = null;
                /** The dataLoaded event handler is a function that is called when data is loaded.
                * @event
                * @example
                * // Display the number of entries found
                * $("#element").wijgrid({
                *		dataLoaded: function (e) {
                *			alert($(this).wijgrid("dataView").count());
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ dataLoaded: function (e) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgriddataloaded", function (e) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                */
                this.dataLoaded = null;
                /** The loading event handler is a function that is called at the beginning of the wijgrid's lifecycle. You can use this event to activate a custom load progress indicator.
                * @event
                * @example
                * // Creating an indeterminate progressbar during loading
                * $("#element").wijgrid({
                *		loading: function (e) {
                *			$("#progressBar").show().progressbar({ value: false });
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ loading: function (e) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridloading", function (e) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                */
                this.loading = null;
                /** The loaded event handler is a function that is called at the end the wijgrid's lifecycle when wijgrid is filled with data and rendered. You can use this event to manipulate the grid html content or to finish a custom load indication.
                * @event
                * @example
                * // The loaded event in the sample below ensures that whatever is selected on load is cleared
                * $("#element").wijgrid({
                *		loaded: function (e) {
                *			$(e.target).wijgrid("selection").clear(); // clear selection
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ loaded: function (e) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridloaded", function (e) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                */
                this.loaded = null;
                /** The rendering event handler is a function that is called when the wijgrid is about to render. Normally you do not need to use this event.
                * @event
                * @example
                * $("#element").wijgrid({
                *		rendering: function (e) {
                *			alert("rendering");
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ rendering: function (e) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridrendering", function (e) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                */
                this.rendering = null;
                /** The rendered event handler is a function that is called when the wijgrid is rendered. Normally you do not need to use this event.
                * @event
                * @example
                * $("#element").wijgrid({
                *		rendered: function (e) {
                *			alert("rendered");
                *		}
                * });
                * @remarks
                * You can bind to the event either by type or by name.
                * Bind to the event by name:
                * $("#element").wijgrid({ rendered: function (e) {
                *		// some code here
                * }});
                *
                * Bind to the event by type:
                * $("#element").bind("wijgridrendered", function (e) {
                *		// some code here
                * });
                * @param {Object} e The jQuery.Event object.
                */
                this.rendered = null;
            }
            return wijgrid_options;
        })();

        //wijgrid.prototype.options = $.extend(true, {}, wijmoWidget.prototype.options, new wijgrid_options());
        wijgrid.prototype.options = wijmo.grid.extendWidgetOptions(wijmo.wijmoWidget.prototype.options, new wijgrid_options());

        $.wijmo.registerWidget("wijgrid", wijgrid.prototype);
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));


/// <reference path="interfaces.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    (function (grid) {
        var $ = jQuery;

        /** @ignore */
        var SketchObject = (function () {
            function SketchObject(attr) {
                if (attr) {
                    this.__attr = attr;
                }
            }
            SketchObject.prototype.ensureAttr = function () {
                this.__attr = this.__attr || {};
                return this.__attr;
            };

            SketchObject.prototype.attr = function (name, value) {
                if (arguments.length == 0) {
                    return this.__attr;
                }

                if (arguments.length == 1) {
                    return this.__attr ? this.__attr[name] : null;
                } else {
                    this.ensureAttr()[name] = value;
                }
            };

            SketchObject.prototype.style = function (name, newValue) {
                if (arguments.length == 0) {
                    return this.__style;
                } else if (arguments.length == 1) {
                    return this.__style && this.__style[name];
                } else {
                    this.ensureStyle()[name] = newValue;
                }
            };
            SketchObject.prototype.deleteAttr = function (name) {
                if (this.__attr) {
                    delete this.__attr[name];
                }
            };
            SketchObject.prototype.deleteStyle = function (name) {
                if (this.__style) {
                    delete this.__style[name];
                }
            };

            /** Creates style object if it does not exist. Then returns it */
            SketchObject.prototype.ensureStyle = function () {
                this.__style = this.__style || {};
                return this.__style;
            };
            return SketchObject;
        })();
        grid.SketchObject = SketchObject;

        /** @ignore */
        var SketchCell = (function (_super) {
            __extends(SketchCell, _super);
            function SketchCell(attr) {
                _super.call(this, attr);
            }
            SketchCell.prototype.visible = function (newValue) {
                if (arguments.length == 0) {
                    return !(this._visible === false);
                } else {
                    this._visible = newValue;
                }
            };
            return SketchCell;
        })(SketchObject);
        grid.SketchCell = SketchCell;

        /** @ignore */
        /* A sketch cell with a value */
        var ValueCell = (function (_super) {
            __extends(ValueCell, _super);
            function ValueCell(value, attr) {
                _super.call(this, attr);
                this.value = value;
            }
            return ValueCell;
        })(SketchCell);
        grid.ValueCell = ValueCell;

        /** @ignore */
        /* A sketch cell with raw html */
        var HtmlCell = (function (_super) {
            __extends(HtmlCell, _super);
            function HtmlCell(html, attr) {
                _super.call(this, attr);

                this.html = html || "";
            }
            HtmlCell.nbsp = function () {
                return new HtmlCell("&nbsp;", null);
            };
            return HtmlCell;
        })(SketchCell);
        grid.HtmlCell = HtmlCell;

        /** @ignore */
        var HeaderCell = (function (_super) {
            __extends(HeaderCell, _super);
            function HeaderCell(column, attrs) {
                _super.call(this, attrs);

                this.column = column;
            }
            return HeaderCell;
        })(SketchCell);
        grid.HeaderCell = HeaderCell;

        /** @ignore */
        var SketchRow = (function (_super) {
            __extends(SketchRow, _super);
            function SketchRow(rowType, renderState, attrs) {
                _super.call(this, attrs);

                this.rowType = rowType;
                this.renderState = renderState;
                this.extInfo = { state: 0 /* none */ };
            }
            /** returns true if this is data\ dataAlt\ dataHierarchyHeader\ dataHierarchyDetail row */
            SketchRow.prototype.isDataRow = function () {
                return (this.rowType & 2 /* data */) === 2 /* data */;
            };

            /** returns true if this is data\ dataAlt row */
            SketchRow.prototype.isPureDataRow = function () {
                var rt = wijmo.grid.rowType;
                return (this.rowType & ~4 /* dataAlt */) === 2 /* data */;
            };

            SketchRow.prototype.dataItemIndex = function (offset) {
                if (typeof offset === "undefined") { offset = 0; }
                return -1;
            };

            SketchRow.prototype.cellCount = function () {
                return this._cells ? this._cells.length : 0;
            };

            /** create the cell table if it does not exist yet */
            SketchRow.prototype._ensureCells = function () {
                this._cells = this._cells || [];
            };

            /** add a cell to the end */
            SketchRow.prototype.add = function (elem) {
                this._ensureCells();
                this._cells.push(elem);
            };

            /** insert a cell */
            SketchRow.prototype.insert = function (index, elem) {
                this._ensureCells();
                this._cells.splice(index, 0, elem);
            };

            SketchRow.prototype.cell = function (index) {
                return this._cells[index];
            };
            SketchRow.prototype.valueCell = function (index) {
                return this.cell(index);
            };

            /** remove a cell by index */
            SketchRow.prototype.removeAt = function (index) {
                if (!this._cells) {
                    throw "Wrong index";
                }
                this._cells.splice(index, 1);
            };

            /** remove all cells */
            SketchRow.prototype.clear = function () {
            };

            SketchRow.prototype.getRowInfo = function () {
                return {
                    type: this.rowType,
                    state: this.renderState,
                    sectionRowIndex: null,
                    dataRowIndex: null,
                    virtualDataItemIndex: null,
                    dataItemIndex: this.dataItemIndex(),
                    sketchRowIndex: null,
                    $rows: null,
                    _extInfo: this.extInfo
                };
            };
            return SketchRow;
        })(SketchObject);
        grid.SketchRow = SketchRow;

        /** @ignore */
        var SketchDataRow = (function (_super) {
            __extends(SketchDataRow, _super);
            //private mDataAccessor: (index: number) => any;
            function SketchDataRow(originalRowIndex /*, dataAccessor: (index: number) => any*/ , renderState, attrs) {
                _super.call(this, 2 /* data */ | ((originalRowIndex % 2) == 1 ? 4 /* dataAlt */ : 0), renderState, attrs);

                //this.mDataAccessor = dataAccessor;
                this.originalRowIndex = originalRowIndex;
            }
            //data(offset = 0): any {
            //	return this.mDataAccessor.call(this, this.dataItemIndex(offset));
            //}
            SketchDataRow.prototype.dataItemIndex = function (offset) {
                if (typeof offset === "undefined") { offset = 0; }
                return offset + this.originalRowIndex;
            };

            SketchDataRow.prototype.isDataRow = function () {
                return true;
            };
            return SketchDataRow;
        })(SketchRow);
        grid.SketchDataRow = SketchDataRow;

        /** @ignore */
        var SketchGroupRow = (function (_super) {
            __extends(SketchGroupRow, _super);
            function SketchGroupRow(header, attrs) {
                var rowType = header ? 16 /* groupHeader */ : 32 /* groupFooter */;
                _super.call(this, rowType, 1 /* rendering */, attrs);
            }
            SketchGroupRow.prototype.getRowInfo = function () {
                var info = _super.prototype.getRowInfo.call(this);
                if (this.groupByValue !== undefined) {
                    info.groupByValue = this.groupByValue;
                }
                return info;
            };
            return SketchGroupRow;
        })(SketchRow);
        grid.SketchGroupRow = SketchGroupRow;

        /** @ignore */
        var SketchHeaderRow = (function (_super) {
            __extends(SketchHeaderRow, _super);
            function SketchHeaderRow(attrs) {
                _super.call(this, 1 /* header */, 1 /* rendering */, attrs);
            }
            return SketchHeaderRow;
        })(SketchRow);
        grid.SketchHeaderRow = SketchHeaderRow;

        /** @ignore */
        var SketchDetailRow = (function (_super) {
            __extends(SketchDetailRow, _super);
            function SketchDetailRow(attrs) {
                _super.call(this, 1024 /* detail */, 1 /* rendering */, attrs);
            }
            return SketchDetailRow;
        })(SketchRow);
        grid.SketchDetailRow = SketchDetailRow;

        /** @ignore */
        var SketchTable = (function () {
            function SketchTable() {
                this._table = [];
            }
            SketchTable.prototype.getRawTable = function () {
                return this._table;
            };

            SketchTable.prototype.row = function (index) {
                return this._table[index];
            };

            SketchTable.prototype.valueAt = function (rowIndex, colIndex) {
                return this.row(rowIndex).valueCell(colIndex).value;
            };

            SketchTable.prototype.wijgridDataAttrValueAt = function (rowIndex, colIndex) {
                return this.row(rowIndex).valueCell(colIndex).attr("wijgrid-data");
            };

            SketchTable.prototype.count = function (newValue) {
                if (typeof newValue === "number") {
                    this._table.length = newValue;
                }
                return this._table.length;
            };

            SketchTable.prototype.add = function (row) {
                this._table.push(row);
            };
            SketchTable.prototype.insert = function (index, row) {
                this._table.splice(index, 0, row);
            };
            SketchTable.prototype.clear = function () {
                this._table.length = 0;
            };
            SketchTable.prototype.indexOf = function (element) {
                return this._table.indexOf(element);
            };
            SketchTable.prototype.remove = function (index, count) {
                if (typeof count === "undefined") { count = 1; }
                this._table.splice(index, count);
            };
            SketchTable.prototype.removeFirst = function (count) {
                if (typeof count === "undefined") { count = 1; }
                this._table.splice(0, count);
            };
            SketchTable.prototype.removeLast = function (count) {
                if (typeof count === "undefined") { count = 1; }
                this._table.splice(this._table.length - count, count);
            };

            SketchTable.prototype.replace = function (index, row) {
                var oldRows = this._table.splice(index, 1, row);

                if (oldRows && oldRows.length && row) {
                    row.extInfo = oldRows[0].extInfo;
                }
            };

            SketchTable.prototype.updateIndexes = function () {
                for (var i = 0; i < this._table.length; i++) {
                    var sketchRow = this._table[i];

                    if (this._table[i].isDataRow()) {
                        sketchRow.originalRowIndex = i;
                    }
                }
            };

            SketchTable.prototype.isLazy = function () {
                return false;
            };
            SketchTable.prototype.ensureNotLazy = function () {
            };
            SketchTable.prototype.find = function (startFrom, callback) {
                var f = this.findEx(startFrom, callback);
                return f ? f.val : null;
            };

            SketchTable.prototype.findIndex = function (startFrom, callback) {
                var f = this.findEx(startFrom, callback);
                return f ? f.at : -1;
            };

            SketchTable.prototype.findEx = function (startFrom, callback) {
                var cnt = this.count();

                for (var i = startFrom; i < cnt; i++) {
                    var row = this.row(i);

                    if (callback(this.row(i)) === true) {
                        return {
                            at: i,
                            val: row
                        };
                    }
                }

                return null;
            };
            return SketchTable;
        })();
        grid.SketchTable = SketchTable;

        /** @ignore */
        var LazySketchTable = (function (_super) {
            __extends(LazySketchTable, _super);
            function LazySketchTable(source) {
                _super.call(this);
                this.mIsLazy = true;
                this.pageSize = 30;
                if (source == null) {
                    throw "Row source is null";
                }
                this.mSource = source;
                this._table.length = source.count();
            }
            LazySketchTable.prototype.isLazy = function () {
                return this.mIsLazy;
            };

            /** Convert to not lazy and create rows if they don't exist*/
            LazySketchTable.prototype.ensureNotLazy = function () {
                if (!this.isLazy())
                    return;
                this.ensureRange();
                this.mIsLazy = false;
            };

            LazySketchTable.prototype.invalidate = function () {
                this._table = new Array(this.mSource.count());
                if (!this.isLazy()) {
                    this.updateRange();
                }
            };

            LazySketchTable.prototype.row = function (index) {
                if (!_super.prototype.row.call(this, index)) {
                    this.ensureRange(Math.max(0, index - this.pageSize / 2), this.pageSize);
                }

                return _super.prototype.row.call(this, index);
            };

            /** Create sketch rows if the don't exist yet.
            * Cannot create anything other than data rows.
            * Requires source
            */
            LazySketchTable.prototype.ensureRange = function (start, length) {
                if (typeof start === "undefined") { start = 0; }
                if (typeof length === "undefined") { length = this._table.length - start; }
                if (!this.isLazy())
                    return;
                if (start < 0) {
                    throw "Wrong range start";
                }

                this._table.length = this.mSource.count();
                if (this._table.length == 0) {
                    if (length > 0) {
                        throw "Wrong range length";
                    }
                    return;
                }

                while (start < this._table.length && this._table[start]) {
                    start++;
                }

                // is there anything to create?
                if (start >= this._table.length)
                    return;

                var last = Math.min(start + length - 1, this._table.length - 1);

                while (last >= start && this._table[last]) {
                    last--;
                }

                length = last - start + 1;
                if (length > 0) {
                    this.updateRange(start, length);
                }
            };
            LazySketchTable.prototype.updateRange = function (start, length) {
                if (typeof start === "undefined") { start = 0; }
                if (typeof length === "undefined") { length = this._table.length - start; }
                if (this.mSource == null) {
                    throw "Cannot create sketch row because source is null";
                }
                this.mSource.getRange(start, length, this._table, start);
            };
            return LazySketchTable;
        })(SketchTable);
        grid.LazySketchTable = LazySketchTable;

        
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="../../../External/declarations/jquery.d.ts"/>
/// <reference path="interfaces.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    (function (grid) {
        var $ = jQuery;

        var widgetEmulator = (function () {
            function widgetEmulator(options, emulatedWidgetName) {
                var names = emulatedWidgetName.split(".");

                this.namespace = names[0];
                this.widgetName = names[1];
                this.widgetFullName = this.namespace + "-" + this.widgetName;

                $.fn[this.widgetName] = function (funcName) {
                    var result = undefined, args = Array.prototype.slice.call(arguments, 1);

                    if ((typeof (funcName) === "string") && this.length) {
                        this.each(function () {
                            var instance = $.data(this, widgetEmulator.DATA_INSTANCE_PROP);
                            if (instance) {
                                if (!$.isFunction(instance[funcName]) || funcName.charAt(0) === "_") {
                                    return false;
                                }

                                result = instance[funcName].apply(instance, args);

                                if (result !== undefined) {
                                    return false;
                                }
                            }
                        });
                    }

                    return result;
                };

                this.options = options || {};
                this._destroyed = false;

                this._provideDefaults();
            }
            widgetEmulator.prototype.option = function (key, value) {
                var options = key;

                if (!arguments.length) {
                    return this.options;
                }

                if (typeof (key) === "string") {
                    if (value === undefined) {
                        return this.options[key];
                    }

                    options = {};
                    options[key] = value;

                    this._setOptions(options);
                }

                return this;
            };

            widgetEmulator.prototype.enable = function () {
                this._setOption("disabled", false);
            };

            widgetEmulator.prototype.disable = function () {
                this._setOption("disabled", true);
            };

            widgetEmulator.prototype.destroy = function () {
                try  {
                    if (!this._destroyed) {
                        this._destroy();

                        this.element.unbind("." + this.widgetName);
                        this.element.removeData(this.widgetFullName);
                    }
                } finally {
                    this._destroyed = true;
                }
            };

            widgetEmulator.prototype.widget = function () {
                return this.element;
            };

            widgetEmulator.prototype._destroy = function () {
            };

            widgetEmulator.prototype._setOptions = function (options) {
                var self = this;

                $.each(options, function (key, value) {
                    self._setOption(key, value);
                });
            };

            widgetEmulator.prototype._attachToElement = function (element) {
                var _this = this;
                this.element = element;

                if (this.element) {
                    if (this.options.disabled) {
                        this.disable();
                    }

                    this.element.data(widgetEmulator.DATA_INSTANCE_PROP, this); // store class instance (used by uiDragndrop).

                    this.element.bind("remove." + this.widgetName, function () {
                        _this.destroy();
                    });
                }
            };

            widgetEmulator.prototype._provideDefaults = function () {
                this.options.disabled = this.options.disabled || false;
            };

            widgetEmulator.prototype._setOption = function (key, value) {
                var presetFunc = this["_preset_" + key], oldValue = this.options[key];

                if (presetFunc) {
                    value = presetFunc.apply(this, [value, oldValue]); // .apply(this, arguments);  note: there is no dynamic linkage between the arguments and the formal parameter values when strict mode is used
                }

                if (value !== oldValue) {
                    var postsetFunc = this["_postset_" + key];

                    this.options[key] = value; // set option

                    this._prepostsetOption(key, value);

                    if (postsetFunc) {
                        postsetFunc.apply(this, [value, oldValue]);
                    }
                }
            };

            widgetEmulator.prototype._prepostsetOption = function (key, value) {
            };

            widgetEmulator.prototype._postset_disabled = function (value, oldValue) {
                //if (this.element) {
                //	this.element[value ? "addClass" : "removeClass"](this.widgetFullName + "-disabled ui-state-disabled").attr("aria-disabled", value);
                //}
            };

            widgetEmulator.prototype._eventKey = function (eventName) {
                return eventName + "." + this.widgetName;
            };
            widgetEmulator.DATA_INSTANCE_PROP = "wijemuinstance";
            return widgetEmulator;
        })();
        grid.widgetEmulator = widgetEmulator;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

var wijmo;
(function (wijmo) {
    (function (_grid) {
        var fieldFactories = [];

        function registerColumnFactory(factory) {
            if (!$.isFunction(factory)) {
                throw "'factory' must be a function.";
            }

            fieldFactories.push(factory);
        }
        _grid.registerColumnFactory = registerColumnFactory;

        function asColumnInstance(grid, column) {
            for (var i = fieldFactories.length - 1; i >= 0; i--) {
                var instance = fieldFactories[i](grid, column);
                if (instance) {
                    return instance;
                }
            }

            throw "Unsupported column.";
        }
        _grid.asColumnInstance = asColumnInstance;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

var wijmo;
(function (wijmo) {
    (function (_grid) {
        var $ = jQuery;

        var c1basefield = (function (_super) {
            __extends(c1basefield, _super);
            function c1basefield(wijgrid, options, widgetName) {
                _super.call(this, options, widgetName || c1basefield.WIDGET_NAME);
                this.mFirstVisible = undefined;

                this.mWijgrid = wijgrid;
            }
            c1basefield.test = function (column) {
                return true;
            };

            c1basefield.prototype._destroy = function () {
                var wijgrid = this._owner(), defCSS = this._defCSS(), wijCSS = this._wijCSS();

                if (this.element) {
                    this.element.find("*").unbind("." + this.widgetName);

                    this.element.removeClass(wijCSS.widget + " " + defCSS.c1basefield + " " + wijCSS.stateDefault).html(this.element.find("." + defCSS.headerCellText).html()); // restore initial cell content
                }

                if (wijgrid && wijgrid._UIDragndrop()) {
                    wijgrid._UIDragndrop(false).detach(this);
                }

                _super.prototype._destroy.apply(this, arguments);
            };

            c1basefield.prototype._owner = function () {
                return this.mWijgrid;
            };

            c1basefield.prototype._attachToElement = function (element) {
                _super.prototype._attachToElement.apply(this, arguments);

                var grid = this._owner();

                if (grid.options.allowColMoving && this._draggable()) {
                    grid._UIDragndrop(true).attach(this);
                }
            };

            c1basefield.prototype._provideDefaults = function () {
                _super.prototype._provideDefaults.call(this);

                wijmo.grid.shallowMerge(this.options, c1basefield.prototype.options);
            };

            c1basefield.prototype._defCSS = function () {
                return wijmo.grid.wijgrid.CSS;
            };

            c1basefield.prototype._wijCSS = function () {
                if (this.mWijgrid) {
                    return this.mWijgrid.options.wijCSS;
                }

                return {};
            };

            //#region rendering
            c1basefield.prototype._initializeCell = function (cell, cellIndex, container, formattedValue, row) {
                var rt = wijmo.grid.rowType, useDefault = true, args = {
                    $cell: cell,
                    $container: container,
                    column: this.options,
                    formattedValue: formattedValue,
                    row: row,
                    afterDefaultCallback: null
                };

                // apply rowHeight option to all tbody rows if virtual scrolling is used.
                if (((row.type & 2 /* data */) || (row.type === 32 /* groupFooter */) || (row.type === 16 /* groupHeader */)) && this.mWijgrid._allowVVirtualScrolling()) {
                    var height = this.mWijgrid._view().getDefaultRowHeight();

                    container.css({
                        "overflow": "hidden",
                        "height": height
                    });
                }

                if ($.isFunction(this.options.cellFormatter)) {
                    useDefault = !this.options.cellFormatter(args);
                }

                if (useDefault) {
                    var rt = wijmo.grid.rowType;

                    switch (row.type & ~(4 /* dataAlt */ | 512 /* dataDetail */ | 256 /* dataHeader */)) {
                        case 2 /* data */:
                            this._initializeDataCell(cell, container, args.formattedValue, row);
                            break;

                        case 64 /* footer */:
                            this._initializeFooterCell(cell, container, row);
                            break;

                        case 1 /* header */:
                            this._initializeHeaderCell(cell, container);
                            break;

                        case 8 /* filter */:
                            this._initializeFilterCell(cell, container);
                            break;

                        case 16 /* groupHeader */:
                            this._initializeGroupHeaderCell(cell, cellIndex, container, args.formattedValue, row);
                            break;

                        case 1024 /* detail */:
                            this._initializeDetailCell(cell, container, row);
                            break;

                        default:
                            this._updateHTML(row, container, args.formattedValue);
                    }

                    if ($.isFunction(args.afterDefaultCallback)) {
                        args.afterDefaultCallback(args);
                    }
                }
            };

            c1basefield.prototype._initializeDataCell = function (cell, container, formattedValue, rowInfo) {
                this._setupDataCell(container, formattedValue, rowInfo);
            };

            c1basefield.prototype._initializeFooterCell = function (cell, container, row) {
                this._setupFooterCell(container, row);
            };

            c1basefield.prototype._initializeHeaderCell = function (cell, container) {
                this._attachToElement(cell);

                var defCSS = this._defCSS(), wijCSS = this._wijCSS();

                cell.addClass(wijCSS.widget + " " + defCSS.c1basefield + " " + wijCSS.stateDefault);

                this._setupHeaderCell();
            };

            c1basefield.prototype._initializeFilterCell = function (cell, container) {
                var defCSS = this._defCSS(), wijCSS = this._wijCSS();

                container.addClass(wijCSS.widget + " " + wijCSS.stateDefault);

                this._setupFilterCell(container);
            };

            c1basefield.prototype._initializeGroupHeaderCell = function (cell, cellIndex, container, value, row) {
                var grid = this.mWijgrid;

                // provide a toggle icon for the first cell of the groupHeader row
                if (cellIndex === this.mWijgrid._virtualLeaves().length) {
                    // if grouped column is hidden then groupedColumn != this.
                    var groupedColumn = this.mWijgrid._groupedLeaves()[row._extInfo.groupLevel - 1];

                    if (groupedColumn) {
                        var gi = groupedColumn.options.groupInfo;

                        if (gi && (gi.outlineMode !== "none")) {
                            var collapsed = (row._extInfo.state & 2 /* collapsed */) != 0;

                            value = this._getToggleButtonHtml(collapsed, collapsed ? gi.collapsedImageClass : gi.expandedImageClass) + value;
                        }
                    }
                }

                this._updateHTML(row, container, value);
            };

            c1basefield.prototype._initializeDetailCell = function (cell, container, row) {
                cell.addClass(this._defCSS().detailContainerCell);
                this._setupDetailCell(container, row);
            };

            c1basefield.prototype._getToggleButtonHtml = function (collapsed, priorityIconCss) {
                var defCSS = this._defCSS(), wijCSS = this._wijCSS(), icon = priorityIconCss || (collapsed ? wijCSS.iconArrowRight : wijCSS.iconArrowRightDown);

                return "<div class =\"" + wijCSS.icon + " " + icon + " " + defCSS.groupToggleVisibilityButton + " " + wijCSS.wijgridGroupToggleVisibilityButton + "\">&nbsp;</div>";
            };

            c1basefield.prototype._cellRendered = function (cell, container, row) {
            };

            c1basefield.prototype._needToEncodeValue = function (row) {
                return false;
            };

            c1basefield.prototype._updateHTML = function (row, container, value) {
                var encode = this._needToEncodeValue(row);
                this.mWijgrid.mCellFormatter.updateHTML(container, value, encode);
            };

            //#endregion rendering
            //#region header cell
            c1basefield.prototype._getHeaderContent = function () {
                return this.options.headerText || "&nbsp;";
            };

            c1basefield.prototype._createHeaderContent = function (container) {
                container.html(this._getHeaderContent()); // html(value) returns "" if value is undefined
            };

            c1basefield.prototype._decorateHeaderContent = function (container) {
                var defCSS = this._defCSS(), wijCSS = this._wijCSS();

                container.wrapInner("<span class=\"" + defCSS.headerCellText + " " + wijCSS.wijgridHeaderCellText + "\" />");
            };

            c1basefield.prototype._setupHeaderCell = function () {
                var $container = this.element.children("." + this._defCSS().cellContainer).empty();

                this._createHeaderContent($container);
                this._decorateHeaderContent($container);
            };

            //#endregion
            //#region filter cell
            c1basefield.prototype._setupFilterCell = function (container) {
            };

            //#endregion
            //#region data cell
            c1basefield.prototype._setupDataCell = function (container, formattedValue, rowInfo) {
                this._updateHTML(rowInfo, container, formattedValue);
            };

            //#endregion
            //#region footer cell
            c1basefield.prototype._setupFooterCell = function (container, row) {
                this._updateHTML(row, container, this.options.footerText || this.options._footerTextDOM);
            };

            //#endregion
            //#region detail cell
            c1basefield.prototype._setupDetailCell = function (container, row) {
                var owner = this._owner(), masterRow = owner.mSketchTable.row(row.sketchRowIndex - 1);

                var detail = owner.details()[masterRow.originalRowIndex];
                if (detail.isExpanded()) {
                    owner.mLoadingDetails++;

                    owner._view()._addDetailInstantiator(function () {
                        _grid.detailInstantiator.instantiateIn(container, owner, detail.masterKey(), masterRow.originalRowIndex);
                        container = null;
                    });
                }
            };

            //#endregion
            //#region properies handlers
            c1basefield.prototype._postset_headerText = function (value, oldValue) {
                this._setupHeaderCell();
            };

            c1basefield.prototype._postset_visible = function (value, oldValue) {
                var self = this, wijgrid = self._owner();
                if (wijgrid._allowHVirtualScrolling()) {
                    wijgrid._resetScrollState(); //make sure wijgrid can get the correct renderable bound.(#123978)
                }
                wijgrid.ensureControl(false);
            };

            c1basefield.prototype._postset_width = function (value, oldValue) {
                var flag = this._owner()._isDetail();

                try  {
                    if (flag) {
                        this._owner()._ignoreSizing(false);
                    }

                    this.options.ensurePxWidth = true; // prevent auto expanding
                    this.options._realWidth = value;

                    this._owner().setSize(); // recalculate sizes and auto expand other columns if possible.
                } finally {
                    if (flag) {
                        this._owner()._ignoreSizing(true);
                    }
                }
            };

            //#endregion
            //#region UI actions
            c1basefield.prototype._draggable = function () {
                return true;
            };

            c1basefield.prototype._canSize = function () {
                return this.options.allowSizing && this._owner().options.allowColSizing;
            };

            // drag-n-drop
            c1basefield.prototype._canDrag = function () {
                return this.options.allowMoving === true;
            };

            c1basefield.prototype._canDropTo = function (column) {
                // parent can't be dropped into a child
                if (wijmo.grid.isChildOf(this._owner()._allColumns(), column, this)) {
                    return false;
                }

                return true;
            };

            c1basefield.prototype._canDropToGroupArea = function () {
                return false;
            };

            //#endregion
            //#region misc
            c1basefield.prototype._visible = function () {
                return this.options._visLeavesIdx >= 0;
                //return this.options._parentVis === true;
            };

            c1basefield.prototype._isFirstVisible = function () {
                if (this.mFirstVisible === undefined) {
                    this.mFirstVisible = this.options._visLeavesIdx === this.mWijgrid._virtualLeaves().length;
                }

                return this.mFirstVisible;
            };

            c1basefield.prototype._isRendered = function () {
                return this._visible() && this.mWijgrid._renderableColumnsRange().contains(this);
            };

            c1basefield.prototype._strictWidthMode = function () {
                return !!(this.options.ensurePxWidth || this.mWijgrid.options.ensureColumnsPxWidth || this.mWijgrid._allowHVirtualScrolling());
            };
            c1basefield.WIDGET_NAME = "wijmo.c1basefield";
            return c1basefield;
        })(_grid.widgetEmulator);
        _grid.c1basefield = c1basefield;

        var c1basefield_options = (function () {
            function c1basefield_options() {
                /** A value indicating whether the column can be moved.
                * @example
                * $("#element").wijgrid({ columns: [ { allowMoving: true } ] });
                */
                this.allowMoving = true;
                /** A value indicating whether the column can be sized.
                * @example
                * $("#element").wijgrid({ columns: [ { allowSizing: true } ] });
                */
                this.allowSizing = true;
                /** This function is called each time wijgrid needs to create cell content.
                * This occurs when rows are being rendered or cell editing is about to finish.
                * You can use it to customize cell content.
                * @example
                * // Add an image which URL is obtained from the "Url" data field to the column cells.
                * $("#demo").wijgrid({
                *		data: [
                *			{ ID: 0, Url: "/images/0.jpg" },
                *			{ ID: 1, Url: "/images/1.jpg" }
                *		],
                *		columns: [
                *			{},
                *			{
                *				cellFormatter: function (args) {
                *					if (args.row.type & wijmo.grid.rowType.data) {
                *						args.$container
                *							.empty()
                *							.append($("<img />")
                *								.attr("src", args.row.data.Url));
                *
                *						return true;
                *					}
                *				}
                *			}
                *		]
                * });
                * @type {Function}
                * @param {wijmo.grid.IC1BaseFieldCellFormatterArgs} args The data with this function.
                * @returns {Boolean} True if container content has been changed and wijgrid should not apply the default formatting to the cell.
                * @remarks
                * Important: cellFormatter should not alter content of header and filter row cells container.
                */
                this.cellFormatter = undefined;
                /** Determines whether to use number type column width as the real width of the column.
                * @example
                * $("#element").wijgrid({ columns: [{ ensurePxWidth: true }]});
                * @remarks
                * If this option is set to true, wijgrid will use the width option of the column widget.
                * If this option is undefined, wijgrid will refer to the ensureColumnsPxWidth option.
                */
                this.ensurePxWidth = undefined;
                /** Gets or sets the footer text.
                * The text may include a placeholder: "{0}" is replaced with the aggregate.
                * @example
                * $("#element").wijgrid({ columns: [{ footerText: "footer" }]});
                * @remarks
                * If the value is undefined the footer text will be determined automatically depending on the type of the datasource:
                * DOM table - text in the footer cell.
                */
                this.footerText = undefined;
                /** Gets or sets the header text.
                * @example
                * $("#element").wijgrid({ columns: [ { headerText: "column0" } ] });
                * @remarks
                * If the value is undefined the header text will be determined automatically depending on the type of the datasource:
                * DOM table - text in the header cell.
                * Array of objects - dataKey (name of the field associated with column).
                * Two-dimensional array - dataKey (index of the field associated with column).
                */
                this.headerText = undefined;
                /** Gets or sets the text alignment of data cells. Possible values are "left", "right", "center".
                * @example
                * $("#element").wijgrid({ columns: [{ textAligment: "right" }]});
                */
                this.textAlignment = undefined;
                /** A value indicating whether column is visible.
                * @example
                * $("#element").wijgrid({ columns: [{ visible: true }]});
                */
                this.visible = true;
                /** Determines the width of the column.
                * @type {String|Number}
                * @example
                * $("#element").wijgrid({ columns: [ { width: 150 } ] });
                * $("#element").wijgrid({ columns: [ { width: "10%" } ]});
                * @remarks
                * The option could either be a number of string.
                * Use number to specify width in pixel, use string to specify width in percentage.
                * By default, wijgrid emulates the table element behavior when using number as width. This means wijgrid may not have the exact width specified. If exact width is needed, please set ensureColumnsPxWidth option of wijgrid to true.
                */
                this.width = undefined;
            }
            return c1basefield_options;
        })();
        _grid.c1basefield_options = c1basefield_options;
        ;

        c1basefield.prototype.options = wijmo.grid.extendWidgetOptions({}, new c1basefield_options());

        wijmo.grid.registerColumnFactory(function (grid, column) {
            if (c1basefield.test(column)) {
                return new c1basefield(grid, column);
            }

            return null;
        });
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

var wijmo;
(function (wijmo) {
    (function (_grid) {
        var $ = jQuery;

        /** @ignore */
        var c1rowheaderfield = (function (_super) {
            __extends(c1rowheaderfield, _super);
            function c1rowheaderfield(wijgrid, options, widgetName) {
                _super.call(this, wijgrid, options, widgetName || c1rowheaderfield.WIDGET_NAME);
            }
            c1rowheaderfield.getInitOptions = function () {
                var opt = {};

                opt._clientType = c1rowheaderfield.CLIENT_TYPE;
                opt._parentVis = true;

                return opt;
            };

            c1rowheaderfield.test = function (column) {
                return column._clientType === c1rowheaderfield.CLIENT_TYPE;
            };

            c1rowheaderfield.prototype._provideDefaults = function () {
                _super.prototype._provideDefaults.call(this);

                this.options.allowMoving = false;
                this.options.allowSizing = false;
                this.options.dataKey = null;
                this.options.width = c1rowheaderfield.COLUMN_WIDTH;
                this.options.ensurePxWidth = true;
            };

            c1rowheaderfield.prototype._initializeCell = function (cell, cellIndex, container, formattedValue, rowInfo) {
                var defCSS = this._defCSS(), wijCSS = this._wijCSS();

                _super.prototype._initializeCell.apply(this, arguments);

                cell.attr({ "role": "rowheader", "scope": "row" }).addClass(wijCSS.stateDefault + " " + wijCSS.content + " " + defCSS.rowHeader + " " + wijCSS.wijgridRowHeader);
            };

            c1rowheaderfield.prototype._initializeDetailCell = function (cell, container, row) {
                _super.prototype._initializeDetailCell.apply(this, arguments);
                cell.removeClass(this._defCSS().detailContainerCell); // row header cell can't be used as detail grid container
            };

            c1rowheaderfield.prototype._setupDetailCell = function (container, row) {
                this._updateHTML(row, container, ""); // row header cell can't be used as detail grid container
            };

            c1rowheaderfield.prototype._draggable = function () {
                return false;
            };

            c1rowheaderfield.prototype._isFirstVisible = function () {
                return false;
            };
            c1rowheaderfield.CLIENT_TYPE = "c1rowheaderfield";

            c1rowheaderfield.WIDGET_NAME = "wijmo.c1rowheaderfield";

            c1rowheaderfield.COLUMN_WIDTH = 22;
            return c1rowheaderfield;
        })(_grid.c1basefield);
        _grid.c1rowheaderfield = c1rowheaderfield;

        c1rowheaderfield.prototype.options = wijmo.grid.extendWidgetOptions({}, new _grid.c1basefield_options());

        wijmo.grid.registerColumnFactory(function (grid, column) {
            if (c1rowheaderfield.test(column)) {
                return new c1rowheaderfield(grid, column);
            }

            return null;
        });
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

var wijmo;
(function (wijmo) {
    (function (_grid) {
        var $ = jQuery;

        /** @ignore */
        var c1detailrowheaderfield = (function (_super) {
            __extends(c1detailrowheaderfield, _super);
            function c1detailrowheaderfield(wijgrid, options, widgetName) {
                _super.call(this, wijgrid, options, widgetName || c1detailrowheaderfield.WIDGET_NAME);
            }
            /** @ignore */
            c1detailrowheaderfield.test = function (column) {
                return column._clientType === c1detailrowheaderfield.CLIENT_TYPE;
            };

            /** @ignore */
            c1detailrowheaderfield.getInitOptions = function () {
                var opts = wijmo.grid.c1rowheaderfield.getInitOptions();
                opts._clientType = c1detailrowheaderfield.CLIENT_TYPE;
                return opts;
            };

            c1detailrowheaderfield.prototype._setupDataCell = function (container, formattedValue, row) {
                var _this = this;
                if (row.type & 512 /* dataDetail */) {
                    this._updateHTML(row, container, "&nbsp;");
                } else {
                    var html = this._getToggleButtonHtml((row._extInfo.state & 2 /* collapsed */) != 0);

                    this._updateHTML(row, container, html);

                    container.find("." + this._defCSS().groupToggleVisibilityButton).click(function (e) {
                        _this._owner()._onToggleHierarchy(e, row);
                        e.stopPropagation();
                        return false;
                    }).dblclick(function (e) {
                        e.stopPropagation(); //#110137
                        return false;
                    });
                }
            };
            c1detailrowheaderfield.CLIENT_TYPE = "c1detailrowheaderfield";

            c1detailrowheaderfield.WIDGET_NAME = "wijmo.c1detailrowheaderfield";
            return c1detailrowheaderfield;
        })(_grid.c1rowheaderfield);
        _grid.c1detailrowheaderfield = c1detailrowheaderfield;

        wijmo.grid.registerColumnFactory(function (grid, column) {
            if (c1detailrowheaderfield.test(column)) {
                return new c1detailrowheaderfield(grid, column);
            }

            return null;
        });
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="c1basefield.ts"/>
/// <reference path="c1groupedfield.ts"/>
/// <reference path="interfaces.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /// <reference path="../../../wijinput/jquery.wijmo.wijinputdate.ts"/>
    /// <reference path="../../../wijinput/jquery.wijmo.wijinputtext.ts"/>
    /// <reference path="../../../wijinput/jquery.wijmo.wijinputnumber.ts"/>
    (function (_grid) {
        var $ = jQuery;

        var c1field = (function (_super) {
            __extends(c1field, _super);
            function c1field(wijgrid, options, widgetName) {
                _super.call(this, wijgrid, options, widgetName || c1field.WIDGET_NAME);
                this.mFilterEditorInitialized = false;
            }
            c1field.test = function (column) {
                // return column.groupInfo || column.sortDirection || column.aggregate || column.dataKey === null;
                return wijmo.grid.validDataKey(column.dataKey);
            };

            c1field.isGroupedColumn = function (column) {
                var opt = column.options;
                return wijmo.grid.c1field.test(opt) && (opt.groupInfo && opt.groupInfo.position && (opt.groupInfo.position !== "none"));
            };

            c1field.prototype._destroy = function () {
                if (this.element) {
                    var defCSS = this._defCSS();
                    this.element.removeClass(defCSS.c1field);
                }

                try  {
                    if (this.mFilterEditor) {
                        this.mFilterEditor.closest("td").find("*").unbind("." + this.widgetName);

                        switch (this._getInputEditorType()) {
                            case "date":
                                if (this.mFilterEditor.data("wijmo-wijinputdate")) {
                                    this.mFilterEditor.wijinputdate("destroy");
                                }
                                break;

                            case "text":
                                if (this.mFilterEditor.data("wijmo-wijinputtext")) {
                                    this.mFilterEditor.wijinputtext("destroy");
                                }
                                break;

                            case "numberCurrency":
                            case "numberNumber":
                            case "numberPercent":
                                if (this.mFilterEditor.data("wijmo-wijinputnumber")) {
                                    this.mFilterEditor.wijinputnumber("destroy");
                                }
                                break;
                        }
                    }

                    this._hideDropDownList();
                } finally {
                    this.mFilterEditor = null;
                    this.mDropDownFilterList = null;
                }

                _super.prototype._destroy.apply(this, arguments);
            };

            c1field.prototype._provideDefaults = function () {
                _super.prototype._provideDefaults.call(this);

                wijmo.grid.shallowMerge(this.options, c1field.prototype.options);

                if ($.isFunction(this.options.dataParser)) {
                    this.options.dataParser = new this.options.dataParser(); // legacy, converts a function into an object intstance.
                }

                this.options.groupInfo = this.options.groupInfo || {};
                wijmo.grid.shallowMerge(this.options.groupInfo, c1field.prototype.options.groupInfo);
            };

            //#region rendering
            c1field.prototype._initializeHeaderCell = function (cell, container) {
                _super.prototype._initializeHeaderCell.apply(this, arguments);

                var defCSS = this._defCSS();

                cell.addClass(defCSS.c1field);
            };

            c1field.prototype._needToEncodeValue = function (row) {
                //  override and introduce the encodeHtml option.
                var rt = wijmo.grid.rowType, encode = ((row.type & 2 /* data */) && !(row.type & 512 /* dataDetail */)) ? this.options.encodeHtml : _super.prototype._needToEncodeValue.apply(this, arguments);

                return encode;
            };

            //#endregion
            //#region UI actions
            c1field.prototype._isSortable = function () {
                return true;
            };

            c1field.prototype._isSortableUI = function () {
                var grid = this._owner();
                return grid.options.allowSorting && this.options.allowSort && this._isSortable();
            };

            c1field.prototype._canDropTo = function (column) {
                if (_super.prototype._canDropTo.apply(this, arguments)) {
                    //the grouped column can't be dropped into group area
                    if (this.options.groupedIndex !== undefined && (column instanceof _grid.c1groupedfield)) {
                        return false;
                    }

                    return true;
                }

                return false;
            };

            c1field.prototype._canDropToGroupArea = function () {
                return this.options.groupedIndex === undefined;
            };

            //#endregion
            //#region header cell
            c1field.prototype._decorateHeaderContent = function ($container) {
                var wijgrid = this._owner(), defCSS = wijmo.grid.wijgrid.CSS, wijCSS = wijgrid.options.wijCSS;

                if (!this._isSortable()) {
                    _super.prototype._decorateHeaderContent.apply(this, arguments); // plain text
                } else {
                    var isSortableUI = this._isSortableUI();

                    if (isSortableUI) {
                        $container.wrapInner("<a class=\"" + defCSS.headerCellText + " " + wijCSS.wijgridHeaderCellText + "\" href=\"#\" role=\"button\" />").children("a").bind("click." + this.widgetName, this, $.proxy(this._onSortableElementClick, this));
                    } else {
                        _super.prototype._decorateHeaderContent.apply(this, arguments); // plain text
                    }

                    // icons
                    var baseSortCSS = defCSS.headerCellSortIcon + " " + wijCSS.wijgridHeaderCellSortIcon + " " + wijCSS.icon, sortIcon = null;

                    switch (this.options.sortDirection) {
                        case "ascending":
                            $container.append(sortIcon = $("<span class=\"" + baseSortCSS + " " + wijCSS.iconArrowUp + "\"></span>"));
                            break;

                        case "descending":
                            $container.append(sortIcon = $("<span class=\"" + baseSortCSS + " " + wijCSS.iconArrowDown + "\"></span>"));
                            break;
                    }

                    if (sortIcon && isSortableUI) {
                        sortIcon.css("cursor", "pointer").bind("click." + this.widgetName, this, $.proxy(this._onSortableElementClick, this));
                    }
                }
            };

            c1field.prototype._onSortableElementClick = function (args) {
                var column = args.data;

                if (column.options.disabled) {
                    return false;
                }

                if (column.options.allowSort) {
                    column._owner()._handleSort(column, args.ctrlKey);
                }

                return false;
            };

            //#endregion
            //#region filter cell
            c1field.prototype._showFilter = function () {
                return this.options.showFilter && !this._isDetailRelationField();
            };

            c1field.prototype._isDetailRelationField = function () {
                var grid = this._owner();

                if (!grid._isRoot()) {
                    var relation = grid.options.relation;

                    if (relation) {
                        for (var i = 0; i < relation.length; i++) {
                            var a = relation[i].detailDataKey, b = this.options.dataKey;

                            if (a && b && ((a + "").toLowerCase() === (b + "").toLowerCase())) {
                                return true;
                            }
                        }
                    }
                }

                return false;
            };

            c1field.prototype._setupFilterCell = function (container) {
                if (this._showFilter()) {
                    var defCSS = this._defCSS(), wijCSS = this._wijCSS();

                    container.html("<table cellPadding=\"0\" cellSpacing=\"0\" class=\"" + defCSS.filter + " " + wijCSS.wijgridFilter + " " + wijCSS.cornerAll + "\">" + "<tr>" + "<td style=\"width:100%\">" + "<input type=\"text\" class=\"" + defCSS.filterInput + " " + wijCSS.wijgridFilterInput + "\" style=\"width:100%\" />" + "</td>" + "<td class=\"" + defCSS.filterTrigger + " " + wijCSS.wijgridFilterTrigger + " " + wijCSS.cornerRight + " " + wijCSS.stateDefault + "\">" + "<span class=\"" + wijCSS.icon + " " + wijCSS.iconArrowDown + "\"></span>" + "</td>" + "</tr>" + "</table>");

                    this._createFilterCellEditor(container);
                }
            };

            c1field.prototype._createFilterCellEditor = function (container) {
                var _this = this;
                var wijgrid = this._owner(), inputType = wijmo.grid.HTML5InputSupport.getDefaultInputType(wijgrid._isMobileEnv(), this.options), defCSS = this._defCSS(), wijCSS = this._wijCSS(), self = this;

                //container
                //	.bind(((<any>$.support).selectstart ? "selectstart" : "mousedown"), function (event) { //?? the problem of inputing in the filter textbox
                //		event.stopPropagation();
                //	})
                // create filter buttons
                container.find("." + defCSS.filterTrigger).attribute({ "role": "button", "aria-haspopup": "true" }).bind("mouseenter." + this.widgetName, function (e) {
                    if (!self.options.disabled) {
                        $(this).addClass(wijCSS.stateDefault + " " + wijCSS.stateHover);
                    }
                }).bind("mouseleave." + this.widgetName, function (e) {
                    if (!self.options.disabled) {
                        $(this).removeClass(wijCSS.stateDefault + " " + wijCSS.stateHover + " " + wijCSS.stateActive);
                    }
                }).bind("mouseup." + this.widgetName, this, function (e) {
                    if (!self.options.disabled) {
                        $(this).removeClass(wijCSS.stateDefault + " " + wijCSS.stateActive);
                    }
                }).bind("mousedown." + this.widgetName, $.proxy(this._onFilterBtnClick, this)).bind("click." + this.widgetName, function (e) {
                    e.preventDefault();
                }); // prevent # being added to url.

                var dataValue = wijgrid.parse(this.options, wijmo.grid.filterHelper.getSingleValue(this.options.filterValue));

                if (dataValue === null || dataValue === "undefined") {
                    switch (wijmo.grid.getDataType(this.options)) {
                        case "boolean":
                            dataValue = false;
                            break;

                        case "number":
                        case "currency":
                            dataValue = 0;
                            break;

                        case "datetime":
                            dataValue = new Date(); // current date
                            break;

                        default:
                            dataValue = "";
                    }
                }

                var editorOptions = {
                    culture: wijgrid.options.culture,
                    cultureCalendar: wijgrid.options.cultureCalendar,
                    disabled: wijgrid.options.disabled,
                    decimalPlaces: (function (pattern) {
                        var test = /^(n|p|c){1}(\d*)$/.exec(pattern);

                        if (test && test[2]) {
                            return parseInt(test[2], 10);
                        }

                        test = /^(d){1}(\d*)$/.exec(pattern);
                        if (test) {
                            return 0;
                        }

                        return 2;
                    })(this.options.dataFormatString),
                    imeMode: this.options.imeMode,
                    triggerMouseUp: function (e) {
                        _this._owner()._hideAllFilterDropDownLists();
                    }
                };

                this.mFilterEditor = container.find("input").bind("keypress." + this.widgetName, $.proxy(this._onFilterEditorKeyPress, this));

                var valListener = function (args) {
                    if (_this.mFilterEditorInitialized) {
                        _this._onFilterEditorValueChanged(args);
                    }
                };

                switch (this._getInputEditorType()) {
                    case "date":
                        if (inputType === "text") {
                            this.mFilterEditor.wijinputdate($.extend(editorOptions, {
                                date: dataValue,
                                dateFormat: this.options.dataFormatString || undefined,
                                showTrigger: true,
                                dateChanged: function (e, args) {
                                    valListener({ value: args.data });
                                },
                                calendar: wijgrid.options.calendar
                            }));
                        } else {
                            // html5 editor
                            this._createHtmlEditor(this.mFilterEditor, inputType, wijmo.grid.HTML5InputSupport.toStr(dataValue, inputType));
                        }
                        break;

                    case "text":
                        this.mFilterEditor.wijinputtext($.extend(editorOptions, {
                            text: dataValue + "",
                            textChanged: function (e, args) {
                                valListener({ value: args.text });
                            }
                        }));
                        break;

                    case "numberCurrency":
                        this.mFilterEditor.wijinputnumber($.extend(editorOptions, {
                            type: "currency",
                            value: dataValue,
                            valueChanged: function (e, args) {
                                valListener({ value: args.value });
                            }
                        }));
                        break;

                    case "numberNumber":
                        if (inputType === "text") {
                            this.mFilterEditor.wijinputnumber($.extend(editorOptions, {
                                value: dataValue,
                                valueChanged: function (e, args) {
                                    valListener({ value: args.value });
                                }
                            }));
                        } else {
                            // html5 editor
                            this._createHtmlEditor(this.mFilterEditor, inputType, wijmo.grid.HTML5InputSupport.toStr(dataValue, inputType));
                        }
                        break;

                    case "numberPercent":
                        this.mFilterEditor.wijinputnumber($.extend(editorOptions, {
                            type: "percent",
                            value: dataValue * 100,
                            valueChanged: function (e, args) {
                                valListener({ value: args.value / 100 });
                            }
                        }));
                        break;

                    default:
                        throw "Unsupported editor type";
                }

                this.mFilterEditorInitialized = true;
            };

            c1field.prototype._createHtmlEditor = function (input, inputType, value) {
                var defCSS = wijmo.grid.wijgrid.CSS, wijCSS = this._owner().options.wijCSS;

                input[0].type = inputType; // use it instead of .attr("type", inputType) to avoid the "'type' property/attribute cannot be changed." exception.

                return input.addClass(wijCSS.stateDefault).wrap("<span class=\"" + defCSS.filterNativeHtmlEditorWrapper + " " + wijCSS.wijgridFilterNativeHtmlEditorWrapper + "\"></span").val(value);
            };

            c1field.prototype._onFilterBtnClick = function (e) {
                var _this = this;
                var wijgrid = this._owner(), ddflVisible = !!this.mDropDownFilterList;

                wijgrid._hideAllFilterDropDownLists();

                if (this.options.disabled || ddflVisible) {
                    return false;
                }

                e.target.focus(); //TFS #24253: In IE9, wijgrid is distorted on opening filter drop-down in a scrollable grid

                var filterOpLowerCase = wijmo.grid.filterHelper.getSingleOperatorName(this.options.filterOperator).toLowerCase(), applicableFilters = wijgrid.getFilterOperatorsByDataType(wijmo.grid.getDataType(this.options)), args = {
                    operators: $.extend(true, [], applicableFilters),
                    column: this.options
                }, items = [];

                wijgrid._onFilterOperatorsListShowing(args);

                if (args.operators) {
                    $.each(args.operators, function (key, operator) {
                        items.push({
                            label: operator.displayName || operator.name,
                            value: operator.name,
                            selected: operator.name.toLowerCase() === filterOpLowerCase
                        });
                    });
                }

                this.mDropDownFilterList = $("<div />").addClass(wijmo.grid.wijgrid.CSS.filterList + " " + wijgrid.options.wijCSS.wijgridFilterList).appendTo(document.body).wijlist({
                    autoSize: true,
                    maxItemsCount: c1field.DROPDOWN_FILTERS_MAX,
                    selected: function (e, data) {
                        var filterValue = _this._getFilterValueFromEditor();
                        _this._hideDropDownList();
                        wijgrid._handleFilter(_this, data.item.value, filterValue);
                    }
                }).css("z-index", wijmo.grid.getZIndex(wijgrid.mOuterDiv, 9999)).wijlist("setItems", items).wijlist("renderList");

                var width = this.mDropDownFilterList.width() | 150;

                this.mDropDownFilterList.width(items.length > c1field.DROPDOWN_FILTERS_MAX ? width + 20 : width).wijlist("refreshSuperPanel").position({
                    of: $(e.currentTarget),
                    my: "left top",
                    at: "left bottom"
                });

                this.mDropDownFilterList.$button = $(e.currentTarget);

                var eventUID = this.mDropDownFilterList.eventUID = wijmo.grid.getUID();

                $(document).bind("mousedown." + this.widgetName + "." + eventUID, { column: this }, this._onDocMouseDown);
            };

            c1field.prototype._onFilterEditorKeyPress = function (e) {
                if (e && (e.which === 13)) {
                    var wijgrid = this._owner(), filterValue = this._getFilterValueFromEditor(), filterOperator = (this.options.filterOperator || "").toLowerCase();

                    if (!filterValue) {
                        filterValue = undefined;
                        filterOperator = "nofilter";
                    } else {
                        if (!filterOperator || (filterOperator === "nofilter")) {
                            filterOperator = (wijmo.grid.getDataType(this.options) === "string") ? "contains" : "equals";
                        }
                    }

                    this._hideDropDownList();
                    wijgrid._handleFilter(this, filterOperator, filterValue);
                }
            };

            c1field.prototype._onDocMouseDown = function (e) {
                var column = e.data.column, $target = $(e.target), defCSS = wijmo.grid.wijgrid.CSS, $filterList = $target.parents("." + defCSS.filterList + ":first"), $filterButton = $target.is("." + defCSS.filterTrigger) ? $target : $target.parents("." + defCSS.filterTrigger + ":first");

                if (($filterButton.length && ($filterButton[0] === column.mDropDownFilterList.$button[0])) || ($filterList.length && ($filterList[0] === column.mDropDownFilterList[0]))) {
                    // do nothing
                } else {
                    column._hideDropDownList();
                }
            };

            c1field.prototype._hideDropDownList = function () {
                if (this.mDropDownFilterList) {
                    var eventUID = this.mDropDownFilterList.eventUID;

                    this.mDropDownFilterList.remove();

                    this.mDropDownFilterList = null;

                    $(document).unbind("mousedown." + this.widgetName + "." + eventUID, this._onDocMouseDown);
                }

                if (this.mFilterEditor && (this._getInputEditorType() === "date")) {
                    var inputDate = this.mFilterEditor.data("wijmo-wijinputdate");
                    if (inputDate) {
                        if (inputDate._popupVisible()) {
                            inputDate._hidePopup();
                        }
                    }
                }
            };

            // "text", "date", "numberNumber", "numberPercent", "numberCurrency"
            c1field.prototype._getInputEditorType = function () {
                switch (wijmo.grid.getDataType(this.options)) {
                    case "number":
                        return (this.options.dataFormatString && this.options.dataFormatString.indexOf("p") === 0) ? "numberPercent" : "numberNumber";

                    case "currency":
                        return "numberCurrency";

                    case "datetime":
                        return "date";

                    default:
                        return "text";
                }
            };

            c1field.prototype._getFilterValueFromEditor = function () {
                var wijgrid = this._owner(), inputType = wijmo.grid.HTML5InputSupport.getDefaultInputType(wijgrid._isMobileEnv(), this.options), filterValue;

                switch (this._getInputEditorType()) {
                    case "date":
                        if (inputType === "text") {
                            filterValue = this.mFilterEditor.wijinputdate("option", "date") || new Date(); // current date
                        } else {
                            filterValue = wijmo.grid.HTML5InputSupport.parse(this.mFilterEditor.val(), inputType) || new Date();
                        }
                        break;

                    case "text":
                        filterValue = this.mFilterEditor.wijinputtext("option", "text");
                        break;

                    case "numberNumber":
                        if (inputType !== "text") {
                            filterValue = wijmo.grid.HTML5InputSupport.parse(this.mFilterEditor.val(), inputType) || 0;
                            break;
                        }

                    case "numberCurrency":
                        filterValue = this.mFilterEditor.wijinputnumber("option", "value");
                        break;

                    case "numberPercent":
                        filterValue = this.mFilterEditor.wijinputnumber("option", "value") / 100;
                        break;
                }

                return filterValue;
            };

            //#endregion filtering
            //#region footer cell
            c1field.prototype._setupFooterCell = function (container, row) {
                var opt = this.options;

                if (opt.aggregate && (opt.aggregate !== "none")) {
                    var totalValue = "";

                    if (opt._totalsValue !== undefined) {
                        totalValue = wijmo.grid.tally.getValueString(opt._totalsValue, this, this._owner());
                    }

                    this._updateHTML(row, container, wijmo.grid.stringFormat(opt.footerText || "{0}", totalValue || ""));
                } else {
                    _super.prototype._setupFooterCell.apply(this, arguments);
                }
            };

            //#endregion
            //#region properies handlers
            c1field.prototype._postset_aggregate = function (value, oldValue) {
                this._owner().ensureControl(false);
            };

            c1field.prototype._postset_allowSort = function (value, oldValue) {
                this._setupHeaderCell();
            };

            c1field.prototype._postset_dataType = function (value, oldValue) {
                throw "read-only";
            };

            c1field.prototype._postset_dataParser = function (value, oldValue) {
                this._owner().ensureControl(false);
            };

            c1field.prototype._postset_disabled = function (value, oldValue) {
                if (this.mFilterEditor) {
                    $.each(this.mFilterEditor.data(), function (key, widget) {
                        if (widget && widget.widgetName && widget.option) {
                            widget.option("disabled", value);
                        }
                    });
                }
            };

            c1field.prototype._postset_dataFormatString = function (value, oldValue) {
                this._owner().ensureControl(false);
            };

            c1field.prototype._postset_filterOperator = function (value, oldValue) {
                var wijgrid = this._owner();

                wijgrid._resetDataProperitesOnFilterChanging();

                wijgrid.ensureControl(true);
            };

            c1field.prototype._postset_filterValue = function (value, oldValue) {
                var wijgrid = this._owner();

                wijgrid._resetDataProperitesOnFilterChanging();

                wijgrid.ensureControl(true);
            };

            c1field.prototype._postset_groupInfo = function (value, oldValue) {
                this._owner().ensureControl(true);
            };

            c1field.prototype._postset_rowMerge = function (value, oldValue) {
                this._owner().ensureControl(false);
            };

            c1field.prototype._postset_showFilter = function (value, oldValue) {
                this._owner().ensureControl(false);
            };

            c1field.prototype._postset_sortDirection = function (value, oldValue) {
                this.options._sortOrder = 0;
                this._owner().ensureControl(true);
            };

            c1field.prototype._postset_width = function (value, oldValue) {
                this._hideDropDownList();
                _super.prototype._postset_width.apply(this, arguments);
            };

            //#endregion
            //#region wijinput event handlers
            c1field.prototype._onFilterEditorValueChanged = function (args) {
            };
            c1field.WIDGET_NAME = "wijmo.c1field";
            c1field.DROPDOWN_FILTERS_MAX = 8;
            return c1field;
        })(_grid.c1basefield);
        _grid.c1field = c1field;

        var c1field_options = (function (_super) {
            __extends(c1field_options, _super);
            function c1field_options() {
                _super.apply(this, arguments);
                /** Causes the grid to calculate aggregate values on the column and place them in the column footer cell or group header and footer rows.
                * Possible values are: "none", "count", "sum", "average", "min", "max", "std", "stdPop", "var", "varPop" and "custom".
                * @example
                * $("#element").wijgrid({ columns: [{ aggregate: "count" }]});
                * @remarks
                * Possible values are:
                * "none": no aggregate is calculated or displayed.
                * "count": count of non-empty values.
                * "sum": sum of numerical values.
                * "average": average of the numerical values.
                * "min": minimum value (numerical, string, or date).
                * "max": maximum value (numerical, string, or date).
                * "std": standard deviation (using formula for Sample, n-1).
                * "stdPop": standard deviation (using formula for Population, n).
                * "var": variance (using formula for Sample, n-1).
                * "varPop": variance (using formula for Population, n).
                * "custom": custom value (causing grid to throw groupAggregate event).
                *
                * If the showFooter option is off or grid does not contain any groups, setting the "aggregate" option has no effect.
                */
                this.aggregate = "none";
                /** A value indicating whether column can be sorted.
                * @example
                * $("#element").wijgrid({ columns: [{ allowSort: true }] });
                */
                this.allowSort = true;
                /** A value indicating the key of the data field associated with a column.
                * If an array of objects is used as a datasource for wijgrid, this should be string value,
                * otherwise this should be an integer determining an index of the field in the datasource.
                * @type {String|Number}
                * @example
                * $("#element").wijgrid({ columns: [{ dataKey: "ProductID" }]});
                */
                this.dataKey = undefined;
                /** Column data type. Defines the rules, according to which column value will be formatted, defines editors types and allowed filter operators.
                * Does not change the type of source data, besides the case when data source is HTMLTable.
                * Possible values are: "string", "number", "datetime", "currency" and "boolean".
                * @example
                * $("#element").wijgrid({ columns: [{ dataType: "string" }]});
                * @remarks
                * Possible values are:
                * "string": if using built-in parser any values are acceptable; "&nbsp;" considered as an empty string, nullString as null.
                * "number": if using built-in parser only numeric values are acceptable, also "&nbsp;", "" and nullString which are considered as null. Any other value throws an exception.
                * "datetime": if using built-in parser only date-time values are acceptable, also "&nbsp;", "" and nullString which are considered as null. Any other value throws an exception.
                * "currency": if using built-in parser only numeric and currency values are acceptable, also "&nbsp;", "" and nullString which are considered as null. Any other value throws an exception.
                * "boolean": if using built-in parser only "true" and "false" (case-insensitive) values are acceptable, also "&nbsp;", "" and nullString which are considered as null. Any other value throws an exception.
                */
                this.dataType = undefined;
                /** Data converter that is able to translate values from a string representation to column data type and back.
                * @example
                * var myBoolParser = {
                *		parseDOM: function (value, culture, format, nullString) {
                *			return this.parse(value.innerHTML, culture, format, nullString);
                *		},
                *		parse: function (value, culture, format, nullString) {
                *			if (typeof (value) === "boolean")  return value;
                *
                *			if (!value || (value === "&nbsp;") || (value === nullString)) {
                *				return null;
                *			}
                *
                *			switch (value.toLowerCase()) {
                *				case "on": return true;
                *				case "off": return false;
                *			}
                *
                *			return NaN;
                *		},
                *		toStr: function (value, culture, format, nullString) {
                *			if (value === null)  return nullString;
                *				return (value) ? "on" : "off";
                *			}
                *		}
                * }
                *
                * $("#element").wijgrid({ columns: [ { dataType: "boolean", dataParser: myBoolParser } ] });
                * @remarks
                * If undefined, than the built-in parser for supported datatypes will be used.
                */
                this.dataParser = undefined;
                /** A pattern used for formatting and parsing column values.
                * @example
                * $("#element").wijgrid({
                *		columns: [
                *			{ dataType: "currency" },
                *			{ dataType: "number" },
                *			{ dataType: "number", dataFormatString: "p0" }
                *		]
                * });
                * @remarks
                * The default value is undefined ("n" pattern will be used for "number" dataType, "d" for "datetime", "c" for "currency").
                * Please see the https://github.com/jquery/globalize for a full explanation and additional values.
                */
                this.dataFormatString = undefined;
                /** A value indicating whether data values are HTML-encoded before they are displayed in a cell.
                * @example
                * $("#element").wijgrid({
                *		data: [
                *			[0, "<b>value</b>"],
                *			[1, "&amp;"],
                *		],
                *		columns: [
                *			{ headerText: "ID" },
                *			{ headerText: "Value", encodeHtml: true }
                *		]
                * });
                */
                this.encodeHtml = false;
                /** An operations set for filtering. Must be either one of the embedded operators or custom filter operator.
                * Operator names are case insensitive.
                *
                * @example
                * $("#element").wijgrid({ columns: [{ dataType: "number", filterOperator: "Equals", filterValue: 0 }]});
                * @remarks
                * Embedded filter operators include:
                * "NoFilter": no filter.
                * "Contains": applicable to "string" data type.
                * "NotContain": applicable to "string" data type.
                * "BeginsWith": applicable to "string" data type.
                * "EndsWith": applicable to "string" data type.
                * "Equals": applicable to "string", "number", "datetime", "currency" and "boolean" data types.
                * "NotEqual": applicable to "string", "number", "datetime", "currency" and "boolean" data types.
                * "Greater": applicable to "string", "number", "datetime", "currency" and "boolean" data types.
                * "Less": applicable to "string", "number", "datetime", "currency" and "boolean" data types.
                * "GreaterOrEqual": applicable to "string", "number", "datetime", "currency" and "boolean" data types.
                * "LessOrEqual": applicable to "string", "number", "datetime", "currency" and "boolean" data types.
                * "IsEmpty": applicable to "string".
                * "NotIsEmpty": applicable to "string".
                * "IsNull": applicable to "string", "number", "datetime", "currency" and "boolean" data types.
                * "NotIsNull": applicable to "string", "number", "datetime", "currency" and "boolean" data types.
                *
                * Full option value is:
                *		[filterOperartor1, ..., filterOperatorN]
                * where each filter item is an object of the following kind:
                *		{ name: <operatorName>, condition: "or"|"and" }
                * where:
                *		name: filter operator name.
                *		condition: logical condition to other operators, "or" is by default.
                * Example:
                *		filterOperator: [ { name: "Equals" }, { name: "NotEqual", condition: "and" } ]
                * It is possible to use shorthand notation, the following statements are equivalent:
                *		filterOperator: [ { name: "Equals" }, { name: "BeginsWith" } ]
                *		filterOperator: [ "Equals", "BeginsWith" ]
                * In the case of a single operator option name may contain only filter operator name, the following statements are equivalent:
                *		filterOperator: [ { name: "Equals" } ]
                *		filterOperator: [ "Equals" ]
                *		filterOperator: "Equals"
                *
                * Note: wijgrid built-in filter editors do not support multiple filter operators.
                *
                */
                this.filterOperator = "nofilter";
                /** A value set for filtering.
                * @example
                * $("#element").wijgrid({ columns: [{ dataType: "number", filterOperator: "Equals", filterValue: 0 }]});
                * @remarks
                * Full option value is:
                *		[filterValue1, ..., filterValueN]
                * where each item is a filter value for the corresponding filter operator. Example:
                *		filterValue: [0, "a", "b"]
                *
                * Built-in filter operators support array of values as an argument. Example:
                *		filterOperator: ["Equals", "BeginsWith"]
                *		filterValue: [[0, 1, 2], "a"]
                * As a result of filtering all the records having 0, 1, 2, or starting with "a" will be fetched.
                *
                * Shorthand notation allows omitting square brackets, the following statements are equivalent:
                *		filterValue: ["a"]
                *		filterValue: [["a"]]
                *		filterValue: "a"
                *
                * Note: wijgrid built-in filter editors do not support multiple filter values.
                */
                this.filterValue = undefined;
                /** Used to customize the appearance and position of groups.
                * @example
                * $("#element").wijgrid({ columns: [{ groupInfo: { position: "header" }}]});
                */
                this.groupInfo = {
                    /** @ignore */
                    expandInfo: [],
                    /** @ignore */
                    level: undefined,
                    groupSingleRow: true,
                    collapsedImageClass: undefined,
                    expandedImageClass: undefined,
                    position: "none",
                    outlineMode: "startExpanded",
                    headerText: undefined,
                    footerText: undefined
                };
                /**
                * Controls the state of the input method editor for text fields.
                * Possible values are: "auto", "active", "inactive", "disabled".
                * Please refer to https://developer.mozilla.org/en-US/docs/Web/CSS/ime-mode for more info.
                * @example
                * $("#element").wijgrid({ columns: [{ imeMode: "auto" }]});
                */
                this.imeMode = "auto";
                /**
                * Determines the type of html editor for filter and cells.
                * Possible values are: "number", "date", "datetime", "datetime-local", "month", "time", "text".
                * @example
                * $("#element").wijgrid({ columns: [{ inputType: "text" }]});
                * @remarks
                * If the value is set then input type element is used with "type" attribute set to the value. If the value is not set then:
                *  - in desktop environment a "text" input element is used as the editor.
                *  - in mobile environment a "number" input element is used for columns having "number" and "currency" dataType; for columns where dataType = "datetime" a "datetime" input element is used, otherwise a "text" input element is shown.
                */
                this.inputType = undefined;
                /** A value indicating whether the cells in the column can be edited.
                * @example
                * $("#element").wijgrid({ columns: [ { readOnly: false } ] });
                */
                this.readOnly = false;
                /** Determines whether rows are merged. Possible values are: "none", "free" and "restricted".
                * @example
                * $("#element").wijgrid({ columns: [{ rowMerge: "none" }]});
                * @remarks
                * Possible values are:
                * "none": no row merging.
                * "free": allows row with identical text to merge.
                * "restricted": keeps rows with identical text from merging if rows in the previous column are merged.
                */
                this.rowMerge = "none";
                /** A value indicating whether filter editor will be shown in the filter row.
                * @example
                * $("#element").wijgrid({ columns: [{ showFilter: true }]});
                */
                this.showFilter = true;
                /** Determines the sort direction. Possible values are: "none", "ascending" and "descending".
                * @example
                * $("#element").wijgrid({ columns: [{ sortDirection: "none" }]});
                * @remarks
                * Possible values are:
                * "none": no sorting.
                * "ascending": sort from smallest to largest.
                * "descending": sort from largest to smallest.
                */
                this.sortDirection = "none";
                /** A value indicating whether null value is allowed during editing.
                * @example
                * $("#element").wijgrid({ columns: [{ valueRequired: false }]});
                */
                this.valueRequired = false;
            }
            return c1field_options;
        })(_grid.c1basefield_options);
        _grid.c1field_options = c1field_options;
        ;

        c1field.prototype.options = wijmo.grid.extendWidgetOptions(_grid.c1basefield.prototype.options, new c1field_options());

        wijmo.grid.registerColumnFactory(function (grid, column) {
            if (c1field.test(column)) {
                return new c1field(grid, column);
            }

            return null;
        });
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

var wijmo;
(function (wijmo) {
    (function (_grid) {
        var $ = jQuery;

        var c1booleanfield = (function (_super) {
            __extends(c1booleanfield, _super);
            function c1booleanfield(wijgrid, options, widgetName) {
                _super.call(this, wijgrid, options, widgetName || c1booleanfield.WIDGET_NAME);
            }
            c1booleanfield.test = function (column) {
                return _grid.c1field.test(column) && (column.dataType === "boolean");
            };

            c1booleanfield.prototype._setupDataCell = function (container, formattedValue, row) {
                var grid = this._owner(), opt = this.options, defCSS = this._defCSS(), allowClickEditing = grid._allowCellEditing() && (opt.readOnly !== true), $input = $("<input class=\"" + defCSS.inputMarker + "\" type=\"checkbox\" aria-label=\"checkbox\" />");

                if (!allowClickEditing) {
                    $input.prop("disabled", true);
                }

                if (grid.parse(opt, grid.mDataViewWrapper.getValue(row.data, opt.dataKey)) === true) {
                    $input.prop("checked", "checked");
                }

                container.empty().append($input);
            };

            c1booleanfield.prototype._cellRendered = function (cell, container, row) {
                var grid = this._owner(), allowClickEditing = grid._allowCellEditing() && (this.options.readOnly !== true);

                // similate single-click behaviour for checkboxes.
                // important: this code must support c1gridview.c1checkboxfield also!
                if (allowClickEditing) {
                    var keyCodeEnum = wijmo.getKeyCodeEnum();

                    container.children("input").bind("mousedown", function (e) {
                        var targetElement = container.parent()[0], currentCell = grid.currentCell();

                        if (currentCell.tableCell() !== targetElement) {
                            grid._onClick({ target: targetElement });
                        }
                        if (!currentCell._isEdit()) {
                            grid.beginEdit();
                        }
                    }).bind("keydown", function (e) {
                        if (e.which === keyCodeEnum.ENTER) {
                            grid._endEditInternal(e);
                            return false;
                        }
                    });
                }
            };
            c1booleanfield.WIDGET_NAME = "wijmo.c1booleanfield";
            return c1booleanfield;
        })(_grid.c1field);
        _grid.c1booleanfield = c1booleanfield;

        wijmo.grid.registerColumnFactory(function (grid, column) {
            if (c1booleanfield.test(column)) {
                return new c1booleanfield(grid, column);
            }

            return null;
        });
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="c1basefield.ts"/>
/// <reference path="interfaces.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    (function (_grid) {
        var $ = jQuery;

        var c1bandfield = (function (_super) {
            __extends(c1bandfield, _super);
            function c1bandfield(wijgrid, options, emulatedWidgetName) {
                _super.call(this, wijgrid, options, emulatedWidgetName || c1bandfield.WIDGET_NAME);
            }
            /** @ignore */
            c1bandfield.test = function (column) {
                return !!(column && column.columns);
            };

            c1bandfield.prototype._provideDefaults = function () {
                _super.prototype._provideDefaults.call(this);

                wijmo.grid.shallowMerge(this.options, c1bandfield.prototype.options);

                this.options.dataKey = null;
            };
            c1bandfield.WIDGET_NAME = "wijmo.c1bandfield";
            return c1bandfield;
        })(_grid.c1basefield);
        _grid.c1bandfield = c1bandfield;

        var c1bandfield_options = (function (_super) {
            __extends(c1bandfield_options, _super);
            function c1bandfield_options() {
                _super.apply(this, arguments);
                /**
                * Gets a array of objects representing the band columns.
                * @example
                * $("#element").wijgrid({
                *   columns: [{
                *      headerText: "Band",
                *      columns: [
                *         { headerText: "ID" },
                *         { headerText: "Name" }
                *      ]
                *   }]
                * });
                */
                this.columns = [];
            }
            return c1bandfield_options;
        })(_grid.c1basefield_options);
        _grid.c1bandfield_options = c1bandfield_options;
        ;

        c1bandfield.prototype.options = wijmo.grid.extendWidgetOptions(_grid.c1basefield.prototype.options, new c1bandfield_options());

        wijmo.grid.registerColumnFactory(function (grid, column) {
            if (!!(column && column.columns)) {
                return new c1bandfield(grid, column);
            }

            return null;
        });
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="c1basefield.ts"/>
/// <reference path="interfaces.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    (function (grid) {
        var $ = jQuery;

        /** @ignore */
        var c1groupedfield = (function (_super) {
            __extends(c1groupedfield, _super);
            function c1groupedfield(wijgrid, options, element, widgetName) {
                _super.call(this, options, widgetName || c1groupedfield.WIDGET_NAME);
                this.mWijgrid = wijgrid;

                this._attachToElement(element);

                this._createContent();

                if (this.mWijgrid.options.allowColMoving) {
                    this.mWijgrid._UIDragndrop(true).attach(this);
                }
            }
            c1groupedfield.prototype._destroy = function () {
                if (this.mWijgrid._UIDragndrop()) {
                    this.mWijgrid._UIDragndrop(false).detach(this);
                }

                this.mWijgrid = null;

                _super.prototype._destroy.apply(this, arguments);
            };

            c1groupedfield.prototype._owner = function () {
                return this.mWijgrid;
            };

            c1groupedfield.prototype._createContent = function () {
                var defCSS = wijmo.grid.wijgrid.CSS, wijCSS = this.mWijgrid.options.wijCSS, $closeButton = $("<span class=\"" + defCSS.groupAreaButtonClose + " " + wijCSS.wijgridGroupAreaButtonClose + " " + wijCSS.stateDefault + " " + wijCSS.cornerAll + "\"><span class=\"" + wijCSS.icon + " " + wijCSS.iconClose + "\"></span></span>").bind("click." + this.widgetName, this, this._onCloseClick);

                this.element.addClass(defCSS.groupAreaButton + " " + wijCSS.wijgridGroupAreaButton + " " + wijCSS.stateDefault + " " + wijCSS.cornerAll).html(this.options.headerText || "").prepend($closeButton);

                if (this._isSortableUI()) {
                    this.element.bind("click." + this.widgetName, this, $.proxy(this._onSortableElementClick, this));
                }

                if (this._isSortable()) {
                    // sorting icon
                    var generalSortClass = defCSS.groupAreaButtonSort + " " + wijCSS.wijgridGroupAreaButtonSort + " " + wijCSS.icon;

                    switch (this.options.sortDirection) {
                        case "ascending":
                            this.element.append($("<span class=\"" + generalSortClass + " " + wijCSS.iconArrowUp + "\"></span>"));
                            break;

                        case "descending":
                            this.element.append($("<span class=\"" + generalSortClass + " " + wijCSS.iconArrowDown + "\"></span>"));
                            break;
                    }
                }
            };

            c1groupedfield.prototype._onCloseClick = function (args) {
                var column = args.data;

                if (!column.options.disabled) {
                    column.mWijgrid._handleUngroup(column);
                }

                return false;
            };

            // taken from the wijgridfield
            c1groupedfield.prototype._onSortableElementClick = function (args) {
                var column = args.data;

                if (column.options.disabled) {
                    return false;
                }

                if (column.options.allowSort) {
                    column.mWijgrid._handleSort(column, args.ctrlKey); // dangerous casting
                }

                return false;
            };

            //#region UI actions
            c1groupedfield.prototype._canDrag = function () {
                return this.options.allowMoving === true;
            };

            c1groupedfield.prototype._canDropTo = function (column) {
                return (column instanceof c1groupedfield);
            };

            c1groupedfield.prototype._canDropToGroupArea = function () {
                // The rightmost column header in the the group area can't be dragged to the end of the group area again.
                return (this.options.groupedIndex !== this.mWijgrid._groupedLeaves().length - 1);
            };

            c1groupedfield.prototype._isSortable = function () {
                return wijmo.grid.c1field.test(this.options);
            };

            c1groupedfield.prototype._isSortableUI = function () {
                return this.mWijgrid.options.allowSorting && this.options.allowSort && this._isSortable();
            };
            c1groupedfield.WIDGET_NAME = "wijmo.c1groupedfield";
            return c1groupedfield;
        })(grid.widgetEmulator);
        grid.c1groupedfield = c1groupedfield;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="../../../Base/jquery.wijmo.widget.ts"/>
/// <reference path="interfaces.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    (function (grid) {
        var $ = jQuery;

        

        /** @ignore */
        var wijgridcommandbuttonbase = (function (_super) {
            __extends(wijgridcommandbuttonbase, _super);
            function wijgridcommandbuttonbase() {
                _super.apply(this, arguments);
            }
            wijgridcommandbuttonbase.prototype._create = function () {
                this.element.css("display", "inline").addClass(this.options.wijCSS.widget);
            };

            wijgridcommandbuttonbase.prototype._destroy = function () {
                this.mBtnElement = null;
            };

            wijgridcommandbuttonbase.prototype._init = function () {
                var _this = this;
                this.mBtnElement = this._createElement(this.options).addClass("wijmo-wijgrid-commandbutton").click(function (e) {
                    if (!_this.options.disabled && $.isFunction(_this.options.click)) {
                        _this.options.click.call(self, e);
                    }
                });

                this.element.append(this.mBtnElement);

                this._attachWidget(this.mBtnElement, this.options);
            };

            wijgridcommandbuttonbase.prototype._setOption = function (key, value) {
                var oldValue = this.options[key];

                _super.prototype._setOption.apply(this, [key, value]);

                if ((oldValue !== value) && (key === "disabled")) {
                    this._onDisabledChanged(value === true);
                }
            };

            wijgridcommandbuttonbase.prototype._createElement = function (settings) {
                throw "not implemented";
            };

            wijgridcommandbuttonbase.prototype._attachWidget = function (element, settings) {
                throw "not implemented";
            };

            wijgridcommandbuttonbase.prototype._btnElement = function () {
                return this.mBtnElement;
            };

            wijgridcommandbuttonbase.prototype._onDisabledChanged = function (value) {
            };
            return wijgridcommandbuttonbase;
        })(wijmo.wijmoWidget);
        grid.wijgridcommandbuttonbase = wijgridcommandbuttonbase;

        /** @ignore */
        var wijgridcommandbuttonbase_options = (function () {
            function wijgridcommandbuttonbase_options() {
                this.text = undefined;
                this.click = undefined;
                this.iconClass = undefined;
                this.disabled = false;
                this.textDataKey = undefined;
            }
            return wijgridcommandbuttonbase_options;
        })();
        grid.wijgridcommandbuttonbase_options = wijgridcommandbuttonbase_options;

        wijgridcommandbuttonbase.prototype.options = wijmo.grid.extendWidgetOptions(wijmo.wijmoWidget.prototype.options, new wijgridcommandbuttonbase_options());

        $.wijmo.registerWidget("wijgridcommandbuttonbase", wijgridcommandbuttonbase.prototype);

        /** @ignore */
        var wijgridcommandlink = (function (_super) {
            __extends(wijgridcommandlink, _super);
            function wijgridcommandlink() {
                _super.apply(this, arguments);
            }
            wijgridcommandlink.prototype._createElement = function (settings) {
                var anchor = $("<a href=\"#\" />").text(settings.text || "");

                if (settings.disabled) {
                    anchor.prop("disabled", "disabled");
                }

                return anchor;
            };

            wijgridcommandlink.prototype._attachWidget = function (element, settings) {
            };

            wijgridcommandlink.prototype._onDisabledChanged = function (value) {
                var btn = this._btnElement();

                if (btn) {
                    btn.prop("disabled", value);
                }
            };
            return wijgridcommandlink;
        })(wijgridcommandbuttonbase);
        grid.wijgridcommandlink = wijgridcommandlink;

        $.wijmo.registerWidget("wijgridcommandlink", $.wijmo.wijgridcommandbuttonbase, wijgridcommandlink.prototype);

        /** @ignore */
        var wijgridcommandbutton = (function (_super) {
            __extends(wijgridcommandbutton, _super);
            function wijgridcommandbutton() {
                _super.apply(this, arguments);
            }
            wijgridcommandbutton.prototype._createElement = function (settings) {
                return $("<input type=\"button\" />").val(settings.text);
            };

            wijgridcommandbutton.prototype._attachWidget = function (element, settings) {
                element.button({ disabled: settings.disabled });
            };

            wijgridcommandbutton.prototype._onDisabledChanged = function (value) {
                var btn = this._btnElement();

                if (btn) {
                    btn.button({ disabled: value });
                }
            };
            return wijgridcommandbutton;
        })(wijgridcommandbuttonbase);
        grid.wijgridcommandbutton = wijgridcommandbutton;

        $.wijmo.registerWidget("wijgridcommandbutton", $.wijmo.wijgridcommandbuttonbase, wijgridcommandbutton.prototype);

        /** @ignore */
        var wijgridcommandimagebutton = (function (_super) {
            __extends(wijgridcommandimagebutton, _super);
            function wijgridcommandimagebutton() {
                _super.apply(this, arguments);
            }
            wijgridcommandimagebutton.prototype._createElement = function (settings) {
                var button, hasText = !!settings.text;

                if (settings.mobile) {
                    button = $("<input type=\"button\" />");

                    if (hasText) {
                        button.val(settings.text);
                    }
                } else {
                    button = $("<button />");

                    if (hasText) {
                        button.text(settings.text);
                    } else {
                        button.html("&nbsp;");
                    }
                }

                return button;
            };

            wijgridcommandimagebutton.prototype._attachWidget = function (element, settings) {
                var hasText = !!settings.text, options = {
                    disabled: settings.disabled
                };

                if (settings.mobile) {
                    options.icon = settings.iconClass;

                    if (!hasText) {
                        options.iconpos = "notext";
                    }
                } else {
                    options.icons = {
                        primary: settings.iconClass
                    };

                    options.text = hasText;
                }

                element.button(options);
            };

            wijgridcommandimagebutton.prototype._onDisabledChanged = function (value) {
                var btn = this._btnElement();

                if (btn) {
                    btn.button({ disabled: value });
                }
            };
            return wijgridcommandimagebutton;
        })(wijgridcommandbuttonbase);
        grid.wijgridcommandimagebutton = wijgridcommandimagebutton;

        $.wijmo.registerWidget("wijgridcommandimagebutton", $.wijmo.wijgridcommandbuttonbase, wijgridcommandimagebutton.prototype);

        /** @ignore */
        var wijgridcommandimage = (function (_super) {
            __extends(wijgridcommandimage, _super);
            function wijgridcommandimage() {
                _super.apply(this, arguments);
            }
            wijgridcommandimage.prototype._createElement = function (settings) {
                var button;

                if (settings.mobile) {
                    button = $("<input type=\"button\" />");
                } else {
                    button = $("<button />").html("&nbsp;");
                }

                return button;
            };

            wijgridcommandimage.prototype._attachWidget = function (element, settings) {
                var options = {
                    disabled: settings.disabled
                };

                if (settings.mobile) {
                    options.icon = settings.iconClass;
                    options.iconpos = "notext";
                } else {
                    options.icons = {
                        primary: settings.iconClass
                    };
                    options.text = false;
                }

                element.button(options);
            };

            wijgridcommandimage.prototype._onDisabledChanged = function (value) {
                var btn = this._btnElement();

                if (btn) {
                    btn.button({ disabled: value });
                }
            };
            return wijgridcommandimage;
        })(wijgridcommandbuttonbase);
        grid.wijgridcommandimage = wijgridcommandimage;

        $.wijmo.registerWidget("wijgridcommandimage", $.wijmo.wijgridcommandbuttonbase, wijgridcommandimage.prototype);
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="interfaces.ts"/>
/// <reference path="c1basefield.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    (function (grid) {
        var $ = jQuery;

        

        // An "abstract" class without a factory.
        var c1buttonbasefield = (function (_super) {
            __extends(c1buttonbasefield, _super);
            function c1buttonbasefield() {
                _super.apply(this, arguments);
            }
            c1buttonbasefield.test = function (options) {
                return !!(options && options.buttonType);
            };

            c1buttonbasefield.prototype._provideDefaults = function () {
                _super.prototype._provideDefaults.call(this);

                wijmo.grid.shallowMerge(this.options, c1buttonbasefield.prototype.options);

                this.options.dataKey = null;
            };

            c1buttonbasefield.prototype._createCommand = function (container, cmd, row, clickCallback) {
                var text = cmd.text;

                if (wijmo.grid.validDataKey(cmd.textDataKey) && row.data) {
                    var dataVal = row.data[cmd.textDataKey];
                    if ($.isFunction(dataVal)) {
                        dataVal = dataVal();
                    }

                    text = wijmo.grid.stringFormat(text, dataVal);
                }

                var btnOptions = $.extend({}, {
                    mobile: this._owner()._isMobileEnv(),
                    //text: cmd.text,
                    text: text,
                    iconClass: cmd.iconClass,
                    disabled: this._owner().options.disabled,
                    click: function (e) {
                        var processDefault = true;

                        if ($.isFunction(cmd.click)) {
                            var res = cmd.click.apply(this, [
                                e, {
                                    row: row,
                                    column: this.options
                                }]);

                            processDefault = (res !== false) && !e.isDefaultPrevented(); // let user to cancel the action
                        }

                        if (processDefault && clickCallback) {
                            clickCallback.apply(this, [e, { row: row }]);
                        }

                        e.preventDefault(); // prevent # beging added to url.
                    }
                });

                var btnContainer = $("<div />");
                container.append(btnContainer);

                switch (this.options.buttonType) {
                    case "link":
                        btnContainer.wijgridcommandlink(btnOptions);
                        break;

                    case "imageButton":
                        btnContainer.wijgridcommandimagebutton(btnOptions);
                        break;

                    case "button":
                        btnContainer.wijgridcommandbutton(btnOptions);
                        break;

                    case "image":
                        btnContainer.wijgridcommandimage(btnOptions);
                        break;

                    default:
                        throw "Unknown buttonType";
                }
            };
            return c1buttonbasefield;
        })(grid.c1basefield);
        grid.c1buttonbasefield = c1buttonbasefield;

        var c1buttonbasefield_options = (function (_super) {
            __extends(c1buttonbasefield_options, _super);
            function c1buttonbasefield_options() {
                _super.apply(this, arguments);
                /** Gets or sets the type of the button in the column. Possible values are "link", "button", "imageButton", "image".
                * @example
                * $("#element").wijgrid({ columns: [{ buttonType: "button" }]});
                */
                this.buttonType = "button";
            }
            return c1buttonbasefield_options;
        })(grid.c1basefield_options);
        grid.c1buttonbasefield_options = c1buttonbasefield_options;
        ;

        c1buttonbasefield.prototype.options = wijmo.grid.extendWidgetOptions(grid.c1basefield.prototype.options, new c1buttonbasefield_options());
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

var wijmo;
(function (wijmo) {
    (function (_grid) {
        var $ = jQuery;

        var c1buttonfield = (function (_super) {
            __extends(c1buttonfield, _super);
            function c1buttonfield(wijgrid, options, widgetName) {
                _super.call(this, wijgrid, options, widgetName || c1buttonfield.WIDGET_NAME);
            }
            c1buttonfield.test = function (options) {
                return !!(_grid.c1buttonbasefield.test(options) || options.command);
            };

            c1buttonfield.prototype._provideDefaults = function () {
                _super.prototype._provideDefaults.call(this);

                wijmo.grid.shallowMerge(this.options, _grid.c1basefield.prototype.options);

                this.options.command = this.options.command || {};
                wijmo.grid.shallowMerge(this.options.command, c1buttonfield.prototype.options.command);
            };

            //#region rendering
            c1buttonfield.prototype._setupDataCell = function (container, formattedValue, row) {
                this._createCommand(container, this.options.command, row, null);
            };
            c1buttonfield.WIDGET_NAME = "wijmo.c1buttonfield";
            return c1buttonfield;
        })(_grid.c1buttonbasefield);
        _grid.c1buttonfield = c1buttonfield;

        var c1buttonfield_options = (function (_super) {
            __extends(c1buttonfield_options, _super);
            function c1buttonfield_options() {
                _super.apply(this, arguments);
                /** Represents options of a command button.
                * @example
                * $("#element").wijgrid({
                *    columns: [{
                *       buttonType: "link",
                *       command: {
                *          text: "myCommand",
                *          click: function (e, args) {
                *             alert("clicked!");
                *          }
                *       }
                *    }]
                * });
                */
                this.command = undefined;
            }
            return c1buttonfield_options;
        })(_grid.c1buttonbasefield_options);
        _grid.c1buttonfield_options = c1buttonfield_options;
        ;

        c1buttonfield.prototype.options = wijmo.grid.extendWidgetOptions(_grid.c1buttonbasefield.prototype.options, new c1buttonfield_options());

        wijmo.grid.registerColumnFactory(function (grid, column) {
            if (c1buttonfield.test(column)) {
                return new c1buttonfield(grid, column);
            }

            return null;
        });
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

var wijmo;
(function (wijmo) {
    (function (_grid) {
        var $ = jQuery;

        var c1commandbuttonfield = (function (_super) {
            __extends(c1commandbuttonfield, _super);
            function c1commandbuttonfield(wijgrid, options, widgetName) {
                _super.call(this, wijgrid, options, widgetName || c1commandbuttonfield.WIDGET_NAME);
            }
            c1commandbuttonfield.test = function (options) {
                return !!((options.showDeleteButton && options.showDeleteButton !== false) || (options.showEditButton && options.showEditButton !== false) || options.cancelCommand || options.deleteCommand || options.editCommand || options.updateCommand);
            };

            c1commandbuttonfield.prototype._provideDefaults = function () {
                _super.prototype._provideDefaults.call(this);

                wijmo.grid.shallowMerge(this.options, c1commandbuttonfield.prototype.options);

                this.options.cancelCommand = this.options.cancelCommand || {};
                wijmo.grid.shallowMerge(this.options.cancelCommand, c1commandbuttonfield.prototype.options.cancelCommand);

                this.options.deleteCommand = this.options.deleteCommand || {};
                wijmo.grid.shallowMerge(this.options.deleteCommand, c1commandbuttonfield.prototype.options.deleteCommand);

                this.options.editCommand = this.options.editCommand || {};
                wijmo.grid.shallowMerge(this.options.editCommand, c1commandbuttonfield.prototype.options.editCommand);

                this.options.updateCommand = this.options.updateCommand || {};
                wijmo.grid.shallowMerge(this.options.updateCommand, c1commandbuttonfield.prototype.options.updateCommand);
            };

            //#region rendering
            c1commandbuttonfield.prototype._setupDataCell = function (container, formattedValue, row) {
                var opt = this.options, grid = this._owner();

                if (row.state & 16 /* editing */) {
                    if (opt.showEditButton) {
                        this._createCommand(container, opt.updateCommand, row, function (e, arg) {
                            grid.updateRow();
                        });

                        container.append(document.createTextNode("\u00A0"));

                        this._createCommand(container, opt.cancelCommand, row, function (e, arg) {
                            grid.cancelRowEditing();
                        });
                    }
                } else {
                    if (opt.showEditButton) {
                        this._createCommand(container, opt.editCommand, row, function (e, arg) {
                            grid.editRow(row.dataItemIndex);
                        });
                    }

                    if (opt.showDeleteButton) {
                        if (opt.showEditButton) {
                            container.append(document.createTextNode("\u00A0"));
                        }

                        this._createCommand(container, opt.deleteCommand, row, function (e, arg) {
                            grid.deleteRow(row.dataItemIndex);
                        });
                    }
                }

                container.addClass("wijmo-wijgrid-innercell-command");
            };
            c1commandbuttonfield.WIDGET_NAME = "wijmo.c1commandbuttonfield";
            return c1commandbuttonfield;
        })(_grid.c1buttonbasefield);
        _grid.c1commandbuttonfield = c1commandbuttonfield;

        var c1commandbuttonfield_options = (function (_super) {
            __extends(c1commandbuttonfield_options, _super);
            function c1commandbuttonfield_options() {
                _super.apply(this, arguments);
                /** Gets or sets a value indicating whether a Delete button is displayed in a command column.
                * @example
                * $("#element").wijgrid({
                *    columns: [{
                *       showDeleteButton: true
                *    }]
                * });
                */
                this.showDeleteButton = false;
                /** Gets or sets a value indicating whether an Edit button is displayed in a command column.
                * @example
                * $("#element").wijgrid({
                *    columns: [{
                *       showEditButton: true
                *    }]
                * });
                */
                this.showEditButton = false;
                /** Represents options of a Cancel command button.
                * @example
                * $("#element").wijgrid({
                *    columns: [{
                *       cancelCommand: {
                *          text: "Cancel!"
                *       }
                *    }]
                * });
                */
                this.cancelCommand = {
                    text: "Cancel",
                    iconClass: "ui-icon-close",
                    click: undefined,
                    textDataKey: undefined
                };
                /** Represents options of a Delete command button.
                * @example
                * $("#element").wijgrid({
                *    columns: [{
                *       deleteCommand: {
                *          text: "Delete!"
                *       }
                *    }]
                * });
                */
                this.deleteCommand = {
                    text: "Delete",
                    iconClass: "ui-icon-trash",
                    click: undefined,
                    textDataKey: undefined
                };
                /** Represents options of a Delete command button.
                * @example
                * $("#element").wijgrid({
                *    columns: [{
                *       deleteCommand: {
                *          text: "Edit!"
                *       }
                *    }]
                * });
                */
                this.editCommand = {
                    text: "Edit",
                    iconClass: "ui-icon-pencil",
                    click: undefined,
                    textDataKey: undefined
                };
                /** Represents options of a Delete command button.
                * @example
                * $("#element").wijgrid({
                *    columns: [{
                *       deleteCommand: {
                *          text: "Update!"
                *       }
                *    }]
                * });
                */
                this.updateCommand = {
                    text: "Update",
                    iconClass: "ui-icon-disk",
                    click: undefined,
                    textDataKey: undefined
                };
            }
            return c1commandbuttonfield_options;
        })(_grid.c1buttonbasefield_options);
        _grid.c1commandbuttonfield_options = c1commandbuttonfield_options;

        c1commandbuttonfield.prototype.options = wijmo.grid.extendWidgetOptions(_grid.c1buttonbasefield.prototype.options, new c1commandbuttonfield_options());

        wijmo.grid.registerColumnFactory(function (grid, column) {
            if (c1commandbuttonfield.test(column)) {
                return new c1commandbuttonfield(grid, column);
            }

            return null;
        });
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="interfaces.ts"/>
var wijmo;
(function (wijmo) {
    (function (grid) {
        var $ = jQuery;

        /** @ignore */
        var bandProcessor = (function () {
            function bandProcessor() {
            }
            bandProcessor.prototype.generateSpanTable = function (root) {
                this._height = this._width = this._inc = this._shift = 0;
                this._table = [];
                this._traverseList = [];
                this._savedXPos = [];

                return this._generateSpanTable(root, true);
            };

            bandProcessor.prototype._generateSpanTable = function (root, parentVisibility) {
                this._height = this.getVisibleHeight(root, parentVisibility);

                this._traverseList = wijmo.grid.flatten(root);
                this._width = this._traverseList.length;

                for (var i = 0; i < this._height; i++) {
                    this._table[i] = [];

                    for (var j = 0; j < this._width; j++) {
                        this._table[i][j] = { column: null, colSpan: 0, rowSpan: 0 };
                    }
                }

                this._setTableValues(root, 0, 0);

                return this._table;
            };

            bandProcessor.prototype.getVisibleHeight = function (root, parentVisibility) {
                var result = 0;

                if ($.isArray(root)) {
                    for (var i = 0, len = root.length; i < len; i++) {
                        var tmp = this.getVisibleHeight(root[i], parentVisibility);
                        result = Math.max(result, tmp);
                    }
                } else {
                    var rootC = root, colVis = (rootC.visible === undefined) ? true : rootC.visible;

                    rootC._parentVis = colVis && parentVisibility;

                    if ($.isArray(rootC.columns)) {
                        for (var i = 0, len = rootC.columns.length; i < len; i++) {
                            tmp = this.getVisibleHeight(rootC.columns[i], rootC._parentVis);
                            result = Math.max(result, tmp);
                        }

                        if (!rootC._parentVis) {
                            return result;
                        }

                        rootC._isLeaf = (result === 0);
                        result++;
                    } else {
                        rootC._isLeaf = true;
                        if (rootC._parentVis) {
                            result = 1;
                        }
                    }
                }

                return result;
            };

            bandProcessor.prototype._getVisibleParent = function (column) {
                while (column) {
                    column = this._traverseList[column._parentIdx];
                    if (column && (column._parentVis || column._parentVis === undefined)) {
                        return column;
                    }
                }

                return null;
            };

            bandProcessor.prototype._setTableValues = function (root, y, x) {
                var tx, posX;

                if ($.isArray(root)) {
                    for (var i = 0, len = root.length; i < len; i++) {
                        this._setTableValues(root[i], y, x);
                    }
                } else {
                    var rootC = root;

                    if (rootC._travIdx === undefined) {
                        throw "undefined travIdx";
                    }

                    tx = x + this._shift;

                    if (rootC._parentVis) {
                        posX = tx + this._inc;
                        this._table[y][posX].column = rootC;
                        this._savedXPos[rootC._travIdx] = posX;
                    }

                    if ($.isArray(rootC.columns)) {
                        for (i = 0, len = rootC.columns.length; i < len; i++) {
                            this._setTableValues(rootC.columns[i], y + 1, x);
                        }
                    }

                    if (rootC._parentVis) {
                        if (this._shift - tx === 0) {
                            this._table[y][this._savedXPos[rootC._travIdx]].rowSpan = this._height - y;
                            this._shift++;
                        } else {
                            this._table[y][this._savedXPos[rootC._travIdx]].colSpan = this._shift - tx;
                        }
                    } else {
                        if (!($.isArray(rootC.columns)) && this._height > 0) {
                            var visibleParent = this._getVisibleParent(rootC), parentIsLeaf = (visibleParent) ? visibleParent._isLeaf : false;

                            if (parentIsLeaf) {
                                this._inc++;
                            }

                            if (y >= this._height) {
                                y = this._height - 1;
                            }

                            posX = x + this._shift + this._inc;

                            this._table[y][posX].column = rootC;

                            if (!parentIsLeaf) {
                                if (visibleParent && (this._savedXPos[visibleParent._travIdx] === posX)) {
                                    this._shiftTableElements(posX, y);
                                }

                                this._inc++;
                            }
                        }
                    }
                }
            };

            bandProcessor.prototype._shiftTableElements = function (x, untilY) {
                for (var i = 0; i < untilY; i++) {
                    this._table[i][x + 1] = this._table[i][x];
                    this._table[i][x] = { column: null, colSpan: 0, rowSpan: 0 };

                    if (this._table[i][x + 1].column) {
                        this._savedXPos[this._table[i][x + 1].column._travIdx]++;
                    }
                }
            };
            return bandProcessor;
        })();
        grid.bandProcessor = bandProcessor;

        /** @ignore */
        function flatten(columns) {
            var result = [];

            wijmo.grid.traverse(columns, function (column) {
                result.push(column);
            });

            return result;
        }
        grid.flatten = flatten;

        /** @ignore */
        function getTompostParent(column, allColumnsTraverseList) {
            if (!column || !allColumnsTraverseList || (column.options._parentIdx === -1)) {
                return null;
            }

            var parent = allColumnsTraverseList[column.options._parentIdx];

            if (parent.options._parentIdx === -1) {
                return parent;
            }

            return wijmo.grid.getTompostParent(parent, allColumnsTraverseList);
        }
        grid.getTompostParent = getTompostParent;

        /** @ignore */
        function isChildOf(allColumns, child, parent) {
            if ($.isArray(parent.options.columns) && child.options._parentIdx >= 0) {
                if (child.options._parentIdx === parent.options._travIdx) {
                    return true;
                }

                if (child.options._parentIdx > parent.options._travIdx) {
                    while (true) {
                        child = allColumns[child.options._parentIdx];

                        if (child.options._travIdx === parent.options._travIdx) {
                            return true;
                        }

                        if (child.options._parentIdx === -1) {
                            break;
                        }
                    }
                }
            }

            return false;
        }
        grid.isChildOf = isChildOf;

        /** @ignore */
        function setTraverseIndex(columns) {
            return _setTraverseIndex(columns, 0, -1);
        }
        grid.setTraverseIndex = setTraverseIndex;

        function _setTraverseIndex(columns, idx, parentIdx) {
            if (columns) {
                for (var i = 0, len = columns.length; i < len; i++) {
                    var column = columns[i];

                    if (column.options) {
                        column = column.options;
                    }

                    column._linearIdx = i;
                    column._travIdx = idx++;
                    column._parentIdx = parentIdx;

                    if (column.columns) {
                        idx = _setTraverseIndex(column.columns, idx, idx - 1);
                    }
                }
            }

            return idx;
        }

        

        

        /** @ignore */
        function traverse(columns, callback) {
            if (columns && ($.isFunction(callback))) {
                for (var i = 0; i < columns.length; i++) {
                    var column = columns[i];

                    if (column.options) {
                        column = column.options;
                    }

                    var len = columns.length;

                    callback(column, columns);

                    if (columns.length !== len) {
                        i--;
                        continue;
                    }

                    if (column.columns) {
                        wijmo.grid.traverse(column.columns, callback);
                    }
                }
            }
        }
        grid.traverse = traverse;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="interfaces.ts"/>
/// <reference path="filterOperators.ts"/>
/// <reference path="misc.ts"/>
var wijmo;
(function (wijmo) {
    /// <reference path="../../../data/src/dataView.ts"/>
    /// <reference path="../../../data/src/filtering.ts"/>
    (function (_grid) {
        var $ = jQuery;

        

        

        

        

        

        /** @ignore */
        var settingsManager = (function () {
            function settingsManager(wijgrid) {
                this._dvFilteringSettings = undefined;
                this._dvPagingSettings = undefined;
                this._dvSortingSettings = undefined;
                this._wgFilteringSettings = undefined;
                this._wgPagingSettings = undefined;
                this._wgSortingSettings = undefined;
                if (!wijgrid) {
                    throw "exception";
                }

                this._wijgrid = wijgrid;
                this._dataView = wijgrid.mDataViewWrapper.dataView();
                this._filterCache = new wijmo.grid.filterOperatorsCache(wijgrid);
            }
            settingsManager.prototype.compareSettings = function () {
                var result = true, len;

                // paging
                var aPgn = this.DVPagingSettings(), bPgn = this.WGPagingSettings();

                result = (aPgn === bPgn);

                if (!result && aPgn && bPgn) {
                    result = (aPgn.pageSize === bPgn.pageSize && aPgn.pageIndex === bPgn.pageIndex);
                }

                // sorting
                if (result) {
                    var aSrt = this.DVSortingSettings();
                    var bSrt = this.WGSortingSettings();

                    result = (aSrt === bSrt);

                    if (!result && aSrt && bSrt && ((len = aSrt.length) === bSrt.length)) {
                        result = true;
                        for (var i = 0; i < len && result; i++) {
                            result = ((aSrt[i].dataKey === bSrt[i].dataKey) && (aSrt[i].sortDirection === bSrt[i].sortDirection));
                        }
                    }
                }

                // filtering
                if (result) {
                    var aFltr = this.DVFilteringSettings(), bFltr = this.WGFilteringSettings();

                    result = wijmo.grid.compareObj(aFltr, bFltr);
                }

                return result;
            };

            settingsManager.prototype.DVFilteringSettings = function () {
                function traverse(filter, normalizedItem) {
                    var condition;

                    $.each(filter, function (i, item) {
                        if (typeof (item) === "string") {
                            condition = item;
                        } else {
                            if ($.isArray(item)) {
                                traverse(item, normalizedItem);
                            } else {
                                var filterDescr = item, normItem = normalizedItem;

                                normItem.value.push(filterDescr.value);

                                normItem.operator.push({
                                    name: (filterDescr.customProps && filterDescr.customProps.originalOperator) || filterDescr.operator,
                                    condition: condition
                                });
                            }
                        }
                    });
                }

                if (this._dvFilteringSettings === undefined) {
                    var foo = [], filter = this._dataView.filter();

                    if (filter) {
                        $.each(filter, function (dataKey, item) {
                            var normalizedItem = {
                                operator: undefined,
                                owner: null,
                                dataKey: dataKey
                            };

                            if ($.isArray(item)) {
                                normalizedItem.value = [];
                                normalizedItem.operator = [];

                                traverse(item, normalizedItem);
                            } else if ($.isPlainObject(item)) {
                                var filterDescriptor = item;

                                normalizedItem.value = filterDescriptor.value;
                                normalizedItem.operator = (filterDescriptor.customProps && filterDescriptor.customProps.originalOperator) || item.operator || "Equals";

                                normalizedItem.customProps = filterDescriptor.customProps;
                            } else {
                                normalizedItem.value = item;
                                normalizedItem.operator = "Equals";
                            }

                            foo.push(normalizedItem);
                        });
                    }

                    this._dvFilteringSettings = (foo.length) ? foo : null;
                }

                return this._dvFilteringSettings;
            };

            settingsManager.prototype.DVPagingSettings = function () {
                if (this._dvPagingSettings === undefined) {
                    var pageableDataView = wijmo.grid.asPagedDataView(this._dataView);

                    if (pageableDataView) {
                        var pageSize = pageableDataView.pageSize();

                        this._dvPagingSettings = (pageSize > 0) ? {
                            pageSize: pageableDataView.pageSize(),
                            pageIndex: pageableDataView.pageIndex()
                        } : null;
                    }
                }

                return this._dvPagingSettings;
            };

            settingsManager.prototype.DVSortingSettings = function () {
                if (this._dvSortingSettings === undefined) {
                    var foo = [];

                    if (true) {
                        var sortDescription = wijmo.data.sorting.compile(this._dataView.sort()).normalized;

                        if (sortDescription) {
                            $.each(sortDescription, function (key, prop) {
                                if (prop !== null) {
                                    foo.push({
                                        dataKey: (typeof prop === "string") ? prop : prop.property,
                                        sortDirection: prop.asc || prop.asc === undefined ? "ascending" : "descending",
                                        sortOrder: undefined,
                                        customProps: prop.customProps
                                    });
                                }
                            });
                        }
                    }

                    this._dvSortingSettings = (foo.length) ? foo : null;
                }

                return this._dvSortingSettings;
            };

            settingsManager.prototype.WGFilteringSettings = function () {
                var _this = this;
                if (this._wgFilteringSettings === undefined) {
                    var foo = [], grid = this._wijgrid, leaves = grid._leaves() || [], dataFieldsMap = {};

                    // process columns
                    $.each(leaves, function (key, column) {
                        if (column instanceof _grid.c1field) {
                            var opt = column.options, filterValue = wijmo.grid.deepExtend({}, { foo: opt.filterValue }).foo, filterOperator = wijmo.grid.deepExtend({}, { foo: opt.filterOperator }).foo, filter = wijmo.grid.filterHelper.verify(filterOperator, filterValue, opt.dataType, _this._filterCache);

                            if (filter) {
                                foo.push({
                                    owner: column,
                                    dataKey: opt.dataKey,
                                    value: filter.value,
                                    operator: filter.operator,
                                    customProps: {
                                        travIdx: opt._travIdx
                                    }
                                });
                            }

                            dataFieldsMap[(opt.dataKey + "").toLowerCase()] = column;
                        }
                    });

                    // handle master-detail relation
                    if (!grid._isRoot()) {
                        var relation = grid.options.relation, masterInfo = grid._masterInfo(), masterDataKey = masterInfo.master.details()[masterInfo.dataRowIndex].masterKey();

                        for (var i = 0; i < relation.length; i++) {
                            var r = relation[i], column = dataFieldsMap[r.detailDataKey.toLowerCase()];

                            foo.push({
                                owner: column,
                                dataKey: r.detailDataKey,
                                value: masterDataKey[r.masterDataKey.toLowerCase()],
                                operator: "Equals"
                            });
                        }
                    }

                    this._wgFilteringSettings = (foo.length) ? foo : null;
                }

                return this._wgFilteringSettings;
            };

            settingsManager.prototype.WGPagingSettings = function () {
                if (this._wgPagingSettings === undefined) {
                    this._wgPagingSettings = this._wijgrid.options.allowPaging ? {
                        pageSize: this._wijgrid.options.pageSize,
                        pageIndex: this._wijgrid.options.pageIndex
                    } : null;
                }

                return this._wgPagingSettings;
            };

            settingsManager.prototype.WGSortingSettings = function () {
                if (this._wgSortingSettings === undefined) {
                    var sortDictionary = {}, sortArray = [], groupedColumns = this._wijgrid._groupedLeaves(true), leaves = this._wijgrid._leaves(), sortOrder = 0;

                    // fill the sortedDictionary with the grouped columns first
                    $.each(groupedColumns, function (i, column) {
                        if (column._isSortable()) {
                            var opt = column.options;

                            if (opt.sortDirection === "none") {
                                opt.sortDirection = "ascending"; // use "ascending" for grouped columns by default
                            }

                            sortDictionary[opt.dataKey] = {
                                dataKey: opt.dataKey,
                                sortDirection: opt.sortDirection,
                                sortOrder: sortOrder++,
                                customProps: {
                                    travIdx: opt._travIdx
                                }
                            };
                        }
                    });

                    sortOrder++;

                    // add other columns
                    $.each(leaves, function (i, column) {
                        if ((column instanceof _grid.c1field) && column._isSortable()) {
                            var opt = column.options;

                            if (opt.sortDirection === "ascending" || opt.sortDirection === "descending") {
                                if (!sortDictionary[opt.dataKey]) {
                                    sortDictionary[opt.dataKey] = {
                                        dataKey: opt.dataKey,
                                        sortDirection: opt.sortDirection,
                                        sortOrder: (opt._sortOrder || 0) + sortOrder,
                                        customProps: {
                                            travIdx: opt._travIdx
                                        }
                                    };
                                }
                            }
                        }
                    });

                    // convert {} to []
                    $.each(sortDictionary, function (key, value) {
                        sortArray.push(value);
                    });

                    // sort by sortOrder
                    sortArray.sort(function (a, b) {
                        return a.sortOrder - b.sortOrder;
                    });

                    $.each(sortArray, function (i, item) {
                        delete item.sortOrder;
                    });

                    this._wgSortingSettings = (sortArray.length) ? sortArray : null;
                }

                return this._wgSortingSettings;
            };

            settingsManager.prototype.MapWGToDV = function () {
                var _this = this;
                var result = {}, foo, newDVFilterOption;

                // * paging *
                if (this._mapPagingParams() && (foo = this.WGPagingSettings())) {
                    result.pageIndex = foo.pageIndex;
                    result.pageSize = foo.pageSize;
                } else {
                    result.pageSize = -1; // cancel paging
                }

                // ** sorting
                if (this._mapSortingParams()) {
                    result.sort = []; // clear sorting

                    if (foo = this.WGSortingSettings()) {
                        result.sort = [];
                        $.each(foo, function (key, o) {
                            result.sort.push({
                                property: o.dataKey,
                                asc: o.sortDirection === "ascending",
                                customProps: o.customProps
                            });
                        });
                    }
                }

                // sorting **
                this._wijgrid.mDeficientFilters = {};

                // ** filtering
                if (this._mapFilteringParams()) {
                    // fill the deficientFilters
                    $.each(this._wijgrid._leaves(), function (key, column) {
                        if (column instanceof _grid.c1field) {
                            var opt = column.options;

                            if ((opt.filterOperator === undefined) ^ (opt.filterValue === undefined)) {
                                _this._wijgrid.mDeficientFilters[opt.dataKey] = {
                                    operator: opt.filterOperator,
                                    value: opt.filterValue
                                };
                            }
                        }
                    });

                    result.filter = {};

                    // set filtering
                    if (foo = this.WGFilteringSettings()) {
                        result.filter = this._convertFilterToDV(foo);
                    }

                    if ($.isEmptyObject(result.filter)) {
                        result.filter = null; // must be null to clear filtering.
                    }
                }

                // filtering **
                return result;
            };

            settingsManager.prototype.MapDVToWG = function () {
                var foo, leavesByDataKey = {}, leavesByTravIdx = {}, mapSortingParams = this._mapSortingParams(), mapPagingParams = this._mapPagingParams(), mapFilteringParams = this._mapFilteringParams(), pagedDataView = wijmo.grid.asPagedDataView(this._dataView), self = this;

                $.each(this._wijgrid._leaves(), function (key, column) {
                    if (column instanceof _grid.c1field) {
                        var opt = column.options;

                        // clear sorting
                        if (mapSortingParams) {
                            opt._sortOrder = 0;
                            opt.sortDirection = "none";
                        }

                        // clear filtering
                        if (mapFilteringParams) {
                            opt.filterOperator = "nofilter";
                            opt.filterValue = undefined;
                        }

                        leavesByDataKey[opt.dataKey] = column;

                        if (opt._travIdx >= 0) {
                            leavesByTravIdx[opt._travIdx] = column;
                        }
                    }
                });

                if (mapPagingParams && pagedDataView) {
                    this._wijgrid.options.pageSize = pagedDataView.pageSize();
                    this._wijgrid.options.pageIndex = pagedDataView.pageIndex();
                }

                if (mapSortingParams && (foo = this.DVSortingSettings())) {
                    $.each(foo, function (idx, o) {
                        var column;

                        if (o.customProps && (o.customProps.travIdx >= 0)) {
                            column = leavesByTravIdx[o.customProps.travIdx]; // to resolve issue when grid contains multiple columns with the same dataKey
                        }

                        if (!column || (column.options.dataKey !== o.dataKey)) {
                            column = leavesByDataKey[o.dataKey];
                        }

                        if (column) {
                            column.options.sortDirection = o.sortDirection;
                            column.options._sortOrder = idx; // restore sort order
                        }
                    });
                }

                if (mapFilteringParams) {
                    if (foo = this.DVFilteringSettings()) {
                        $.each(foo, function (key, o) {
                            var column;

                            if (o.customProps && (o.customProps.travIdx >= 0)) {
                                column = leavesByTravIdx[o.customProps.travIdx]; // to resolve issue when grid contains multiple columns with the same dataKey
                            }

                            if (!column || (column.options.dataKey !== o.dataKey)) {
                                column = leavesByDataKey[o.dataKey];
                            }

                            if (column && !column._isDetailRelationField()) {
                                var opt = column.options;

                                opt.filterValue = o.value;
                                opt.filterOperator = o.operator;

                                if ($.isPlainObject(opt.filterOperator)) {
                                    opt.filterOperator = opt.filterOperator.name;
                                }

                                delete self._wijgrid.mDeficientFilters[opt.dataKey]; // unary operator?
                            }
                        });
                    }

                    $.each(this._wijgrid.mDeficientFilters, function (dataKey, value) {
                        var field = leavesByDataKey[dataKey];
                        if (field) {
                            var opt = leavesByDataKey[dataKey].options;

                            opt.filterOperator = value.operator;
                            opt.filterValue = value.value;
                        }
                    });
                }
            };

            settingsManager.prototype._mapPagingParams = function () {
                return this._wijgrid.options.allowPaging && !this._wijgrid._customPagingEnabled() && !this._wijgrid._serverShaping();
            };

            settingsManager.prototype._mapSortingParams = function () {
                return !this._wijgrid._serverShaping();
            };

            settingsManager.prototype._mapFilteringParams = function () {
                return !this._wijgrid._serverShaping();
            };

            settingsManager.prototype._getDateValueRequirements = function (column) {
                var opt = column.options;

                return opt.inputType ? _grid.TimeUnitConverter.convertInputType(opt.inputType) : _grid.TimeUnitConverter.convertFormatString(opt.dataFormatString || "d");
            };

            settingsManager.prototype.makeProxyFilter = function (column, prop, name, value) {
                name = name.toLowerCase();

                var self = this, colOpt = column.options, isDateColumn = (colOpt.dataType === "datetime"), result = {
                    property: prop,
                    operator: name,
                    value: value,
                    customProps: {
                        travIdx: colOpt._travIdx
                    }
                };

                var internalOp = this._filterCache.getByNameInt(name);
                var builtinOp = wijmo.data.filtering.ops[name];

                if ((name !== "nofilter") && (internalOp.isCustom || isDateColumn)) {
                    result.customProps.originalOperator = result.operator;

                    if (internalOp.isCustom) {
                        result.operator = $.extend(true, {}, internalOp.op);
                        result.operator.apply = result.operator.operator;
                    } else {
                        result.operator = $.extend(true, {}, builtinOp);

                        var filterRequirements = this._getDateValueRequirements(column);

                        result.operator.apply = function (a, b) {
                            if (!(a instanceof Date)) {
                                a = self._wijgrid.parse(colOpt, a);
                            }

                            if (!(b instanceof Date)) {
                                b = self._wijgrid.parse(colOpt, b);
                            }

                            _grid.TimeUnitConverter.cutDate(a, filterRequirements);
                            _grid.TimeUnitConverter.cutDate(b, filterRequirements);

                            return builtinOp.apply(a, b);
                        };
                    }
                }

                return result;
            };

            // conversion from wijgrid format
            settingsManager.prototype._convertFilterToDV = function (normalizedFilter) {
                var result = {}, manager = this;

                $.each(normalizedFilter, function (i, group) {
                    var prop = group.dataKey, currConds = [], currConn = "and", conn, operators, values, conds;

                    if (!$.isPlainObject(group))
                        return;

                    operators = group.operator;
                    values = group.value;

                    if (operators == null)
                        return;

                    if (!$.isArray(operators)) {
                        operators = [operators];
                    }

                    if (!$.isArray(values)) {
                        values = [values];
                    }

                    if (operators.length != values.length)
                        throw "The number of filter operators must match the number of filter values";

                    if (operators.length == 0)
                        return;

                    $.each(operators, function (i, operator) {
                        var value;

                        if (typeof operator === "string") {
                            operator = {
                                name: operator
                            };
                        }

                        if (!$.isPlainObject(operator) || !operator.name)
                            throw "Invalid filter operator";

                        value = values[i];

                        if (!$.isArray(value)) {
                            value = [value];
                        }

                        conds = $.map(value, function (operand) {
                            if (group.owner) {
                                if ((group.owner.options.dataType === "datetime") && (operand instanceof Date)) {
                                    _grid.TimeUnitConverter.cutDate(operand, manager._getDateValueRequirements(group.owner));
                                }

                                return manager.makeProxyFilter(group.owner, prop, operator.name, operand);
                            } else {
                                return {
                                    property: prop,
                                    operator: operator.name,
                                    value: operand
                                };
                            }
                        });

                        function adjustConds() {
                            if (conds.length > 1) {
                                conds.splice(0, 0, "or");
                            } else {
                                conds = conds[0];
                            }
                        }

                        function adjustCurrConds() {
                            if (currConn == null) {
                                currConn = conn;
                                currConds.splice(0, 0, conn);
                            }
                        }

                        currConn = null;
                        conn = operator.condition || "or";
                        if (currConds.length <= 1 || currConn == conn) {
                            if (conds.length == 1 || currConds.length <= 1 || currConn == "or") {
                                currConds = currConds.concat(conds);
                                adjustCurrConds();
                            } else {
                                adjustConds();
                                currConds.push(conds);
                                adjustCurrConds();
                            }
                        } else {
                            adjustConds();
                            currConds = [currConds, conds];
                            adjustCurrConds();
                        }
                    });

                    $.each(currConds, function (j, cond) {
                        if ($.isArray(cond) && cond.length == 2)
                            currConds[j] = cond[1];
                    });

                    if (currConds.length == 2 && typeof (currConds[0] === "string")) {
                        currConds.shift();
                    }

                    if (currConds.length == 1) {
                        currConds = currConds[0]; // unwrap single filter
                    }

                    result[prop] = currConds;
                }); // $.each(normalizedFilter)

                return result;
            };
            return settingsManager;
        })();
        _grid.settingsManager = settingsManager;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="../../../data/src/dataView.ts"/>
/// <reference path="../data/dataViewAdapter.ts"/>
/// <reference path="../data/koDataView.ts"/>
var wijmo;
(function (wijmo) {
    /// <reference path="interfaces.ts"/>
    /// <reference path="misc.ts"/>
    /// <reference path="wijgrid.ts"/>
    /// <reference path="settingsManager.ts"/>
    /// <reference path="htmlTableAccessor.ts"/>
    /// <reference path="tally.ts"/>
    (function (_grid) {
        var $ = jQuery;

        

        /** @ignore */
        var dataViewWrapper = (function () {
            function dataViewWrapper(wijgrid) {
                this._domSource = null;
                this._ignoreAllEvents = false;
                this._ignoreChangeEvent = false;
                this._ignoreCurrentChangedEvent = false;
                this._userData = null;
                this._totals = null;
                //private _propChangeListener: propChangeListener;
                this._changeTimer = 0;
                this._toDispose = [];
                this._isOwnDataView = false;
                this._isWijdatasource = false;
                this._isKODataView = false;
                this._isDynamicWijdatasource = false;
                this._wijgrid = wijgrid;
                this._createDataViewWrapper(); // set _dataView
            }
            dataViewWrapper.getMetadata = function (dataItem) {
                var expando;

                if (dataItem && (expando = wijmo.data.Expando.getFrom(dataItem, false)) && (expando = expando[wijmo.grid.EXPANDO])) {
                    return expando || null;
                }

                return null;
            };

            dataViewWrapper.testMetaForClass = function (meta, className) {
                if (meta) {
                    var ra = meta.rowAttributes;
                    return !!(ra && ra["class"] && (ra["class"].indexOf(className) >= 0));
                }

                return false;
            };

            dataViewWrapper.isHierarchyDetailItem = function (dataItem, metaOut) {
                var meta = wijmo.grid.dataViewWrapper.getMetadata(dataItem), res = false;

                if (meta) {
                    res = wijmo.grid.dataViewWrapper.testMetaForClass(meta, _grid.wijgrid.CSS.detailRow);
                }

                if (metaOut) {
                    metaOut.value = meta;
                }

                return res;
            };

            dataViewWrapper.prototype.data = function () {
                var dataView = this._getDataViewInst(), pagedDataView = wijmo.grid.asPagedDataView(dataView);

                return {
                    totalRows: pagedDataView != null ? pagedDataView.totalItemCount() : (dataView.getSource() || []).length,
                    totals: this._getTotals(),
                    emptyData: this.isBoundedToDOM() ? this._domSource.emptyData : null
                };
            };

            dataViewWrapper.prototype.dataView = function () {
                return this._getDataViewInst();
            };

            dataViewWrapper.prototype.dispose = function () {
                var dataView = this._getDataViewInst();

                //this._propChangeListener.dispose();
                $.each(this._toDispose, function (_, disposable) {
                    disposable.dispose();
                });

                if (dataView && this._isOwnDataView) {
                    dataView.dispose();
                }

                this._wijgrid.mWijDataView = null;
            };

            dataViewWrapper.prototype.ignoreChangeEvent = function (value) {
                if (arguments.length) {
                    this._ignoreChangeEvent = (value === true);
                } else {
                    return this._ignoreChangeEvent;
                }
            };

            dataViewWrapper.prototype.ignoreCurrentChangedEvent = function (value) {
                if (arguments.length) {
                    this._ignoreCurrentChangedEvent = (value === true);
                } else {
                    return this._ignoreCurrentChangedEvent;
                }
            };

            dataViewWrapper.prototype.isDataLoaded = function () {
                var dataView = this._getDataViewInst();
                return dataView.isLoaded();
            };

            dataViewWrapper.prototype.isOwnDataView = function () {
                return this._isOwnDataView;
            };

            dataViewWrapper.prototype.getFieldsInfo = function () {
                var dataView = this._getDataViewInst();

                return this._propDescriptorsToFieldsInfo(dataView.getProperties());
            };

            dataViewWrapper.prototype._propDescriptorsToFieldsInfo = function (propDescriptors) {
                var result = {};

                if (propDescriptors) {
                    $.each(propDescriptors, function (_, prop) {
                        if (prop.name === "$$hash" || prop.name === "$$hashKey") {
                            return;
                        }

                        result[prop.name] = {
                            name: prop.name,
                            type: prop.type || "string"
                        };
                    });
                }

                return result;
            };

            dataViewWrapper.prototype.isBoundedToDOM = function () {
                return this._domSource !== null;
            };

            dataViewWrapper.prototype.isKODataView = function () {
                return this._isKODataView;
            };

            dataViewWrapper.prototype.load = function (userData) {
                this._userData = userData;
                var dataView = this._getDataViewInst();

                if (!dataView) {
                    this._createDataViewWrapper();
                    dataView = this._getDataViewInst();
                }

                this._onDataViewLoading();

                var sm = new wijmo.grid.settingsManager(this._wijgrid);

                if ((userData && userData.forceDataLoad) || this._needToLoad(sm)) {
                    var loadParams = sm.MapWGToDV(), local = false;

                    if (this._isWijdatasource && !this._isDynamicWijdatasource && dataView.isLoaded()) {
                        local = true;
                    }

                    // ** ensure pageIndex
                    var pagedDataView = wijmo.grid.asPagedDataView(dataView), totalItems = -1;

                    // if paging is enabled and dataView provides totalItemCount then ensure that pageIndex is within[0; pageCount) range.
                    if (pagedDataView && (loadParams.pageSize >= 0) && ((totalItems = pagedDataView.totalItemCount()) >= 0)) {
                        // ** 47731: handle situation when underlying array was changed directly by user.
                        if (this._isOwnDataView && !this._isKODataView && !this._isDynamicWijdatasource && (pagedDataView.pageSize() > 0)) {
                            var source = pagedDataView.getSource();
                            if (source && (source.length < totalItems)) {
                                totalItems = source.length;
                            }
                        }

                        // 47731 **
                        var pageCount = Math.ceil(totalItems / loadParams.pageSize) || 1, pageIndex = loadParams.pageIndex;

                        if (pageIndex >= pageCount) {
                            pageIndex = Math.max(0, pageCount - 1);
                        }

                        loadParams.pageIndex = pageIndex;
                    }

                    // ensure pageIndex **
                    this.ignoreCurrentChangedEvent(true); // The currentPositionChanged event fires before the change event, stop listening. Listening will  be restored in the _onDataViewReset method.
                    dataView.refresh(loadParams, local);
                } else {
                    if (this.isDataLoaded()) {
                        this._onDataViewLoaded();
                        this._onDataViewReset(); // suppose that data is loaded, send notification to wijgrid.
                    }
                }
            };

            dataViewWrapper.prototype.currentPosition = function (rowIndex) {
                var dataView = this._getDataViewInst();

                if (!arguments.length) {
                    return dataView.currentPosition();
                }

                this.ignoreCurrentChangedEvent(true);

                try  {
                    dataView.currentPosition(rowIndex);
                } finally {
                    this.ignoreCurrentChangedEvent(false);
                }
            };

            dataViewWrapper.prototype.getValue = function (indexOrItem, key) {
                var dataView = this._getDataViewInst();

                if (typeof (key) === "number") {
                    key = key + "";
                }

                return dataView.getProperty(indexOrItem, key);
            };

            dataViewWrapper.prototype.setValue = function (indexOrItem, key, value) {
                var dataView = this._getDataViewInst();

                this.ignoreChangeEvent(true);

                try  {
                    if (typeof (key) === "number") {
                        key = key + "";
                    }

                    dataView.setProperty(indexOrItem, key, value);
                } finally {
                    this.ignoreChangeEvent(false);
                }
            };

            dataViewWrapper.prototype.makeDirty = function () {
                //this._propChangeListener.removeAll(); // remove old subscriptions
                this._totals = null;
            };

            dataViewWrapper.prototype._createDataViewWrapper = function () {
                var dataItemToGetProperties, data = this._wijgrid.options.data, dataView = this._getDataViewInst(), isWijdatasource = false;

                if (dataView) {
                    return;
                }

                if (!data) {
                    this._domSource = this._processDOM(this._wijgrid.element, this._wijgrid.options.readAttributesFromData);
                    data = this._domSource.items;
                }

                isWijdatasource = (typeof (wijdatasource) !== "undefined" && (data instanceof wijdatasource));
                this._isKODataView = data instanceof wijmo.grid.koDataView;
                this._isOwnDataView = ($.isArray(data) || isWijdatasource || this._isKODataView);
                this._isWijdatasource = !!(this._isOwnDataView && isWijdatasource);

                //this._isRemoteWijdatasource = !!(this._isOwnDataView && isWijdatasource && data.proxy);
                this._isDynamicWijdatasource = !!(this._isOwnDataView && isWijdatasource && data.dynamic);

                if (this._isOwnDataView && !this._isKODataView) {
                    if (!this._domSource && this._wijgrid.options.readAttributesFromData) {
                        this._moveAttributesToExpando(data);
                    }

                    var tBody = this.isBoundedToDOM() && wijmo.grid.getTableSection(this._wijgrid.element, 2 /* body */);

                    dataView = wijmo.grid.GridLocalDataDataView.create(wijmo.data.asDataView(this._parseOwnData(data, null, tBody)));
                } else {
                    // dataView = this._isKODataView ? data : wijmo.grid.GridDataView.create(data); // test for GridDataView instance (wijgridfilter)!
                    dataView = data;
                }

                this._wijgrid.mWijDataView = dataView;

                this._toDispose.push(dataView.isLoading.subscribe($.proxy(this._onDataViewLoadingInternal, this)));
                this._toDispose.push(dataView.isLoaded.subscribe($.proxy(this._onDataViewLoadedInternal, this)));
                this._toDispose.push(dataView.subscribe($.proxy(this._onDataViewChangeInternal, this)));
                this._toDispose.push(dataView.currentPosition.subscribe($.proxy(this._onDataViewCurrentChangedInternal, this)));
            };

            // if columns argument is null, then it will be autogenerated from the first data item
            dataViewWrapper.prototype._parseOwnData = function (data, columns, tbody) {
                if (data && data.length) {
                    var grid = this._wijgrid, dataLeaves = [];

                    if (!columns) {
                        columns = $.extend(true, [], this._wijgrid.options.columns);

                        var props = wijmo.data.ArrayDataViewBase._getProps(data[0]) || [], fieldsInfo = this._propDescriptorsToFieldsInfo(props);

                        grid._prepareColumns(columns, "merge", fieldsInfo, true, true, false);
                    }

                    wijmo.grid.traverse(columns, function (column) {
                        if (grid._needParseColumnDOM(column)) {
                            dataLeaves.push(column);
                        }
                    });

                    if (dataLeaves.length && tbody) {
                        var readerCulture = grid._getDOMReaderCulture();

                        $.each(data, function (i, dataItem) {
                            if (!wijmo.grid.dataViewWrapper.isHierarchyDetailItem(dataItem)) {
                                wijmo.grid.dataViewWrapper._parseDataItem(grid, dataItem, (tbody && tbody.rows[i]), dataLeaves, readerCulture);
                            }
                        });
                    }
                }

                return data;
            };

            dataViewWrapper._parseDataItem = function (parseHandler, dataItem, domRow, leaves, culture) {
                $.each(leaves, function (i, leaf) {
                    var value = dataItem[leaf.dataKey], newValue = parseHandler.parseCtx(leaf, value, dataItem, domRow.cells[leaf.dataKey], culture);

                    if (wijmo.grid.isNaN(newValue)) {
                        var domCell = null;

                        if (domRow) {
                            domCell = domRow.cells[leaf.dataKey];
                        }

                        newValue = parseHandler.parseCtxFailed(leaf, value, dataItem, domCell, culture);
                    }

                    dataItem[leaf.dataKey] = newValue;
                });

                return dataItem;
            };

            dataViewWrapper.prototype._getDataViewInst = function () {
                return this._wijgrid.mWijDataView;
            };

            dataViewWrapper.prototype._needToLoad = function (settingsManager) {
                var dataView = this._getDataViewInst();

                if (this._isDynamicWijdatasource || (this._isWijdatasource && !dataView.isLoaded())) {
                    return true;
                }

                if (this._isOwnDataView && !this._isWijdatasource && this.isDataLoaded()) {
                    return true;
                }

                if (this.isDataLoaded() || dataView.isLoading()) {
                    return !settingsManager.compareSettings();
                }

                return true;
            };

            dataViewWrapper.prototype._validateSettings = function (settingsManager) {
                if (!this._isOwnDataView && this._wijgrid.options.allowPaging && ((settingsManager.DVPagingSettings() || {}).pageSize !== (settingsManager.WGPagingSettings() || {}).pageSize)) {
                    throw "The pageSize option of the external dataView can't be changed.";
                }
            };

            // ** dataView events handlers
            dataViewWrapper.prototype._onDataViewLoadingInternal = function (isLoading) {
                if (this._ignoreAllEvents) {
                    return;
                }

                if (isLoading) {
                    if (!this._userData) {
                        this._onDataViewLoading();
                    }
                }
            };

            dataViewWrapper.prototype._onDataViewLoadedInternal = function (isLoaded) {
                if (this._ignoreAllEvents) {
                    return;
                }

                if (isLoaded) {
                    this._onDataViewLoaded();
                }
            };

            dataViewWrapper.prototype._onDataViewChangeInternal = function (args) {
                var self = this;

                if (this._ignoreAllEvents || this._ignoreChangeEvent) {
                    return;
                }

                if (args.changes) {
                    if (args.length && args[0].entityState() === "detached") {
                        return;
                    }

                    $.each(args.changes, function (_, change) {
                        switch (change.changeType) {
                            case "remove":
                                break;

                            case "add":
                                break;
                        }
                    });
                }

                this._onDataViewChange.apply(this, arguments);
            };

            dataViewWrapper.prototype._onDataViewCurrentChangedInternal = function () {
                if (this._ignoreAllEvents || this._ignoreCurrentChangedEvent) {
                    return;
                }

                this._onDataViewCurrentChanged.apply(this, arguments);
            };

            // dataView events handlers **
            // ** event handlers
            dataViewWrapper.prototype._onDataViewReset = function () {
                try  {
                    this.ignoreCurrentChangedEvent(false); // restore listening (see the load() method).
                    this.makeDirty(); // force to recreate  the _totals and _sharedDataItems fields when the this.data() method will be called.
                    this._wijgrid._onDataViewReset(this._userData, this._isKODataView); // 47851: recreate columns each time if koDataView is used to handle situation when observable array value was changed completely: viewModel.property([]) -> viewModel.property([a, b, c]).
                } finally {
                    this._userData = null;
                }
            };

            dataViewWrapper.prototype._onPropertyChanged = function (newValue) {
                var self = this;

                if (this._changeTimer > 0) {
                    window.clearTimeout(this._changeTimer);
                    this._changeTimer = 0;
                }

                if (this._changeTimer != -1) {
                    this._changeTimer = window.setTimeout(function () {
                        self._changeTimer = -1;

                        if (!self._wijgrid.mDestroyed) {
                            self._onDataViewChange();
                        }

                        self._changeTimer = 0;
                    }, 100);
                }
            };

            // args can be empty
            dataViewWrapper.prototype._onDataViewChange = function (args) {
                this._onDataViewReset(); // force re-rendering. TODO: handle "add", "remove", "modify" etc.
            };

            dataViewWrapper.prototype._onDataViewCurrentChanged = function (e, args) {
                this._wijgrid._onDataViewCurrentPositionChanged(e, args);
            };

            dataViewWrapper.prototype._onDataViewLoading = function () {
                this._wijgrid._onDataViewLoading();
            };

            dataViewWrapper.prototype._onDataViewLoaded = function () {
                this._wijgrid._onDataViewLoaded();
            };

            // event handlers **
            dataViewWrapper.prototype._getTotals = function () {
                if (!this._totals) {
                    var dataView = this._getDataViewInst();
                    this._totals = this._prepareTotals(dataView, this._wijgrid._prepareTotalsRequest());
                }

                if (!this._totals) {
                    this._totals = {};
                }

                return this._totals;
            };

            dataViewWrapper.prototype._prepareTotals = function (dataView, request) {
                if (!request || request.length === 0) {
                    return {};
                }

                var tallies = [], result = {};

                for (var i = 0, len = request.length; i < len; i++) {
                    tallies.push(new wijmo.grid.tally(this._wijgrid));
                }

                for (var i = 0, len = dataView.count(); i < len; i++) {
                    for (var j = 0, len2 = tallies.length; j < len2; j++) {
                        var opt = request[j].options;

                        tallies[j].add(this._wijgrid.parse(opt, this.getValue(i, opt.dataKey)));
                    }
                }

                for (var i = 0, len = tallies.length; i < len; i++) {
                    var opt = request[i].options;
                    result[opt.dataKey] = tallies[i].getValue(request[i]);
                }

                return result;
            };

            // ** DOM
            dataViewWrapper.prototype._processDOM = function ($obj, readAttributes) {
                var result = {
                    items: [],
                    emptyData: []
                };

                if (wijmo.grid.getTableSectionLength($obj, 2 /* body */) === 1 && $(wijmo.grid.getTableSectionRow($obj, 2 /* body */, 0)).hasClass(wijmo.grid.wijgrid.CSS.emptyDataRow)) {
                    result.emptyData = this._wijgrid._readTableSection($obj, 2 /* body */);
                } else {
                    result.items = this._wijgrid._readTableSection($obj, 2 /* body */, readAttributes);
                }

                return result;
            };

            // DOM **
            dataViewWrapper.prototype._moveAttributesToExpando = function (rawData) {
                $.each(rawData, function (i, item) {
                    var expando = wijmo.data.Expando.getFrom(item, true), rowMeta;

                    rowMeta = expando[wijmo.grid.EXPANDO] = { cellsAttributes: {}, rowAttributes: {} }; // store attributes within the original item using Expando

                    if (item.rowAttributes) {
                        rowMeta.rowAttributes = item.rowAttributes;
                        delete item.rowAttributes;
                    }
                    ;

                    $.each(item, function (dataKey, dataValue) {
                        if ($.isArray(dataValue)) {
                            rowMeta.cellsAttributes[dataKey] = dataValue[1];
                            item[dataKey] = dataValue[0];
                        }
                    });
                });
            };

            dataViewWrapper.prototype._wrapDataItem = function (dataItem, dataItemIndex) {
                return {
                    values: dataItem,
                    originalRowIndex: dataItemIndex
                };
            };

            // ** used by c1gridview to update underlying data during callbacks.
            dataViewWrapper.prototype._refreshSilent = function () {
                // used by c1gridview to refresh underlying data during callbacks.
                var dataView = this._getDataViewInst();

                if (dataView) {
                    try  {
                        this._ignoreAllEvents = true;
                        dataView.refresh();
                    } finally {
                        this._ignoreAllEvents = false;
                    }
                }
            };

            dataViewWrapper.prototype._unsafeReplace = function (index, newItem) {
                var dataView = this._getDataViewInst();

                if (!(dataView instanceof wijmo.grid.GridLocalDataDataView)) {
                    "operation is not supported";
                }

                dataView._unsafeReplace(index, newItem);
            };

            dataViewWrapper.prototype._unsafeSplice = function (index, count, item) {
                var dataView = this._getDataViewInst();

                if (!(dataView instanceof wijmo.grid.GridLocalDataDataView)) {
                    "operation is not supported";
                }

                if (arguments.length === 2) {
                    dataView._unsafeSplice(index, count);
                } else {
                    dataView._unsafeSplice(index, count, item);
                }
            };

            dataViewWrapper.prototype._unsafePush = function (item) {
                var dataView = this._getDataViewInst();

                if (!(dataView instanceof wijmo.grid.GridLocalDataDataView)) {
                    "operation is not supported";
                }

                dataView._unsafePush(item);
            };
            return dataViewWrapper;
        })();
        _grid.dataViewWrapper = dataViewWrapper;

        /** @ignore */
        function asPagedDataView(dataView) {
            return dataView && ("pageCount" in dataView) ? dataView : null;
        }
        _grid.asPagedDataView = asPagedDataView;

        /** @ignore */
        function asEditableDataView(dataView) {
            return dataView && ("commitEdit" in dataView) ? dataView : null;
        }
        _grid.asEditableDataView = asEditableDataView;

        /** @ignore */
        var propChangeListener = (function () {
            function propChangeListener(callback) {
                this._subscriptions = [];
                this._callback = callback;
            }
            propChangeListener.prototype.insert = function (index, dataViewItem) {
                var itemSubscrArray = null, self = this;

                $.each(dataViewItem, function (key, value) {
                    if (self._isValidPropName(key) && value && $.isFunction(value.subscribe)) {
                        itemSubscrArray = itemSubscrArray || [];
                        itemSubscrArray.push(value.subscribe(self._callback));
                    }
                });

                if (!itemSubscrArray) {
                    // we didn't subscribe in fact
                    return false;
                }

                if (this._subscriptions.length < index) {
                    // inflate the array before inserting
                    this._subscriptions.length = index;
                }
                this._subscriptions.splice(index, 0, itemSubscrArray);

                return true;
            };

            propChangeListener.prototype.remove = function (index) {
                var subscrArray = this._subscriptions[index];

                if (subscrArray) {
                    $.each(subscrArray, function (key, propSubscr) {
                        propSubscr.dispose();
                        subscrArray[key] = null;
                    });
                }

                this._subscriptions[index] = null;
                this._subscriptions.splice(index, 1);
            };

            propChangeListener.prototype.removeAll = function () {
                var len, subscr;

                while (len = this._subscriptions.length) {
                    this.remove(len - 1);
                }

                this._subscriptions = [];
            };

            propChangeListener.prototype.dispose = function () {
                this.removeAll();
            };

            propChangeListener.prototype._isValidPropName = function (name) {
                if (name && (typeof (name) === "string")) {
                    return name.match(/^entityState|jQuery/) === null;
                }

                return true;
            };
            return propChangeListener;
        })();
        _grid.propChangeListener = propChangeListener;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="../../../wijutil/jquery.wijmo.wijutil.ts" />
/// <reference path="interfaces.ts"/>
/// <reference path="merger.ts"/>
/// <reference path="wijgrid.ts"/>
/// <reference path="groupHelper.ts"/>
var wijmo;
(function (wijmo) {
    (function (_grid) {
        var $ = jQuery;

        /** @ignore */
        var groupRange = (function () {
            function groupRange(expanded, range, sum, position, hasHeaderOrFooter) {
                this.cr = new wijmo.grid.cellRange(-1, -1);
                this.isExpanded = false;
                this.position = "none";
                this._sum = -1;
                this._hasHeaderOrFooter = true;
                if (expanded !== undefined) {
                    this.isExpanded = expanded;
                }

                if (range !== undefined) {
                    this.cr = range;
                }

                if (sum !== undefined) {
                    this._sum = sum;
                }

                if (position !== undefined) {
                    this.position = position;
                }

                if (hasHeaderOrFooter !== undefined) {
                    this._hasHeaderOrFooter = hasHeaderOrFooter;
                }
            }
            groupRange.prototype.isSubRange = function (groupRange) {
                return ((this.cr.r1 >= groupRange.cr.r1) && (this.cr.r2 <= groupRange.cr.r2));
            };

            groupRange.prototype.toString = function () {
                return this.cr.r1 + "-" + this.cr.r2;
            };

            groupRange.prototype.collapse = function (grid, column) {
                var groupInfo = column.options.groupInfo, leaves = grid._leaves();

                if (wijmo.grid.groupHelper.isParentExpanded(leaves, this.cr, groupInfo.level)) {
                    if ((groupInfo.position !== "footer") && (groupInfo.outlineMode !== "none")) {
                        var groupedColumnsCnt = wijmo.grid.groupHelper.getGroupedColumnsCount(leaves);

                        this._collapse(grid, column, grid._rows(), leaves, this, groupedColumnsCnt, grid._allowVVirtualScrolling());
                    }
                }
            };

            groupRange.prototype.expand = function (grid, column, expandChildren) {
                var groupInfo = column.options.groupInfo, leaves = grid._leaves();

                if (wijmo.grid.groupHelper.isParentExpanded(leaves, this.cr, groupInfo.level)) {
                    var groupedColumnsCnt = wijmo.grid.groupHelper.getGroupedColumnsCount(leaves);

                    this._expand(grid, column, grid._rows(), leaves, this, groupedColumnsCnt, expandChildren, true, grid._allowVVirtualScrolling());
                }
            };

            // column - an owner of the groupRange
            groupRange.prototype._collapse = function (grid, column, rowAccessor, leaves, groupRange, groupedColumnsCnt, virtualScrollingEnabled) {
                var groupInfo = column.options.groupInfo, dataStart = groupRange.cr.r1, dataEnd = groupRange.cr.r2;

                switch (groupInfo.position) {
                    case "header":
                    case "headerAndFooter":
                        this._toggleSketchRowVisibility(grid.mSketchTable.row(groupRange.cr.r1), undefined, false);

                        if (!virtualScrollingEnabled) {
                            this._toggleRowVisibility(grid, rowAccessor.item(groupRange.cr.r1), undefined, false);
                        }

                        dataStart++;
                        break;
                }

                for (var i = dataStart; i <= dataEnd; i++) {
                    this._toggleSketchRowVisibility(grid.mSketchTable.row(i), false, undefined);

                    if (!virtualScrollingEnabled) {
                        this._toggleRowVisibility(grid, rowAccessor.item(i), false, undefined);
                    }
                }

                // update isExpanded property
                groupRange.isExpanded = false;

                for (var i = groupInfo.level + 1; i <= groupedColumnsCnt; i++) {
                    var childRangesInfo = wijmo.grid.groupHelper.getChildGroupRanges(leaves, groupRange.cr, i - 1);

                    if (childRangesInfo) {
                        var childRanges = childRangesInfo.ranges;

                        for (var j = 0, len = childRanges.length; j < len; j++) {
                            var childRange = childRanges[j];

                            childRange.isExpanded = false;

                            switch (childRangesInfo.column.options.groupInfo.position) {
                                case "header":
                                case "headerAndFooter":
                                    this._toggleSketchRowVisibility(grid.mSketchTable.row(childRange.cr.r1), false, false);

                                    if (!virtualScrollingEnabled) {
                                        this._toggleRowVisibility(grid, rowAccessor.item(childRange.cr.r1), false, false);
                                    }
                                    break;
                            }
                        }
                    }
                }
            };

            // column - an owner of the groupRange
            groupRange.prototype._expand = function (grid, column, rowAccessor, leaves, groupRange, groupedColumnsCnt, expandChildren, isRoot, virtualScrollingEnabled) {
                var groupInfo = column.options.groupInfo, dataStart = groupRange.cr.r1, dataEnd = groupRange.cr.r2;

                switch (groupInfo.position) {
                    case "header":
                        this._toggleSketchRowVisibility(grid.mSketchTable.row(dataStart), true, isRoot || expandChildren);

                        if (!virtualScrollingEnabled) {
                            this._toggleRowVisibility(grid, rowAccessor.item(dataStart), true, isRoot || expandChildren);
                        }

                        dataStart++;
                        break;

                    case "footer":
                        this._toggleSketchRowVisibility(grid.mSketchTable.row(dataEnd), true, undefined);

                        if (!virtualScrollingEnabled) {
                            this._toggleRowVisibility(grid, rowAccessor.item(dataEnd), true, undefined);
                        }

                        dataEnd--;
                        break;
                    case "headerAndFooter":
                        this._toggleSketchRowVisibility(grid.mSketchTable.row(dataStart), true, isRoot || expandChildren);

                        if (!virtualScrollingEnabled) {
                            this._toggleRowVisibility(grid, rowAccessor.item(dataStart), true, isRoot || expandChildren);
                        }

                        if (isRoot) {
                            this._toggleSketchRowVisibility(grid.mSketchTable.row(dataEnd), true, undefined);

                            if (!virtualScrollingEnabled) {
                                this._toggleRowVisibility(grid, rowAccessor.item(dataEnd), true, undefined);
                            }
                        }
                        dataStart++;
                        dataEnd--;
                        break;
                }

                if (isRoot) {
                    groupRange.isExpanded = true;
                } else {
                    return;
                }

                if (groupInfo.level === groupedColumnsCnt) {
                    for (var i = dataStart; i <= dataEnd; i++) {
                        this._toggleSketchRowVisibility(grid.mSketchTable.row(i), true, undefined);

                        if (!virtualScrollingEnabled) {
                            this._toggleRowVisibility(grid, rowAccessor.item(i), true, undefined);
                        }
                    }
                } else {
                    var childRangesInfo = wijmo.grid.groupHelper.getChildGroupRanges(leaves, groupRange.cr, groupInfo.level);

                    if (childRangesInfo) {
                        var childRanges = childRangesInfo.ranges, childColumn = childRangesInfo.column;

                        if (childRanges.length && (dataStart !== childRanges[0].cr.r1)) {
                            for (i = dataStart; i < childRanges[0].cr.r1; i++) {
                                this._toggleSketchRowVisibility(grid.mSketchTable.row(i), true, undefined);

                                if (!virtualScrollingEnabled) {
                                    this._toggleRowVisibility(grid, rowAccessor.item(i), true, undefined);
                                }
                            }
                        }

                        if (expandChildren) {
                            for (var i = 0, len = childRanges.length; i < len; i++) {
                                var childRange = childRanges[i];

                                this._expand(grid, childColumn, rowAccessor, leaves, childRange, groupedColumnsCnt, expandChildren, true, virtualScrollingEnabled);
                            }
                        } else {
                            for (var i = 0, len = childRanges.length; i < len; i++) {
                                var childRange = childRanges[i], childIsRoot = (childColumn.options.groupInfo.position === "footer" || childColumn.options.groupInfo.outlineMode === "none");

                                this._expand(grid, childColumn, rowAccessor, leaves, childRange, groupedColumnsCnt, false, childIsRoot, virtualScrollingEnabled);
                            }
                        }
                    }
                }
            };

            groupRange.prototype._toggleRowVisibility = function (grid, rowObj, visible, expanded) {
                if (rowObj) {
                    var rse = wijmo.grid.renderStateEx, view = grid._view(), rowInfo = view._getRowInfo(rowObj, false);

                    if (visible !== undefined) {
                        if (visible) {
                            rowInfo._extInfo.state &= ~1 /* hidden */;
                        } else {
                            rowInfo._extInfo.state |= 1 /* hidden */;
                        }
                    }

                    if (expanded !== undefined) {
                        if (expanded) {
                            rowInfo._extInfo.state &= ~2 /* collapsed */;
                        } else {
                            rowInfo._extInfo.state |= 2 /* collapsed */;
                        }
                    }

                    view._setRowInfo(rowInfo.$rows, rowInfo);

                    grid.mRowStyleFormatter._groupFormatter(rowInfo);
                }
            };

            groupRange.prototype._toggleSketchRowVisibility = function (sketchRow, visible, expanded) {
                if (sketchRow) {
                    var rse = wijmo.grid.renderStateEx;

                    if (visible !== undefined) {
                        if (visible) {
                            sketchRow.extInfo.state &= ~1 /* hidden */;
                        } else {
                            sketchRow.extInfo.state |= 1 /* hidden */;
                        }
                    }

                    if (expanded !== undefined) {
                        if (expanded) {
                            sketchRow.extInfo.state &= ~2 /* collapsed */;
                        } else {
                            sketchRow.extInfo.state |= 2 /* collapsed */;
                        }
                    }
                }
            };
            return groupRange;
        })();
        _grid.groupRange = groupRange;

        /** @ignore */
        var grouper = (function () {
            function grouper() {
                this.mGroupRowIdx = 0;
                this.mFirstVisbileLeafIndex = 0;
            }
            grouper.prototype.group = function (grid, data) {
                var _this = this;
                this.mGrid = grid;
                this.mLeaves = grid._leaves();
                this.mSketchTable = data;
                this.mGroupRowIdx = 0;

                var flag = false;

                $.each(this.mLeaves, function (i, column) {
                    var opt = column.options;

                    if (opt.groupInfo) {
                        delete opt.groupInfo.level;
                        delete opt.groupInfo.expandInfo;
                    }

                    // get index of the first visible leaf (excluding row header)
                    if (!flag && (flag = column._isFirstVisible())) {
                        _this.mFirstVisbileLeafIndex = i;
                    }
                });

                this._group();
            };

            grouper.prototype._group = function () {
                var _this = this;
                var groupedLeaves = this.mGrid._groupedLeaves(true), level = 1;

                if (groupedLeaves.length == 0) {
                    return;
                }

                // make sure all rows are created
                this.mSketchTable.ensureNotLazy();

                $.each(groupedLeaves, function (i, leaf) {
                    _this.mGroupRowIdx = 0;

                    if (_grid.c1field.isGroupedColumn(leaf)) {
                        var opt = leaf.options;

                        opt.groupInfo.level = level;
                        opt.groupInfo.expandInfo = [];

                        _this._processRowGroup(leaf, level++);
                    }
                });
            };

            grouper.prototype._processRowGroup = function (leaf, level) {
                var hasHeaderOrFooter = true, rse = wijmo.grid.renderStateEx;

                for (var rowIndex = 0; rowIndex < this.mSketchTable.count(); rowIndex++) {
                    var row = this.mSketchTable.row(rowIndex);

                    if (!row.isPureDataRow()) {
                        continue;
                    }

                    var cellRange = this._getGroupCellRange(rowIndex, leaf, level), isExpanded = true, startCollapsed = (leaf.options.groupInfo.outlineMode === "startCollapsed"), header, footer, groupRange, isParentCollapsed;

                    if (startCollapsed || wijmo.grid.groupHelper.isParentCollapsed(this.mLeaves, cellRange, level)) {
                        if ((leaf.options.groupInfo.groupSingleRow === false) && (cellRange.r1 === cellRange.r2)) {
                            continue;
                        }
                        isExpanded = false;
                    }

                    // indent
                    if (level && this.mGrid.options.groupIndent) {
                        for (var indentRow = cellRange.r1; indentRow <= cellRange.r2; indentRow++) {
                            this._addIndent(this.mSketchTable.row(indentRow).cell(this.mFirstVisbileLeafIndex), level);
                        }
                    }

                    hasHeaderOrFooter = !(leaf.options.groupInfo.groupSingleRow === false && (cellRange.r1 === cellRange.r2));

                    switch (leaf.options.groupInfo.position) {
                        case "header":
                            groupRange = this._addGroupRange(leaf.options.groupInfo, cellRange, isExpanded, hasHeaderOrFooter);

                            for (var i = cellRange.r1; i <= cellRange.r2; i++) {
                                row = this.mSketchTable.row(i);
                                row.extInfo.groupLevel = level + 1;
                                if (!isExpanded) {
                                    row.extInfo.state |= 1 /* hidden */;
                                }
                            }

                            if (!hasHeaderOrFooter) {
                                break;
                            }

                            this._updateByGroupRange(groupRange, level);

                            isParentCollapsed = wijmo.grid.groupHelper.isParentCollapsed(this.mLeaves, groupRange.cr, level);
                            header = this._buildGroupRow(leaf, groupRange, cellRange, true, isParentCollapsed);

                            this.mSketchTable.insert(cellRange.r1, header); // insert group header

                            header.extInfo.groupLevel = level;
                            if (!isExpanded) {
                                header.extInfo.state |= 2 /* collapsed */;
                            }
                            if (isParentCollapsed) {
                                header.extInfo.state |= 1 /* hidden */;
                            }

                            rowIndex = cellRange.r2 + 1;
                            break;

                        case "footer":
                            groupRange = this._addGroupRange(leaf.options.groupInfo, cellRange, true, hasHeaderOrFooter);

                            if (!hasHeaderOrFooter) {
                                break;
                            }

                            this._updateByGroupRange(groupRange, level);

                            footer = this._buildGroupRow(leaf, groupRange, cellRange, false, false);
                            footer.extInfo.groupLevel = level;

                            this.mSketchTable.insert(cellRange.r2 + 1, footer);
                            rowIndex = cellRange.r2 + 1;

                            isParentCollapsed = wijmo.grid.groupHelper.isParentCollapsed(this.mLeaves, groupRange.cr, level);
                            if (isParentCollapsed) {
                                footer.extInfo.state |= 1 /* hidden */;
                            }

                            break;

                        case "headerAndFooter":
                            groupRange = this._addGroupRange(leaf.options.groupInfo, cellRange, isExpanded, hasHeaderOrFooter);

                            for (i = cellRange.r1; i <= cellRange.r2; i++) {
                                row = this.mSketchTable.row(i);
                                row.extInfo.groupLevel = level + 1;
                                if (!isExpanded) {
                                    row.extInfo.state |= 1 /* hidden */;
                                }
                            }

                            if (!hasHeaderOrFooter) {
                                break;
                            }

                            this._updateByGroupRange(groupRange, level);

                            isParentCollapsed = wijmo.grid.groupHelper.isParentCollapsed(this.mLeaves, groupRange.cr, level);
                            header = this._buildGroupRow(leaf, groupRange, cellRange, true, isParentCollapsed);
                            footer = this._buildGroupRow(leaf, groupRange, cellRange, false, false);

                            this.mSketchTable.insert(cellRange.r2 + 1, footer);
                            footer.extInfo.groupLevel = level;
                            if (isParentCollapsed || !isExpanded) {
                                footer.extInfo.state |= 1 /* hidden */;
                            }

                            this.mSketchTable.insert(cellRange.r1, header);
                            header.extInfo.groupLevel = level;
                            if (!isExpanded) {
                                header.extInfo.state |= 2 /* collapsed */;
                            }
                            if (isParentCollapsed) {
                                header.extInfo.state |= 1 /* hidden */;
                            }

                            rowIndex = cellRange.r2 + 2;
                            break;

                        default:
                            throw wijmo.grid.stringFormat("Unknown Position value: \"{0}\"", leaf.options.groupInfo.position);
                    }

                    this.mGroupRowIdx++;
                }
            };

            grouper.prototype._buildGroupRow = function (column, groupRange, cellRange, isHeader, isParentCollapsed) {
                //when some column is hidden, the group row is not correct.
                var colOpt = column.options, groupInfo = colOpt.groupInfo, sketchRow = new _grid.SketchGroupRow(isHeader, null), groupByValue = undefined, groupByText = "", aggregate = "", defCSS = wijmo.grid.wijgrid.CSS;

                sketchRow.extInfo.groupIndex = this.mGroupRowIdx; // to make a row ID.

                if ((groupByValue = this.mSketchTable.valueAt(cellRange.r1, colOpt._leavesIdx)) !== null) {
                    if (this.mGrid.options.readAttributesFromData) {
                        // Avoid sutuation when grouped cell contains inplace editors (C1GridView, #64745)
                        var attrValue = this.mSketchTable.wijgridDataAttrValueAt(cellRange.r1, colOpt._leavesIdx);
                        if (attrValue) {
                            groupByValue = this.mGrid.parse(colOpt, attrValue);
                        }
                    }

                    groupByText = this.mGrid.toStr(colOpt, groupByValue);
                }

                sketchRow.groupByValue = groupByValue;

                if (this.mGrid._showRowHeader()) {
                    sketchRow.add(_grid.HtmlCell.nbsp());
                }

                // create the summary cell
                var cell = new _grid.HtmlCell("", null);

                sketchRow.add(cell);

                // add group header text
                if (colOpt.aggregate && (colOpt.aggregate !== "none")) {
                    aggregate = this._getAggregate(cellRange, column, column, isHeader, groupByText);
                }

                var caption = (isHeader) ? groupInfo.headerText : groupInfo.footerText;

                // format caption
                // The text may include up to three placeholders:
                // "{0}" is replaced with the value being grouped on and
                // "{1}" is replaced with the group's column header
                // "{2}" is replaced with the aggregate
                if (caption === "custom") {
                    var args = {
                        data: this.mSketchTable.getRawTable(),
                        column: colOpt,
                        groupByColumn: colOpt,
                        groupText: groupByText,
                        text: "",
                        groupingStart: cellRange.r1,
                        groupingEnd: cellRange.r2,
                        isGroupHeader: isHeader,
                        aggregate: aggregate
                    };

                    if (this.mGrid._trigger("groupText", null, args)) {
                        caption = args.text;
                    }
                } else {
                    if ((caption === undefined) || (caption === null)) {
                        if (isHeader) {
                            caption = "{1}: {0}";
                        }

                        if (aggregate || (aggregate === 0)) {
                            caption = caption ? caption + " {2}" : "{2}";
                        }
                    }

                    caption = wijmo.grid.stringFormat(caption, colOpt.encodeHtml ? wijmo.htmlEncode(groupByText) : groupByText, colOpt.headerText ? colOpt.headerText : "", this._wrapAggregateValue(aggregate));
                }

                if (!caption) {
                    caption = "&nbsp;";
                }

                cell.html += "<span>" + caption + "</span>";
                this._addIndent(cell, groupInfo.level - 1);

                // summary cells span until the end of the row or the first aggregate
                var span = 1, col = this.mGrid._virtualLeaves().length, bFirst = true;

                for (; col < this.mLeaves.length; col++) {
                    var tmp = this.mLeaves[col].options;

                    if (tmp._parentVis) {
                        if (bFirst) {
                            bFirst = false;
                            continue;
                        }
                        if ((tmp._dynamic !== true) && tmp.aggregate && (tmp.aggregate !== "none")) {
                            break;
                        }

                        span++;
                    }
                }

                for (; col < this.mLeaves.length; col++) {
                    var tmp2 = this.mLeaves[col];

                    if (tmp2.options._parentVis) {
                        var agg = "";

                        if (tmp2 instanceof _grid.c1field) {
                            agg = this._getAggregate(cellRange, tmp2, column, isHeader, groupByText);
                        }

                        agg = agg || "&nbsp;";

                        sketchRow.add(new _grid.HtmlCell(this._wrapAggregateValue(agg), {
                            groupInfo: {
                                leafIndex: tmp2.options._leavesIdx,
                                purpose: 1 /* aggregateCell */
                            }
                        }));
                    }
                }

                cell.ensureAttr().colSpan = span;
                cell.ensureAttr().groupInfo = { leafIndex: colOpt._leavesIdx, purpose: 0 /* groupCell */ }; // will be passed into the cellStyleFormatter

                return sketchRow;
            };

            grouper.prototype._getAggregate = function (cellRange, column, groupByColumn, isGroupHeader, groupByText) {
                var result = "";

                if (!column.options.aggregate || (column.options.aggregate === "none")) {
                    return result;
                }

                if (column.options.aggregate === "custom") {
                    var args = {
                        data: this.mSketchTable.getRawTable(),
                        column: column.options,
                        groupByColumn: groupByColumn.options,
                        groupText: groupByText,
                        text: "",
                        groupingStart: cellRange.r1,
                        groupingEnd: cellRange.r2,
                        isGroupHeader: isGroupHeader
                    };

                    var tmp = column.options.dataIndex;
                    try  {
                        column.options.dataIndex = column.options._leavesIdx; // workaround: change dataIndex since the sketchRow (args.data[i]) contains both bound and unbound cells.

                        if (this.mGrid._trigger("groupAggregate", null, args)) {
                            result = args.text;
                        }
                    } finally {
                        column.options.dataIndex = tmp; // restore
                    }
                } else {
                    var tally = new wijmo.grid.tally(this.mGrid);

                    for (var row = cellRange.r1; row <= cellRange.r2; row++) {
                        tally.add(this.mSketchTable.valueAt(row, column.options._leavesIdx));
                    }

                    result = wijmo.grid.tally.getValueString(tally.getValue(column), column, this.mGrid);
                }

                return result;
            };

            grouper.prototype._getGroupCellRange = function (rowIndex, leaf, level) {
                var idx = leaf.options._leavesIdx, row, range = new wijmo.grid.cellRange(rowIndex, idx), parentRange = wijmo.grid.groupHelper.getParentGroupRange(this.mLeaves, range, level), value, nextValue, count;

                row = this.mSketchTable.row(rowIndex);
                if (row.isPureDataRow()) {
                    value = row.valueCell(leaf.options._leavesIdx).value;

                    if (value instanceof Date) {
                        value = value.getTime();
                    }

                    for (range.r2 = rowIndex, count = this.mSketchTable.count() - 1; range.r2 < count; range.r2++) {
                        if (!this.mSketchTable.row(range.r2 + 1).isPureDataRow() || (parentRange && (range.r2 + 1 > parentRange.cr.r2))) {
                            break;
                        }

                        nextValue = this.mSketchTable.valueAt(range.r2 + 1, leaf.options._leavesIdx);

                        if (nextValue instanceof Date) {
                            nextValue = nextValue.getTime();
                        }

                        if (value !== nextValue) {
                            break;
                        }
                    }
                }

                return range;
            };

            grouper.prototype._addGroupRange = function (groupInfo, cellRange, isExpanded, hasHeaderOrFooter) {
                var result = null, idx = wijmo.grid.groupHelper.getChildGroupIndex(cellRange, groupInfo.expandInfo), range, expandState, r1, r2;

                if (idx >= 0 && idx < groupInfo.expandInfo.length) {
                    result = groupInfo.expandInfo[idx];
                } else {
                    range = new wijmo.grid.cellRange(cellRange.r1, cellRange.r1, cellRange.r2, cellRange.r2); // clone
                    expandState = (groupInfo.position === "footer" || !hasHeaderOrFooter) ? true : isExpanded && (groupInfo.outlineMode !== "startCollapsed");

                    result = new wijmo.grid.groupRange(expandState, range, -1, groupInfo.position, hasHeaderOrFooter);

                    groupInfo.expandInfo.push(result);
                }

                if (result && hasHeaderOrFooter) {
                    r1 = cellRange.r1;
                    r2 = cellRange.r2;

                    if (groupInfo.position === "headerAndFooter") {
                        r2 += 2;
                    }

                    if (groupInfo.position !== "headerAndFooter") {
                        r2++;
                    }

                    result.cr.r2 = r2;
                }

                return result;
            };

            grouper.prototype._updateByGroupRange = function (groupRange, level) {
                for (var i = 0, len = this.mLeaves.length; i < len; i++) {
                    var groupInfo = this.mLeaves[i].options.groupInfo;

                    if (groupInfo && (groupInfo.level < level)) {
                        var len2 = (groupInfo.expandInfo) ? groupInfo.expandInfo.length : 0;

                        for (var j = 0; j < len2; j++) {
                            var cur = groupInfo.expandInfo[j];
                            var delta = (groupRange.position === "headerAndFooter") ? 2 : 1;

                            if (cur.cr.r1 >= groupRange.cr.r1 && !((cur.cr.r1 === groupRange.cr.r1) && (cur.position === "footer"))) {
                                cur.cr.r1 += delta;
                            }

                            if (cur.cr.r2 >= groupRange.cr.r1) {
                                cur.cr.r2 += delta;
                            }
                        }
                    }
                }
            };

            grouper.prototype._addIndent = function (cellObj, level) {
                var indent;

                if (level > 0 && (indent = this.mGrid.options.groupIndent)) {
                    cellObj.ensureStyle().paddingLeft = (indent * level) + "px";
                }
            };

            grouper.prototype._wrapAggregateValue = function (value) {
                return "<span class='" + wijmo.grid.wijgrid.CSS.aggregateContainer + "'>" + value.toString() + "</span>";
                //return value.toString();
            };
            return grouper;
        })();
        _grid.grouper = grouper;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="interfaces.ts"/>
/// <reference path="merger.ts"/>
/// <reference path="grouper.ts"/>
var wijmo;
(function (wijmo) {
    (function (grid) {
        var $ = jQuery;

        /** @ignore */
        var groupHelper = (function () {
            function groupHelper() {
            }
            groupHelper.getGroupInfo = function (row) {
                if (row) {
                    var info = wijmo.grid.groupHelper._getGroupInfoRegExp.exec(row.id), level, index, isHeader;

                    if (info) {
                        level = parseInt(info[3], 10);
                        index = parseInt(info[2], 10);
                        isHeader = (info[1] === "H");

                        return {
                            level: level,
                            index: index,
                            isHeader: isHeader,
                            toString: function () {
                                return (isHeader ? "GH" : "GF") + index + "-" + level;
                            }
                        };
                    }
                }

                return null;
            };

            groupHelper.getColumnByGroupLevel = function (leaves, level) {
                for (var i = 0, len = leaves.length; i < len; i++) {
                    var leaf = leaves[i], opt = leaves[i].options;

                    if (opt.groupInfo && (opt.groupInfo.level === level)) {
                        return leaf;
                    }
                }

                return null;
            };

            groupHelper.getGroupedColumnsCount = function (leaves) {
                var result = 0;

                for (var i = 0, len = leaves.length; i < len; i++) {
                    var groupInfo = leaves[i].options.groupInfo;

                    if (groupInfo && (groupInfo.position === "header" || groupInfo.position === "headerAndFooter" || groupInfo.position === "footer")) {
                        result++;
                    }
                }

                return result;
            };

            // cellRange cellRange
            // groupRange[] childExpandInfo
            groupHelper.getChildGroupIndex = function (cellRange, childExpandInfo) {
                var left = 0, right = childExpandInfo.length - 1, median, cmp;

                while (left <= right) {
                    median = ((right - left) >> 1) + left;
                    cmp = childExpandInfo[median].cr.r1 - cellRange.r1;

                    if (cmp === 0) {
                        return median;
                    }

                    if (cmp < 0) {
                        left = median + 1;
                    } else {
                        right = median - 1;
                    }
                }

                return left;
                //return ~left;
            };

            groupHelper.getParentGroupIndex = function (cellRange, parentExpandInfo) {
                var idx = wijmo.grid.groupHelper.getChildGroupIndex(cellRange, parentExpandInfo);

                if (idx > 0) {
                    idx--;
                }

                //return (idx < parentExpandInfo.length)
                //	? idx
                //	: -1;
                if (idx < parentExpandInfo.length) {
                    var groupRange = parentExpandInfo[idx];
                    if ((cellRange.r1 >= groupRange.cr.r1) && (cellRange.r2 <= groupRange.cr.r2)) {
                        return idx;
                    }
                }

                return -1;
            };

            // level: 1-based level of the cellRange;
            groupHelper.getChildGroupRanges = function (leaves, cellRange, level) {
                var result = [], childGroupedColumn = wijmo.grid.groupHelper.getColumnByGroupLevel(leaves, level + 1);

                if (childGroupedColumn) {
                    var childRanges = childGroupedColumn.options.groupInfo.expandInfo, firstChildIdx = wijmo.grid.groupHelper.getChildGroupIndex(cellRange, childRanges);

                    for (var i = firstChildIdx, len = childRanges.length; i < len; i++) {
                        var childRange = childRanges[i];

                        if (childRange.cr.r2 <= cellRange.r2) {
                            result.push(childRange);
                        } else {
                            break;
                        }
                    }

                    return {
                        column: childGroupedColumn,
                        ranges: result
                    };
                }

                return null;
            };

            // level: 1-based level of the cellRange; optional.
            groupHelper.getParentGroupRange = function (leaves, cellRange, level) {
                if (level === undefined) {
                    level = 0xFFFF;
                }

                if (cellRange && (level - 2 >= 0)) {
                    for (var i = leaves.length - 1; i >= 0; i--) {
                        var groupInfo = leaves[i].options.groupInfo;

                        if (!groupInfo || !groupInfo.expandInfo || (groupInfo.level < 0) || (groupInfo.level !== level - 1)) {
                            continue;
                        }

                        var idx = wijmo.grid.groupHelper.getParentGroupIndex(cellRange, groupInfo.expandInfo);
                        if (idx >= 0) {
                            return groupInfo.expandInfo[idx];
                        }
                    }
                }

                return null;
            };

            // level: 1-based level of the cellRange.
            groupHelper.isParentCollapsed = function (leaves, cellRange, level) {
                if (level === 1) {
                    return false;
                }

                for (var i = level; i > 1; i--) {
                    var parentGroupRange = wijmo.grid.groupHelper.getParentGroupRange(leaves, cellRange, i);

                    if (!parentGroupRange) {
                        return false;
                    }

                    if (!parentGroupRange.isExpanded) {
                        return true;
                    }

                    cellRange = parentGroupRange.cr;
                }

                return false;
            };

            // level: 1-based level of the cellRange.
            groupHelper.isParentExpanded = function (leaves, cellRange, level) {
                if (level === 1) {
                    return true;
                }

                for (var i = level; i > 1; i--) {
                    var parentGroupRange = wijmo.grid.groupHelper.getParentGroupRange(leaves, cellRange, i);

                    if (!parentGroupRange || (parentGroupRange && parentGroupRange.isExpanded)) {
                        return true;
                    }

                    cellRange = parentGroupRange.cr;
                }

                return false;
            };
            groupHelper._getGroupInfoRegExp = new RegExp(".*G([HF]){1}(\\d+)-(\\d+)$");
            return groupHelper;
        })();
        grid.groupHelper = groupHelper;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="interfaces.ts"/>
var wijmo;
(function (wijmo) {
    (function (_grid) {
        var $ = jQuery;

        /** @ignore */
        var cellRange = (function () {
            function cellRange(row1, col1, row2, col2) {
                switch (arguments.length) {
                    case 2:
                        this.r1 = this.r2 = row1;
                        this.c1 = this.c2 = col1;
                        break;
                    case 4:
                        this.r1 = row1;
                        this.r2 = row2;
                        this.c1 = col1;
                        this.c2 = col2;
                        break;
                    default:
                        this.r1 = 0;
                        this.r2 = 0;
                        this.c1 = 0;
                        this.c2 = 0;
                }
            }
            cellRange.prototype.isSingleCell = function () {
                return ((this.r1 === this.r2) && (this.c1 === this.c2));
            };
            return cellRange;
        })();
        _grid.cellRange = cellRange;

        /** @ignore */
        var merger = (function () {
            function merger() {
            }
            merger.prototype.merge = function (grid, data) {
                this._leaves = grid._visibleLeaves();
                this._data = data;

                this._merge();
            };

            merger.prototype._merge = function () {
                var firstLeaf = true;

                for (var i = 0, len = this._leaves.length; i < len; i++) {
                    if (this._leaves[i] instanceof _grid.c1field) {
                        var leaf = this._leaves[i];

                        if (leaf.options.rowMerge === "free" || leaf.options.rowMerge === "restricted") {
                            if (firstLeaf) {
                                this._data.ensureNotLazy();
                                firstLeaf = false;
                            }
                            this._mergeColumn(leaf);
                        }
                    }
                }
            };

            merger.prototype._mergeColumn = function (column) {
                var cellIdx = column.options._leavesIdx;

                for (var i = 0, len = this._data.count(); i < len; i++) {
                    var row = this._data.row(i);

                    if (!row.isPureDataRow()) {
                        continue;
                    }

                    var range = this._getCellRange(i, column);

                    if (range.r1 !== range.r2) {
                        var span = range.r2 - range.r1 + 1;
                        this._data.row(range.r1).cell(cellIdx).ensureAttr().rowSpan = span;

                        for (var spannedRow = range.r1 + 1; spannedRow <= range.r2; spannedRow++) {
                            this._data.row(spannedRow).cell(cellIdx).visible(false);
                        }
                    }

                    i = range.r2;
                }
            };

            merger.prototype._getCellRange = function (rowIdx, column) {
                var cellIdx = column.options._leavesIdx, range = new wijmo.grid.cellRange(rowIdx, cellIdx), str = (this._data.valueAt(rowIdx, cellIdx) || "").toString(), dataLen = this._data.count();

                for (range.r2 = rowIdx; range.r2 < dataLen - 1; range.r2++) {
                    var row = this._data.row(range.r2 + 1);

                    if (!row.isPureDataRow() || ((row.valueCell(cellIdx).value || "").toString() !== str)) {
                        break;
                    }
                }

                var leafIdx = column.options._leavesIdx;

                if (leafIdx > 0 && column.options.rowMerge === "restricted") {
                    var prevLeaf = this._leaves[leafIdx - 1];

                    if (prevLeaf instanceof wijmo.grid.c1field) {
                        var range2 = this._getCellRange(rowIdx, prevLeaf);

                        range.r1 = Math.max(range.r1, range2.r1);
                        range.r2 = Math.min(range.r2, range2.r2);
                    }
                }

                return range;
            };
            return merger;
        })();
        _grid.merger = merger;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="interfaces.ts"/>
/// <reference path="../../../wijutil/jquery.wijmo.wijutil.ts" />
var wijmo;
(function (wijmo) {
    (function (grid) {
        var $ = jQuery;

        grid.EXPANDO = "__wijgrid";

        var rctrltrim = /^[\f\n\r\t]+|[\f\n\r\t]+$/g;

        /**
        * Specifies the type of a row in the grid.
        */
        (function (rowType) {
            /** The header row. */
            rowType[rowType["header"] = 1] = "header";

            /** Data row. */
            rowType[rowType["data"] = 2] = "data";

            /** Alternating data row (used only as modifier of the rowType.data, not as an independent value). */
            rowType[rowType["dataAlt"] = 4] = "dataAlt";

            /** Filter row. */
            rowType[rowType["filter"] = 8] = "filter";

            /** Group header row. */
            rowType[rowType["groupHeader"] = 16] = "groupHeader";

            /** Group footer row. */
            rowType[rowType["groupFooter"] = 32] = "groupFooter";

            /** Footer row. */
            rowType[rowType["footer"] = 64] = "footer";

            /** @ignore
            * Infrastructure.
            */
            rowType[rowType["emptyDataRow"] = 128] = "emptyDataRow";

            /** Hierarchy header row  (used only as modifier of the rowType.data, not as an independent value). */
            rowType[rowType["dataHeader"] = 256] = "dataHeader";

            /** @ignore
            * Infrastructure, modifer of the rowType.data
            */
            rowType[rowType["dataDetail"] = 512] = "dataDetail";

            /** Hierararchy detail row. */
            rowType[rowType["detail"] = 1024] = "detail";
        })(grid.rowType || (grid.rowType = {}));
        var rowType = grid.rowType;

        /**
        * Determines an object render state. This enumeration can be used with the cellStyleFormatter and rowStyleFormatter options to get a formatted object state.
        */
        (function (renderState) {
            /** This is the normal state. The object is rendered and not hovered, selected, or one of the elements determining the current position of the wijgrid. */
            renderState[renderState["none"] = 0] = "none";

            /** The object is being rendered. In the cellStyleFormatter, the rendered object is a table cell. In the rowStyleFormatter, the object is a table row. */
            renderState[renderState["rendering"] = 1] = "rendering";

            /** The object is one of the elements determining the current position of the wijgrid. */
            renderState[renderState["current"] = 2] = "current";

            /** The object is hovered over. */
            renderState[renderState["hovered"] = 4] = "hovered";

            /** The object is selected. */
            renderState[renderState["selected"] = 8] = "selected";

            /** @ignore. */
            renderState[renderState["editing"] = 16] = "editing";
        })(grid.renderState || (grid.renderState = {}));
        var renderState = grid.renderState;

        /**
        * Infrastructure.
        * @ignore
        */
        (function (renderStateEx) {
            renderStateEx[renderStateEx["none"] = 0] = "none";
            renderStateEx[renderStateEx["hidden"] = 1] = "hidden";
            renderStateEx[renderStateEx["collapsed"] = 2] = "collapsed";
        })(grid.renderStateEx || (grid.renderStateEx = {}));
        var renderStateEx = grid.renderStateEx;

        /**
        * Infrastructure.
        * @ignore
        */
        (function (rowScope) {
            rowScope[rowScope["table"] = 0] = "table";
            rowScope[rowScope["head"] = 1] = "head";
            rowScope[rowScope["body"] = 2] = "body";
            rowScope[rowScope["foot"] = 3] = "foot";
        })(grid.rowScope || (grid.rowScope = {}));
        var rowScope = grid.rowScope;

        /**
        * Infrastructure.
        * @ignore
        */
        (function (cellRangeExtendMode) {
            cellRangeExtendMode[cellRangeExtendMode["none"] = 0] = "none";
            cellRangeExtendMode[cellRangeExtendMode["column"] = 1] = "column";
            cellRangeExtendMode[cellRangeExtendMode["row"] = 2] = "row";
        })(grid.cellRangeExtendMode || (grid.cellRangeExtendMode = {}));
        var cellRangeExtendMode = grid.cellRangeExtendMode;

        /**
        * Infrastructure.
        * @ignore
        */
        (function (objectMode) {
            objectMode[objectMode["createIfNull"] = 0] = "createIfNull";
            objectMode[objectMode["createAlways"] = 1] = "createAlways";
            objectMode[objectMode["dispose"] = 2] = "dispose";
        })(grid.objectMode || (grid.objectMode = {}));
        var objectMode = grid.objectMode;

        /**
        * Determines purpose of the group row cells.
        * @ignore
        */
        (function (groupRowCellPurpose) {
            groupRowCellPurpose[groupRowCellPurpose["groupCell"] = 0] = "groupCell";
            groupRowCellPurpose[groupRowCellPurpose["aggregateCell"] = 1] = "aggregateCell";
        })(grid.groupRowCellPurpose || (grid.groupRowCellPurpose = {}));
        var groupRowCellPurpose = grid.groupRowCellPurpose;

        /**
        * Infrastructure.
        * @ignore
        */
        (function (dataRowsRangeMode) {
            dataRowsRangeMode[dataRowsRangeMode["sketch"] = 0] = "sketch";
            dataRowsRangeMode[dataRowsRangeMode["rendered"] = 1] = "rendered";
            dataRowsRangeMode[dataRowsRangeMode["renderable"] = 2] = "renderable";
        })(grid.dataRowsRangeMode || (grid.dataRowsRangeMode = {}));
        var dataRowsRangeMode = grid.dataRowsRangeMode;

        /**
        * Infrastructure.
        * @ignore
        */
        (function (intersectionMode) {
            intersectionMode[intersectionMode["none"] = 0] = "none";
            intersectionMode[intersectionMode["overlapTop"] = 1] = "overlapTop";
            intersectionMode[intersectionMode["overlapBottom"] = 2] = "overlapBottom";
            intersectionMode[intersectionMode["reset"] = 3] = "reset";
        })(grid.intersectionMode || (grid.intersectionMode = {}));
        var intersectionMode = grid.intersectionMode;

        /**
        * Infrastructure.
        * @ignore
        */
        (function (trimMethod) {
            trimMethod[trimMethod["none"] = 0] = "none";
            trimMethod[trimMethod["control"] = 1] = "control";
            trimMethod[trimMethod["all"] = 2] = "all";
        })(grid.trimMethod || (grid.trimMethod = {}));
        var trimMethod = grid.trimMethod;

        function emptyTable(table) {
            if (table) {
                while (table.rows.length) {
                    var row;

                    while ((row = table.rows[0]).cells.length) {
                        var cell = row.cells[0];

                        while (cell.firstChild) {
                            cell.removeChild(cell.firstChild);
                        }

                        row.deleteCell(0);

                        row = cell = null;
                    }

                    table.deleteRow(0);
                }

                while (table.firstChild) {
                    table.removeChild(table.firstChild);
                }
            }

            table = null;
        }
        grid.emptyTable = emptyTable;

        /** @ignore */
        function compareObj(a, b) {
            var flag;

            if ($.isArray(a) && $.isArray(b)) {
                if (a.length === b.length) {
                    flag = true;

                    for (var i = 0, len = a.length; i < len && flag; i++) {
                        flag = wijmo.grid.compareObj(a[i], b[i]);
                    }

                    return flag;
                }
            } else {
                if ($.isPlainObject(a) && $.isPlainObject(b)) {
                    for (var key in a) {
                        if (a.hasOwnProperty(key)) {
                            if (!wijmo.grid.compareObj(a[key], b[key])) {
                                return false;
                            }
                        }
                    }

                    for (var key in b) {
                        if (b.hasOwnProperty(key)) {
                            if (!wijmo.grid.compareObj(a[key], b[key])) {
                                return false;
                            }
                        }
                    }

                    return true;
                } else {
                    if (a instanceof Date) {
                        a = a.getTime();
                    }

                    if (b instanceof Date) {
                        b = b.getTime();
                    }
                }
            }

            return a === b;
        }
        grid.compareObj = compareObj;

        /** @ignore */
        function stringFormat(pattern) {
            var params = [];
            for (var _i = 0; _i < (arguments.length - 1); _i++) {
                params[_i] = arguments[_i + 1];
            }
            var i, len;

            if (!pattern) {
                return "";
            }

            for (i = 0, len = params.length; i < len; i++) {
                pattern = pattern.replace(new RegExp("\\{" + i + "\\}", "gm"), params[i]);
            }

            return pattern;
        }
        grid.stringFormat = stringFormat;

        /** @ignore */
        function validDataKey(dataKey) {
            return (dataKey && !(dataKey < 0)) || (dataKey === 0);
        }
        grid.validDataKey = validDataKey;

        /** @ignore */
        function validDate(date) {
            if (date && (date instanceof Date)) {
                return !isNaN(date.getTime());
            }

            return false;
        }
        grid.validDate = validDate;

        /** @ignore */
        function getDataType(column) {
            return column.dataType || "string";
        }
        grid.getDataType = getDataType;

        /** @ignore */
        function iterateChildrenWidgets(item, callback) {
            if (item && callback) {
                item.find(".ui-widget,.wijmo-wijgrid-root").each(function (index, dom) {
                    $.each($(dom).data(), function (dataKey, dataValue) {
                        if (dataValue.widgetName) {
                            callback(index, dataValue);
                        }
                    });

                    return true;
                });
            }
        }
        grid.iterateChildrenWidgets = iterateChildrenWidgets;

        /** @ignore */
        function remove$dataByPrefix(element, prefix) {
            var data$keys = [];

            $.each(element.data(), function (key) {
                if (key.indexOf(prefix) === 0) {
                    data$keys.push(key);
                }
            });

            $.each(data$keys, function (idx, key) {
                element.removeData(key);
            });
        }
        grid.remove$dataByPrefix = remove$dataByPrefix;

        /** @ignore */
        var domSelection = (function () {
            function domSelection(dom) {
                this._dom = dom;
            }
            // The 'dom' must be an input element
            domSelection.prototype.getSelection = function () {
                var start = 0, end = 0, textRange;

                if (this._dom.selectionStart !== undefined) {
                    start = this._dom.selectionStart;
                    end = this._dom.selectionEnd;
                } else {
                    if (document.selection) {
                        textRange = document.selection.createRange().duplicate();
                        end = textRange.text.length; // selection length
                        start = Math.abs(textRange.moveStart("character", -this._dom.value.length)); // move selection to the beginning
                        end += start;
                    }
                }

                return { start: start, end: end, length: end - start };
            };

            // The 'dom' must be an input element
            domSelection.prototype.setSelection = function (range) {
                if (this._dom.selectionStart !== undefined) {
                    this._dom.setSelectionRange(range.start, range.end);
                } else {
                    var textRange = this._dom.createTextRange();

                    textRange.collapse(true);
                    textRange.moveStart("character", range.start);
                    textRange.moveEnd("character", range.end);
                    textRange.select();
                }
            };

            domSelection.prototype.toggleSelection = function (enable) {
                var $dom = $(this._dom), useSelectStart = "onselectstart" in this._dom;

                if (enable) {
                    if (useSelectStart) {
                        $dom.unbind(".wijgrid-disableSelection");
                    } else {
                        $dom.css({ "MozUserSelect": "", "WebkitUserSelect": "" });
                    }
                } else {
                    if (useSelectStart) {
                        $dom.bind("selectstart.wijgrid-disableSelection", function (e) {
                            e.preventDefault();
                        });
                    } else {
                        $dom.css({ "MozUserSelect": "-moz-none", "WebkitUserSelect": "none" });
                    }
                }
            };
            return domSelection;
        })();
        grid.domSelection = domSelection;

        /** @ignore */
        function createDynamicField(options) {
            var opt = {};

            opt._dynamic = true;
            opt._isLeaf = true; // important!

            return $.extend(true, opt, options);
        }
        grid.createDynamicField = createDynamicField;

        /** @ignore */
        function bounds(element, client) {
            if (element) {
                var $dom = element.nodeType ? $(element) : element, offset = $dom.offset();

                if (offset) {
                    if (client) {
                        return { top: offset.top, left: offset.left, width: $dom[0].clientWidth || 0, height: $dom[0].clientHeight || 0 };
                    }

                    return { top: offset.top, left: offset.left, width: $dom.outerWidth(), height: $dom.outerHeight() };
                }
            }

            return null;
        }
        grid.bounds = bounds;

        /** @ignore */
        function ensureBounds(bounds, max) {
            if (bounds) {
                if (bounds.start < 0) {
                    bounds.start = 0;
                }

                if (bounds.end < 0) {
                    bounds.end = 0;
                }

                bounds.start = Math.min(bounds.start, max);

                bounds.end = Math.min(bounds.end, max);
            }

            return bounds;
        }
        grid.ensureBounds = ensureBounds;

        // maxDepth = -1 --  iterate through all child elements
        // default value = 3
        /** @ignore */
        function _getDOMText(dom, maxDepth, ignoreTextNodes) {
            if (!ignoreTextNodes && dom.nodeType === 3) {
                var nodeValue = (dom.nodeValue || "").replace(/[\r\t\n]+/g, "");
                return nodeValue;
            }

            if (dom && maxDepth !== 0) {
                if (!ignoreTextNodes && dom.nodeType === 3) {
                    return dom.nodeValue;
                }

                if (dom.nodeType === 1) {
                    switch (dom.type) {
                        case "button":
                        case "text":
                        case "textarea":
                        case "select-one":
                            return dom.value;
                        case "checkbox":
                            return dom.checked.toString();
                    }

                    // go deeper
                    var result = "", i = 0, child;

                    while (child = dom.childNodes[i++]) {
                        result += wijmo.grid._getDOMText(child, maxDepth - 1, ignoreTextNodes);
                    }

                    return result;
                }
            }

            return "";
        }
        grid._getDOMText = _getDOMText;

        /** @ignore */
        function isNaN(value) {
            return value !== value;
        }
        grid.isNaN = isNaN;

        // obj, prefix, name (opt), value (opt)
        /** @ignore */
        function dataPrefix(obj, prefix, name, value) {
            var treatAsArray = (obj.jquery || $.isArray(obj)), internalName = prefix + name;

            if (arguments.length === 3) {
                if (treatAsArray) {
                    return $.data(obj[0], internalName);
                }

                return $.data(obj, internalName);
            } else {
                if (treatAsArray) {
                    var tmp;

                    for (var i = 0, len = obj.length; i < len; i++) {
                        tmp = $.data(obj[i], internalName, value);
                    }

                    return tmp;
                }

                return $.data(obj, internalName, value);
            }
        }
        grid.dataPrefix = dataPrefix;

        /** @ignore */
        function shallowMerge(target, src) {
            if (src && target) {
                for (var name in src) {
                    if (src.hasOwnProperty(name)) {
                        var value = src[name], typeOf = typeof (value);

                        if ((typeOf === "string" || typeOf === "boolean" || typeOf === "number") && (target[name] === undefined)) {
                            target[name] = value;
                        }
                    }
                }
            }
        }
        grid.shallowMerge = shallowMerge;

        /** @ignore */
        function getAttributes(dom, prevent) {
            if (dom) {
                var cnt = 0, result = {};

                for (var i = 0, len = dom.attributes.length; i < len; i++) {
                    var attrName = dom.attributes[i].name;

                    if (attrName && (!prevent || !prevent(attrName))) {
                        var attrValue = dom.getAttribute(attrName);

                        if (attrName === "style") {
                            attrValue = (typeof (attrValue) === "object") ? attrValue.cssText : attrValue;
                        }

                        if (!attrValue && attrName === "class") {
                            attrValue = dom.getAttribute("className");
                        }

                        if (attrValue && (typeof (attrValue) !== "function")) {
                            result[attrName] = attrValue;
                            cnt++;
                        }
                    }
                }

                if (cnt) {
                    return result;
                }
            }

            return null;
        }
        grid.getAttributes = getAttributes;

        // unlike the jQuery.extend(true) function the deepExtend() function doesn't skips undefined values.
        /** @ignore */
        function deepExtend(source, target) {
            var key, src, dst, isArray, clone;

            if (source) {
                if (typeof (target) !== "object" && !$.isFunction(target)) {
                    target = {};
                }

                for (key in source) {
                    src = source[key];
                    dst = target[dst];

                    if (src === target) {
                        continue;
                    }

                    if (src && ($.isPlainObject(src) || (isArray = $.isArray(src)))) {
                        if (isArray) {
                            isArray = false;
                            clone = dst && $.isArray(dst) ? dst : [];
                        } else {
                            clone = dst && $.isPlainObject(dst) ? dst : {};
                        }

                        target[key] = wijmo.grid.deepExtend(src, clone);
                    } else {
                        target[key] = src;
                    }
                }
            }

            return target;
        }
        grid.deepExtend = deepExtend;

        

        

        /** @ignore */
        function widgetName(element, name) {
            if (element && element.jquery) {
                element = element[0];
            }

            if (element) {
                return (arguments.length === 1) ? $.data(element, "wijgridwidgetName") : $.data(element, "wijgridwidgetName", name);
            }

            return undefined;
        }
        grid.widgetName = widgetName;

        /** @ignore */
        var HTML5InputSupport = (function () {
            function HTML5InputSupport() {
            }
            HTML5InputSupport.isExtendSupportRequired = function (inputType) {
                inputType = (inputType || "").toLowerCase();

                return (inputType in wijmo.grid.HTML5InputSupport._requiresExtendedSupport);
            };

            HTML5InputSupport.getDefaultInputType = function (mobileEnvironment, column) {
                var inputType = (column.inputType || "").toLowerCase();

                if (!inputType && mobileEnvironment) {
                    switch (wijmo.grid.getDataType(column)) {
                        case "number":
                        case "currency":
                            inputType = "number";
                            break;

                        case "datetime":
                            inputType = "datetime";
                            break;
                    }
                }

                if (!inputType || ((inputType !== "text") && !HTML5InputSupport._isSupportedByBrowser(inputType))) {
                    inputType = "text"; // fallback to "text"
                }

                return inputType;
            };

            HTML5InputSupport.toStr = function (value, inputType) {
                var result = value;

                inputType = (inputType || "").toLowerCase();

                if (wijmo.grid.HTML5InputSupport.isExtendSupportRequired(inputType)) {
                    switch (inputType) {
                        case "datetime":
                            result = (value) ? result = Globalize.format(value, "yyyy-MM-ddTHH:mm:ssZ") : "";
                            break;

                        case "datetime-local":
                            result = (value) ? result = Globalize.format(value, "yyyy-MM-ddTHH:mm:ss") : "";
                            break;

                        case "date":
                            result = (value) ? result = Globalize.format(value, "yyyy-MM-dd") : "";
                            break;

                        case "month":
                            result = (value) ? result = Globalize.format(value, "yyyy-MM") : "";
                            break;

                        case "time":
                            result = (value) ? result = Globalize.format(value, "HH:mm:ss") : "";
                            break;
                    }
                } else {
                    result = value + "";
                }

                return result;
            };

            HTML5InputSupport.parse = function (value, inputType) {
                var result, fallback = function (date) {
                    date = new Date(date);
                    if (!wijmo.grid.validDate(date)) {
                        date = null;
                    }

                    return date;
                };

                inputType = (inputType || "").toLowerCase();

                if (wijmo.grid.HTML5InputSupport.isExtendSupportRequired(inputType)) {
                    switch (inputType) {
                        case "datetime":
                            result = Globalize.parseDate(value, "yyyy-MM-ddTHH:mm:ssZ") || Globalize.parseDate(value, "yyyy-MM-ddTHH:mmZ") || fallback(value);
                            break;
                        case "datetime-local":
                            result = Globalize.parseDate(value, "yyyy-MM-ddTHH:mm:ss") || Globalize.parseDate(value, "yyyy-MM-ddTHH:mm") || fallback(value);
                            break;

                        case "date":
                            result = Globalize.parseDate(value, "yyyy-MM-dd") || fallback(value);
                            break;

                        case "month":
                            result = Globalize.parseDate(value, "yyyy-MM");
                            break;

                        case "time":
                            result = Globalize.parseDate(value, "HH:mm:ss") || Globalize.parseDate(value, "HH:mm");
                            ;
                            break;

                        case "number":
                            result = parseFloat(value);
                    }
                } else {
                    result = value;
                }

                return result;
            };

            HTML5InputSupport.extend = function (value, extendWith, inputType) {
                if (!value) {
                    value = extendWith;
                } else {
                    inputType = (inputType || "").toLowerCase();

                    switch (inputType) {
                        case "date":
                            value.setFullYear(extendWith.getFullYear(), extendWith.getMonth(), extendWith.getDate());
                            break;

                        case "month":
                            value.setFullYear(extendWith.getFullYear(), extendWith.getMonth());
                            break;

                        case "time":
                            value.setHours(extendWith.getHours());
                            value.setMinutes(extendWith.getMinutes());
                            value.setSeconds(extendWith.getSeconds());
                            break;

                        default:
                            value = extendWith;
                    }
                }

                return value;
            };

            HTML5InputSupport._isSupportedByBrowser = function (inputType) {
                if (inputType) {
                    if (this._supportedInputTypesCache[inputType] === undefined) {
                        var success;

                        try  {
                            var $element = $("<input type='" + inputType + "' style='display:none' />");
                            success = true;
                        } catch (e) {
                            success = false;
                        }

                        this._supportedInputTypesCache[inputType] = success && ($element[0].type === inputType);
                    }

                    return this._supportedInputTypesCache[inputType];
                }

                return false;
            };
            HTML5InputSupport._requiresExtendedSupport = {
                "date": "",
                "datetime": "",
                "datetime-local": "",
                "month": "",
                "time": ""
            };

            HTML5InputSupport._supportedInputTypesCache = {};
            return HTML5InputSupport;
        })();
        grid.HTML5InputSupport = HTML5InputSupport;

        /** @ignore */
        function getZIndex(element, minValue) {
            if (typeof minValue === "undefined") { minValue = 99; }
            var zIndex = 0;

            if (element && $.ui && $.fn.zIndex) {
                zIndex = element.zIndex(); // try to get zIndex of the first z-indexed ancestor.

                if (zIndex) {
                    zIndex++; // get next value
                }
            }

            return Math.max(zIndex, minValue);
        }
        grid.getZIndex = getZIndex;

        // * taken from jQuery UI
        /** @ignore */
        function isOverAxis(x, reference, size) {
            // Determines when x coordinate is over "b" element axis
            return (x > reference) && (x < (reference + size));
        }
        grid.isOverAxis = isOverAxis;

        /** @ignore */
        function isOver(y, x, top, left, height, width) {
            // Determines when x, y coordinates is over "b" element
            return wijmo.grid.isOverAxis(y, top, height) && wijmo.grid.isOverAxis(x, left, width);
        }
        grid.isOver = isOver;

        // taken from jQuery UI *
        // ** uid
        var __uid = 0;

        /** @ignore */
        function getUID() {
            return "uid" + __uid++;
        }
        grid.getUID = getUID;

        // uid **
        /** @ignore */
        function isMobileSafari() {
            return !!(navigator && navigator.userAgent && (navigator.userAgent.match(/Mobile.*Safari/)) !== null);
        }
        grid.isMobileSafari = isMobileSafari;

        /** @ignore */
        function isMobile() {
            if (navigator) {
                var agent = (navigator.userAgent || "").toLowerCase();
                return !!(agent.indexOf("android") >= 0 || agent.match(/iphone|ipad|ipod|mobi/i));
            }
            return false;
        }
        grid.isMobile = isMobile;

        /** @ignore */
        function getWindowOrientation() {
            return window.orientation || 0;
        }
        grid.getWindowOrientation = getWindowOrientation;

        /** @ignore */
        function isPercentage(value) {
            return !!(value && (typeof (value) === "string") && (value[value.length - 1] === "%"));
        }
        grid.isPercentage = isPercentage;

        /** @ignore*/
        function rowObjToJQuery(row) {
            if (row) {
                if (row[1]) {
                    return $(row);
                }

                return $(row[0]);
            }

            return null;
        }
        grid.rowObjToJQuery = rowObjToJQuery;

        var __scrollBarSize = 0;

        /** @ignore */
        function getSuperPanelScrollBarSize() {
            if (!(__scrollBarSize > 0)) {
                if (document && document.body && $.support.isTouchEnabled && $.support.isTouchEnabled()) {
                    var $div;

                    try  {
                        $div = $("<div></div>").css({
                            overflow: "scroll",
                            width: 30,
                            height: 30,
                            position: "absolute",
                            visibility: "hidden"
                        }).append($("<div></div>").css({ width: 100, height: 100 })).appendTo(document.body);

                        __scrollBarSize = $div[0].offsetWidth - $div[0].clientWidth; // measure
                    } catch (ex) {
                    } finally {
                        if ($div) {
                            $div.remove();
                        }
                    }
                }

                if (!(__scrollBarSize > 0)) {
                    __scrollBarSize = 18; // use the default size of the wijsuperpanel' scrollbars
                }
            }

            return __scrollBarSize;
        }
        grid.getSuperPanelScrollBarSize = getSuperPanelScrollBarSize;

        /** @ignore */
        function getContent(element, decodeHTML, trim) {
            var value = "";

            if (decodeHTML && element.childNodes.length === 1 && element.firstChild.nodeType === 3) {
                value = (element.textContent !== undefined) ? element.textContent : element.innerText; // IE <= 8

                if (trim) {
                    value = (trim === 2 /* all */) ? $.trim(value) : trimCtrl(value);
                }

                if (value && (value.length === 1)) {
                    var ch = value.charCodeAt(0);

                    if ((ch === 160) || ((ch === 32) && ($.trim(element.innerHTML) === "&nbsp;"))) {
                        value = "";
                    }
                }
            } else {
                value = element.innerHTML;

                if (trim) {
                    value = (trim === 2 /* all */) ? $.trim(value) : trimCtrl(value);
                }

                if (value === "&nbsp;") {
                    value = "";
                }
            }

            return value;
        }
        grid.getContent = getContent;

        /** @ignore */
        function setContent(element, encodeHTML, value) {
            if (encodeHTML) {
                if (element.textContent !== undefined) {
                    element.textContent = value || "";
                } else {
                    element.innerText = value || ""; // IE <= 8
                }
            } else {
                element.innerHTML = value || "&nbsp;";
            }
        }
        grid.setContent = setContent;

        // removes control characters only from the beginning and the end of the string.
        /** @ignore */
        function trimCtrl(value) {
            return (value === null) ? "" : (value + "").replace(rctrltrim, "");
        }

        /** @ignore */
        var DataOptionPersister = (function () {
            function DataOptionPersister() {
            }
            DataOptionPersister.persistAndClear = function (options) {
                var result = {}, recurse = function (o, storage) {
                    if (o) {
                        if (o.data) {
                            storage.data = o.data;
                            o.data = undefined; // clear
                        }

                        if (o.detail) {
                            storage.detail = {};
                            recurse(o.detail, storage.detail);
                        }
                    }
                };

                recurse(options, result);

                return result;
            };

            DataOptionPersister.restore = function (options, storage) {
                var recurse = function (o, st) {
                    if (o && st) {
                        if (st.data) {
                            o.data = st.data;
                        }

                        recurse(o.detail, st.detail);
                    }
                };

                recurse(options, storage);
            };

            DataOptionPersister.persistAndClearIntoElement = function (element, options) {
                $.data(element, this.DATA_STORAGE_KEY, this.persistAndClear(options));
            };

            DataOptionPersister.restoreFromElement = function (element, options, removeData) {
                if (typeof removeData === "undefined") { removeData = false; }
                this.restore(options, $.data(element, this.DATA_STORAGE_KEY));

                if (removeData) {
                    $.removeData(element, this.DATA_STORAGE_KEY);
                }
            };
            DataOptionPersister.DATA_STORAGE_KEY = "wijgridDataStorage";
            return DataOptionPersister;
        })();
        grid.DataOptionPersister = DataOptionPersister;

        // * compatibility: export members to the $.wijmo.wijgrid "namespace" *
        $.extend($.wijmo.wijgrid, {
            rowType: wijmo.grid.rowType,
            renderState: wijmo.grid.renderState,
            bounds: wijmo.grid.bounds
        });
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

var wijmo;
(function (wijmo) {
    (function (grid) {
        /** @ignore */
        (function (TimeUnit) {
            TimeUnit[TimeUnit["Millisecond"] = 1] = "Millisecond";
            TimeUnit[TimeUnit["Second"] = 2] = "Second";
            TimeUnit[TimeUnit["Minute"] = 4] = "Minute";
            TimeUnit[TimeUnit["Hour"] = 8] = "Hour";
            TimeUnit[TimeUnit["Day"] = 16] = "Day";
            TimeUnit[TimeUnit["Month"] = 32] = "Month";
            TimeUnit[TimeUnit["Year"] = 64] = "Year";

            TimeUnit[TimeUnit["DATE"] = 64 /* Year */ | 32 /* Month */ | 16 /* Day */] = "DATE";
            TimeUnit[TimeUnit["TIME"] = 8 /* Hour */ | 4 /* Minute */ | 2 /* Second */ | 1 /* Millisecond */] = "TIME";
            TimeUnit[TimeUnit["ALL"] = TimeUnit.DATE | TimeUnit.TIME] = "ALL";
        })(grid.TimeUnit || (grid.TimeUnit = {}));
        var TimeUnit = grid.TimeUnit;
        ;

        /** @ignore */
        var TimeUnitConverter = (function () {
            function TimeUnitConverter() {
            }
            /**
            * @param inputType One of the HTML input type values (date-time).
            */
            TimeUnitConverter.convertInputType = function (inputType) {
                var formatString = wijmo.grid.TimeUnitConverter.convertInputTypeToFormatString(inputType), result = wijmo.grid.TimeUnitConverter.convertFormatString(formatString);

                return result;
            };

            TimeUnitConverter.convertInputTypeToFormatString = function (inputType) {
                switch ((inputType || "").toLowerCase()) {
                    case "datetime":
                    case "datetime-local":
                        return "f";

                    case "date":
                        return "d";

                    case "month":
                        return "Y";

                    case "time":
                        return "t";
                }

                return "";
            };

            /**
            * @param dateFormatString
            */
            TimeUnitConverter.convertFormatString = function (dateFormatString) {
                var result = 0;

                if (dateFormatString) {
                    // ** check one-char standard formats **
                    if (dateFormatString.length === 1) {
                        switch (dateFormatString[0]) {
                            case "t":
                                return 8 /* Hour */ | 4 /* Minute */;

                            case "T":
                                return TimeUnit.TIME;

                            case "d":
                            case "D":
                                return TimeUnit.DATE;

                            case "Y":
                                return 32 /* Month */ | 64 /* Year */;

                            case "M":
                                return 32 /* Month */ | 16 /* Day */;

                            case "f", "F", "S":
                                return TimeUnit.ALL;
                        }
                    }

                    // ** check custom tokens **
                    var quoteFirst, quoteLast;

                    // remove quoted text
                    if (((quoteFirst = dateFormatString.indexOf("'")) >= 0) && ((quoteLast = dateFormatString.lastIndexOf("'")) >= 0) && (quoteFirst !== quoteLast)) {
                        dateFormatString = dateFormatString.substr(0, quoteFirst) + dateFormatString.substring(quoteLast + 1, dateFormatString.length - 1);
                    }

                    for (var i = 0, len = dateFormatString.length; i < len; i++) {
                        switch (dateFormatString[i]) {
                            case "d":
                                result |= 16 /* Day */;
                                break;

                            case "M":
                                result |= 32 /* Month */;
                                break;

                            case "y":
                                result |= 64 /* Year */;
                                break;

                            case "m":
                                result |= 4 /* Minute */;
                                break;

                            case "h":
                            case "H":
                                result |= 8 /* Hour */;
                                break;

                            case "s":
                                result |= 2 /* Second */;
                                break;

                            case "f":
                                result |= 1 /* Millisecond */;
                                break;
                        }
                    }
                }

                return result || TimeUnit.ALL;
            };

            TimeUnitConverter.cutDate = function (date, timeUnit) {
                if (date) {
                    timeUnit = ~timeUnit;

                    if (timeUnit & 1 /* Millisecond */) {
                        date.setMilliseconds(0);
                    }

                    if (timeUnit & 2 /* Second */) {
                        date.setSeconds(0);
                    }

                    if (timeUnit & 4 /* Minute */) {
                        date.setMinutes(0);
                    }

                    if (timeUnit & 8 /* Hour */) {
                        date.setHours(0);
                    }

                    if (timeUnit & 16 /* Day */) {
                        date.setDate(1);
                    }

                    if (timeUnit & 32 /* Month */) {
                        date.setMonth(0);
                    }

                    if (timeUnit & 64 /* Year */) {
                        date.setFullYear(0);
                    }
                }

                return date;
            };
            return TimeUnitConverter;
        })();
        grid.TimeUnitConverter = TimeUnitConverter;

        /** @ignore */
        function lazy(eval, context) {
            var hasValue = false, value;
            return function () {
                if (!hasValue) {
                    value = context ? eval.call(context) : eval();
                    hasValue = true;
                }
                return value;
            };
        }
        grid.lazy = lazy;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="wijgrid.ts"/>
/// <reference path="interfaces.ts"/>
var wijmo;
(function (wijmo) {
    /// <reference path="../../../data/src/dataView.ts"/>
    /// <reference path="../../../data/src/filtering.ts"/>
    (function (grid) {
        var $ = jQuery;

        /** @ignore */
        var builtInFilterOperators = (function () {
            function builtInFilterOperators() {
            }
            builtInFilterOperators.NoFilterOp = {
                applicableTo: null,
                name: "NoFilter",
                displayName: "No filter",
                arity: 1,
                operator: function () {
                    return true;
                }
            };
            return builtInFilterOperators;
        })();

        /** @ignore */
        var filterOperatorsCache = (function () {
            function filterOperatorsCache(wijgrid) {
                this._cache = {};
                var self = this;

                this._wijgrid = wijgrid;

                this._addOperator(null, builtInFilterOperators.NoFilterOp);

                $.each(wijmo.data.filtering.ops, function (name, op) {
                    self._addOperator(name, op);
                });

                $.each(wijgrid.options.customFilterOperators, function (key, fop) {
                    self._addOperator(null, fop, true);
                });
            }
            filterOperatorsCache.prototype.getByName = function (name) {
                var fop = this.getByNameInt(name);

                return (fop) ? fop.op : null;
            };

            filterOperatorsCache.prototype.getByNameInt = function (name) {
                return this._cache[(name || "").toLowerCase()];
            };

            filterOperatorsCache.prototype.getByDataType = function (dataType) {
                var intResult = [], result;

                $.each(this._cache, function (key, val) {
                    var fop = val.op;

                    if (!fop.applicableTo || $.inArray(dataType, fop.applicableTo) >= 0) {
                        intResult.push(val);
                    }
                });

                switch (this._wijgrid.options.filterOperatorsSortMode.toLowerCase()) {
                    case "alphabetical":
                        intResult.sort(this._sortAlpha);
                        break;
                    case "alphabeticalcustomfirst":
                        intResult.sort(this._sortAlphaCustomFirst);
                        break;

                    case "alphabeticalembeddedFirst":
                        intResult.sort(this._sortAlphaEmbeddedFirst);
                        break;

                    case "none":
                        break;

                    default:
                        break;
                }

                result = $.map(intResult, function (val, key) {
                    return val.op;
                });

                return result;
            };

            filterOperatorsCache.prototype._addOperator = function (name, fop, isCustom) {
                if (typeof isCustom === "undefined") { isCustom = false; }
                if (name && !fop.name) {
                    fop.name = name;
                }

                name = (name || fop.name).toLowerCase();

                if (!this._cache[name]) {
                    this._cache[name] = {
                        op: fop,
                        isCustom: (isCustom === true)
                    };
                }
            };

            filterOperatorsCache.prototype._sortAlpha = function (a, b) {
                var n1 = a.op.name.toLowerCase(), n2 = b.op.name.toLowerCase();

                if (n1 !== n2) {
                    if (n1 === "nofilter") {
                        return -1;
                    }

                    if (n2 === "nofilter") {
                        return 1;
                    }
                }

                if (n1 === n2) {
                    return 0;
                }

                return (n1 < n2) ? -1 : 1;
            };

            filterOperatorsCache.prototype._sortAlphaEmbeddedFirst = function (a, b) {
                var n1 = a.op.name.toLowerCase(), n2 = b.op.name.toLowerCase();

                if (n1 !== n2) {
                    if (n1 === "nofilter") {
                        return -1;
                    }

                    if (n2 === "nofilter") {
                        return 1;
                    }
                }

                if (a.isCustom !== b.isCustom) {
                    if (a.isCustom) {
                        return 1;
                    }

                    if (b.isCustom) {
                        return -1;
                    }
                }

                if (n1 === n2) {
                    return 0;
                }

                return (n1 < n2) ? -1 : 1;
            };

            filterOperatorsCache.prototype._sortAlphaCustomFirst = function (a, b) {
                var n1 = a.op.name.toLowerCase(), n2 = b.op.name.toLowerCase();

                if (n1 !== n2) {
                    if (n1 === "nofilter") {
                        return -1;
                    }

                    if (n2 === "nofilter") {
                        return 1;
                    }
                }

                if (a.isCustom !== b.isCustom) {
                    if (a.isCustom) {
                        return -1;
                    }

                    if (b.isCustom) {
                        return 1;
                    }
                }

                if (n1 === n2) {
                    return 0;
                }

                return (n1 < n2) ? -1 : 1;
            };
            return filterOperatorsCache;
        })();
        grid.filterOperatorsCache = filterOperatorsCache;

        

        /** @ignore */
        var filterHelper = (function () {
            function filterHelper() {
            }
            // filterValue
            // [filterValue, ..., filterValue]
            // [[filterValue, ..., filterValue], ..., [filterValue, ..., filterValue]]
            filterHelper.getSingleValue = function (filterValue) {
                if ($.isArray(filterValue)) {
                    filterValue = filterValue[0];

                    if ($.isArray(filterValue)) {
                        filterValue = filterValue[0];
                    }
                }

                return filterValue;
            };

            // filterOperator -> name | { name, condition }
            // filterOperator -> filterOperator | [ filterOperator, ..., filterOperator]
            filterHelper.getSingleOperatorName = function (filterOperator) {
                if ($.isArray(filterOperator)) {
                    filterOperator = filterOperator[0];
                }

                return filterOperator.name || filterOperator || "";
            };

            // filterOperator: opName | [opName, ..., opName] | [ { name, condition }, ..., { name, condition } ]
            // filterValue: filterValue | [filterValue, ... , filterValue] | [[], ..., []]
            filterHelper.verify = function (filterOperator, filterValue, dataType, cache) {
                if (filterOperator) {
                    if ($.isArray(filterOperator)) {
                        var fop = [], fval = [];

                        if (!$.isArray(filterValue)) {
                            filterValue = [filterValue];
                        }

                        for (var i = 0, len = filterOperator.length; i < len; i++) {
                            if (wijmo.grid.filterHelper._verifySingleOp(filterOperator[i], filterValue[i], dataType, cache)) {
                                fop.push({
                                    name: filterOperator[i].name || filterOperator[i],
                                    condition: filterOperator[i].condition || "or"
                                });

                                fval.push(filterValue ? filterValue[i] : undefined);
                            }
                        }

                        if (fop.length) {
                            return {
                                operator: fop,
                                value: fval
                            };
                        }
                    } else {
                        if (wijmo.grid.filterHelper._verifySingleOp(filterOperator, filterValue, dataType, cache)) {
                            return {
                                operator: filterOperator,
                                value: filterValue
                            };
                        }
                    }
                }

                return null;
            };

            // filterOpeator: name | { name, condition }
            filterHelper._verifySingleOp = function (filterOperator, filterValue, dataType, cache) {
                if (filterOperator && (filterOperator = (filterOperator.name || filterOperator))) {
                    var fop;

                    filterOperator = (filterOperator || "").toLowerCase();

                    if ((filterOperator !== "nofilter" || filterValue !== undefined) && (fop = cache.getByName(filterOperator))) {
                        if (fop.applicableTo === null || $.inArray(dataType || "string", fop.applicableTo) >= 0) {
                            if (fop.arity === 1 || (fop.arity > 1 && wijmo.grid.filterHelper.getSingleValue(filterValue) !== undefined)) {
                                return true;
                            }
                        }
                    }
                }

                return false;
            };
            filterHelper.marker = "_wijgrid";
            return filterHelper;
        })();
        grid.filterHelper = filterHelper;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="interfaces.ts"/>
/// <reference path="misc.ts"/>
var wijmo;
(function (wijmo) {
    (function (grid) {
        var $ = jQuery;

        

        

        /** @ignore */
        function getTableSection(table, scope) {
            if (table && !table.nodeType) {
                table = table[0];
            }

            if (table) {
                switch (scope) {
                    case 1 /* head */:
                        return table.tHead;

                    case 2 /* body */:
                        if (table.tBodies) {
                            return table.tBodies[0] || null;
                        }
                        break;

                    case 3 /* foot */:
                        return table.tFoot;

                    default:
                        return table;
                }
            }

            return null;
        }
        grid.getTableSection = getTableSection;

        

        

        /** @ignore */
        function getTableSectionLength(table, scope) {
            var section;

            if (table && !table.nodeType) {
                table = table[0]; // jQuery
            }

            return (table && (section = this.getTableSection(table, scope))) ? section.rows.length : 0;
        }
        grid.getTableSectionLength = getTableSectionLength;

        

        

        /** @ignore */
        function getTableSectionRow(table, scope, rowIndex) {
            var section;

            if (table && !table.nodeType) {
                table = table[0]; // jQuery
            }

            return (table && (section = this.getTableSection(table, scope))) ? (section.rows[rowIndex] || null) : null;
        }
        grid.getTableSectionRow = getTableSectionRow;

        

        

        /** @ignore */
        function readTableSection(table, scope, decodeHTML, trim, readAttributes) {
            var result = [], prevent = function (attrName) {
                attrName = attrName.toLowerCase();
                return attrName === "rowspan" || attrName === "colspan";
            }, section;

            if (table && !table.nodeType) {
                table = table[0]; // jQuery
            }

            if (table && (section = this.getTableSection(table, scope))) {
                for (var i = 0, len = section.rows.length; i < len; i++) {
                    var domRow = section.rows[i], row = [], rowAttributes;

                    if (readAttributes) {
                        var expando = wijmo.data.Expando.getFrom(row, true);

                        rowAttributes = expando[wijmo.grid.EXPANDO] = {
                            cellsAttributes: {},
                            rowAttributes: wijmo.grid.getAttributes(domRow) || {}
                        };
                    }

                    for (var j = 0, len2 = domRow.cells.length; j < len2; j++) {
                        var value = wijmo.grid.getContent(domRow.cells[j], decodeHTML, trim);

                        row[j] = value;

                        if (readAttributes) {
                            rowAttributes.cellsAttributes[j] = wijmo.grid.getAttributes(domRow.cells[j], prevent) || {};
                        }
                    }

                    result[i] = row;
                }
            }

            return result;
        }
        grid.readTableSection = readTableSection;

        /** @ignore */
        function determineSection(cell) {
            var element = cell.parentNode.parentNode;

            switch (element.tagName.toLowerCase()) {
                case "thead":
                    return 1 /* head */;

                case "tbody":
                    return 2 /* body */;

                case "tfoot":
                    return 3 /* foot */;
            }

            return null;
        }
        grid.determineSection = determineSection;

        /** @ignore */
        var htmlTableAccessor = (function () {
            function htmlTableAccessor(domTable, skipOffsets, ensureTBody, ensureColgroup) {
                this._width = 0;
                this._table = domTable;
                this._offsets = [];

                if (ensureColgroup) {
                    this.ensureColGroup();
                }

                if (ensureTBody) {
                    this.ensureTBody();
                }

                if (!skipOffsets) {
                    this._buildOffsets();
                }
            }
            htmlTableAccessor.prototype.element = function () {
                return this._table;
            };

            htmlTableAccessor.prototype.width = function () {
                return this._width;
            };

            htmlTableAccessor.prototype.getCellIdx = function (colIdx, rowIdx) {
                return (colIdx < this._width && rowIdx >= 0 && rowIdx < this._offsets.length) ? this._offsets[rowIdx][colIdx].cellIdx : -1;
            };

            htmlTableAccessor.prototype.getColumnIdx = function (cellIdx, rowIdx) {
                if (typeof (cellIdx) !== "number") {
                    var domCell = cellIdx;

                    cellIdx = domCell.cellIndex;
                    rowIdx = domCell.parentNode.rowIndex;
                }

                return (cellIdx < this._width) ? this._offsets[rowIdx][cellIdx].colIdx : -1;
            };

            htmlTableAccessor.prototype.clearContent = function () {
                if (this._table) {
                    while (this._table.firstChild) {
                        this._table.removeChild(this._table.firstChild);
                    }

                    this.ensureColGroup();
                    this.ensureTBody();
                }
            };

            htmlTableAccessor.prototype.clearSection = function (scope) {
                var start, end, section = wijmo.grid.getTableSection(this._table, scope);

                switch (scope) {
                    case 2 /* body */:
                        start = this.getSectionLength(0 /* table */);
                        end = start + this.getSectionLength(scope) - 1;
                        break;

                    case 3 /* foot */:
                        start = this.getSectionLength(0 /* table */) + this.getSectionLength(1 /* head */);
                        end = start + this.getSectionLength(scope) - 1;
                        break;

                    default:
                        start = 0;
                        end = this.getSectionLength(scope) - 1;
                }

                while (section.rows.length) {
                    $(section.rows[0]).remove();
                }

                // update offsets
                this._offsets.splice(start, end - start + 1);
            };

            htmlTableAccessor.prototype.getSectionLength = function (scope) {
                return wijmo.grid.getTableSectionLength(this._table, scope);
            };

            htmlTableAccessor.prototype.getSectionRow = function (rowIndex, scope) {
                return wijmo.grid.getTableSectionRow(this._table, scope, rowIndex);
            };

            // iterates through the table rows using natural cells order
            htmlTableAccessor.prototype.forEachColumnCellNatural = function (columnIdx, callback, param) {
                for (var i = 0, len = this._table.rows.length; i < len; i++) {
                    var row = this._table.rows[i];

                    if (columnIdx < row.cells.length) {
                        var result = callback(row.cells[columnIdx], i, param);

                        if (result !== true) {
                            return result;
                        }
                    }
                }

                return true;
            };

            // iterates through the table rows using colSpan\rowSpan offsets
            htmlTableAccessor.prototype.forEachColumnCell = function (columnIdx, callback, param) {
                for (var i = 0, len = this._offsets.length; i < len; i++) {
                    var row = this._table.rows[i], offsetCellIdx = this.getCellIdx(columnIdx, i);

                    if (offsetCellIdx >= 0) {
                        var result = callback(row.cells[offsetCellIdx], i, param);

                        if (result !== true) {
                            return result;
                        }
                    }
                }

                return true;
            };

            // iterates throw the cells of a table row
            htmlTableAccessor.prototype.forEachRowCell = function (rowIndex, callback, param) {
                var row = this._table.rows[rowIndex];

                for (var i = 0, len = row.cells.length; i < len; i++) {
                    var result = callback(row.cells[i], i, param);

                    if (result !== true) {
                        return result;
                    }
                }

                return true;
            };

            htmlTableAccessor.prototype.colGroupTag = function () {
                var cgs = this._table.getElementsByTagName("colgroup");
                return (cgs && cgs[0]) || null;
            };

            htmlTableAccessor.prototype.colTags = function () {
                var colGroup = this.colGroupTag();
                return ((colGroup && colGroup.getElementsByTagName("col")) || []);
            };

            htmlTableAccessor.prototype.ensureTBody = function () {
                return ((this._table.tBodies && this._table.tBodies[0]) || this._table.appendChild(document.createElement("tbody")));
            };

            htmlTableAccessor.prototype.ensureTHead = function () {
                return (this._table.tHead && this._table.tHead[0]) || this._table.createTHead();
            };

            htmlTableAccessor.prototype.ensureTFoot = function () {
                return (this._table.tFoot && this._table.tFoot[0]) || this._table.createTFoot();
            };

            htmlTableAccessor.prototype.ensureColGroup = function () {
                var colGroup = this._table.getElementsByTagName("colgroup");
                return ((colGroup && colGroup[0]) || this._table.appendChild(document.createElement("colgroup")));
            };

            htmlTableAccessor.prototype.appendCol = function (domCol /*opt*/ ) {
                var colGroup = this.ensureColGroup();
                return ((domCol && colGroup.appendChild(domCol)) || colGroup.appendChild(document.createElement("col")));
            };

            htmlTableAccessor.prototype.removeOffset = function (idx) {
                if (idx >= 0 && idx < this._offsets.length) {
                    if (idx < 0 || (!idx && idx !== 0)) {
                        idx = this._offsets.length - 1; // last row
                    }

                    this._offsets.splice(idx, 1);
                }
            };

            htmlTableAccessor.prototype.insertOffset = function (idx) {
                var row, i;

                if (this._width > 0) {
                    row = [];

                    for (i = 0; i < this._width; i++) {
                        row.push({ cellIdx: i, colIdx: i });
                    }

                    if (idx < 0 || (!idx && idx !== 0)) {
                        idx = this._offsets.length; // append row
                    }

                    this._offsets.splice(idx, 0, row);
                }
            };

            htmlTableAccessor.prototype.rebuildOffsets = function () {
                this._offsets = [];
                this._width = 0;
                this._buildOffsets();
            };

            htmlTableAccessor.prototype._buildOffsets = function () {
                var rowSpan = [];

                for (var i = 0, len = this._table.rows.length; i < len; i++) {
                    var rowOffsets = [], jOffset = 0, row = this._table.rows[i];

                    this._offsets[i] = rowOffsets;

                    for (var j = 0, len2 = row.cells.length; j < len2; j++, jOffset++) {
                        var cell = row.cells[j];

                        for (; rowSpan[jOffset] > 1; jOffset++) {
                            rowSpan[jOffset]--;
                            rowOffsets[jOffset] = { cellIdx: -1, colIdx: -1 };
                        }

                        if (!(rowSpan[jOffset] > 1)) {
                            rowSpan[jOffset] = cell.rowSpan;
                        }

                        rowOffsets[jOffset] = { cellIdx: j, colIdx: -1 };
                        rowOffsets[j].colIdx = jOffset;

                        // process colspan
                        var cs = cell.colSpan;
                        for (; cs > 1; cs--) {
                            rowOffsets[++jOffset] = { cellIdx: -1, colIdx: -1 };
                        }
                    }

                    var rowSpanLen = rowSpan.length;
                    for (; jOffset < rowSpanLen; jOffset++) {
                        rowSpan[jOffset]--;
                        rowOffsets[jOffset] = { cellIdx: -1, colIdx: -1 };
                    }

                    this._width = Math.max(this._width, rowSpanLen);
                }
            };
            return htmlTableAccessor;
        })();
        grid.htmlTableAccessor = htmlTableAccessor;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="interfaces.ts" />
/// <reference path="wijgrid.ts" />
/// <reference path="misc.ts" />
var wijmo;
(function (wijmo) {
    (function (_grid) {
        var $ = jQuery;

        /** An object that represents a single cell. */
        var cellInfo = (function () {
            /** Creates an object that represents a single cell. Normally you do not need to use this method.
            * @example
            * var cell = new wijmo.grid.cellInfo(0, 0, $("#demo").data("wijmo-wijgrid"));
            * @param {Number} cellIndex The zero-based index of the required cell inside the corresponding row.
            * @param {Number} rowIndex The zero-based index of the row that contains required cell.
            * @param {Object} wijgrid The wijgrid instance.
            * @returns {wijmo.grid.cellInfo} Object that represents a single cell.
            */
            function cellInfo(cellIndex, rowIndex, wijgrid, absolute, virtualize) {
                if (typeof wijgrid === "undefined") { wijgrid = null; }
                if (typeof absolute === "undefined") { absolute = false; }
                if (typeof virtualize === "undefined") { virtualize = true; }
                this.mIsPreparingForEditing = false;
                this.mIsEdit = false;
                this._wijgrid = wijgrid;
                this._virtualize = virtualize;

                if (absolute) {
                    this._ci = cellIndex - this._wijgrid._getDataToAbsOffset().x;
                    this._ri = rowIndex - this._wijgrid._getDataToAbsOffset().y;

                    if (this._virtualize) {
                        if (this._ci >= 0) {
                            this._ci = this._wijgrid._renderedLeaves()[this._ci].options._visLeavesIdx;
                        }

                        if (this._ri >= 0) {
                            this._ri = this._wijgrid._renderableRowsRange().getAbsIndex(this._ri + this._wijgrid._viewPortBounds().start);
                        }
                    }
                } else {
                    this._ci = cellIndex;
                    this._ri = rowIndex;
                }
            }
            // public
            /** @ignore */
            cellInfo.prototype.cellIndexAbs = function () {
                var dataOffset = this._wijgrid._getDataToAbsOffset().x;

                var value = this._virtualize ? this._wijgrid._visibleLeaves()[this._ci + dataOffset].options._renderedIndex : this._ci + dataOffset;

                return value;
            };

            /** @ignore */
            cellInfo.prototype.rowIndexAbs = function () {
                var value = this._virtualize ? this._wijgrid._renderableRowsRange().getRenderedIndex(this._ri) - this._wijgrid._viewPortBounds().start : this._ri;

                value += this._wijgrid._getDataToAbsOffset().y;

                return value;
            };

            /** @ignore */
            cellInfo.prototype.cellIndex = function (value) {
                if (!arguments.length) {
                    return this._ci;
                }

                this._ci = value;
            };

            /** Gets the associated column object.
            * @example
            * var column = cellInfoObj.column();
            * @returns {wijmo.grid.IColumn} The associated column object.
            */
            cellInfo.prototype.column = function () {
                var instance = this.columnInst();

                return instance ? instance.options : null;
            };

            /** @ignore */
            cellInfo.prototype.columnInst = function () {
                if (this._wijgrid && this._isValid()) {
                    var dataOffset = this._wijgrid._getDataToAbsOffset();
                    return this._wijgrid._visibleLeaves()[this.cellIndex() + dataOffset.x];
                }

                return null;
            };

            /** Returns the jQuery object containing a cell content.
            * @example
            * var $container = cellInfoObj.container();
            * @returns {Object} The jQuery object containing a cell content.
            */
            cellInfo.prototype.container = function () {
                var tableCell = this.tableCell(), $innerDiv;

                if (tableCell) {
                    $innerDiv = $(tableCell).children("div." + wijmo.grid.wijgrid.CSS.cellContainer);
                    if ($innerDiv) {
                        return $innerDiv;
                    }
                }

                return null;
            };

            /** Compares the current object with an object you have specified and indicates whether they are identical
            * @example
            * var isEqual = cellInfoObj1.isEqual(cellInfoObj2);
            * @param {wijmo.grid.cellInfo} value The object to compare
            * @returns {Boolean} True if the objects are identical, otherwise false.
            */
            cellInfo.prototype.isEqual = function (value) {
                return (value && (value.rowIndex() === this.rowIndex()) && (value.cellIndex() === this.cellIndex()));
            };

            /** Gets the accociated row's information.
            * @example
            * var row = cellInfoObj.row();
            * @returns {wijmo.grid.IRowInfo} Information about associated row.
            */
            cellInfo.prototype.row = function () {
                var rowObj = null, result = null;

                if (this._wijgrid) {
                    if (this._virtualize) {
                        result = this._wijgrid._view()._getRowInfoBySketchRowIndex(this.rowIndex());
                    } else {
                        rowObj = this._wijgrid._view().rows().item(this.rowIndexAbs());

                        if (rowObj && rowObj.length) {
                            result = this._wijgrid._view()._getRowInfo(rowObj);
                        }
                    }
                }

                return result;
            };

            /** @ignore */
            cellInfo.prototype.rowIndex = function (value) {
                if (!arguments.length) {
                    return this._ri;
                }

                this._ri = value;
            };

            /** Returns the table cell element corresponding to this object.
            * @example
            * var domCell = cellInfoObj.tableCell();
            * @returns {HTMLTableCellElement} The table cell element corresponding to this object.
            */
            cellInfo.prototype.tableCell = function () {
                if (this._wijgrid && this._isValid()) {
                    if (!this._virtualize || this._isRendered()) {
                        return this._wijgrid._view().getCell(this.cellIndexAbs(), this.rowIndexAbs());
                    }
                }

                return null;
            };

            /** @ignore */
            cellInfo.prototype.value = function (value /*opt*/ ) {
                var column, rowInfo, colVal;

                if (this._wijgrid && this._isValid()) {
                    rowInfo = this.row();

                    if (rowInfo.type & 2 /* data */) {
                        column = this.column();

                        if (arguments.length === 0) {
                            colVal = this._wijgrid.mDataViewWrapper.getValue(rowInfo.data, column.dataKey);
                            return this._wijgrid.parse(column, colVal);
                        } else {
                            // validation
                            value = this._wijgrid.parse(column, value);

                            if ((value === null && column.valueRequired) || ((wijmo.grid.getDataType(column) !== "string") && _grid.isNaN(value))) {
                                throw "invalid value";
                            }

                            // update dataView
                            this._wijgrid.mDataViewWrapper.setValue(rowInfo.dataItemIndex, column.dataKey, value);

                            // keep sketchTable values in sync (to avoid issues during virtual scrolling)
                            var sketchRow = this._sketchRow();
                            if (sketchRow) {
                                var sketchCell = sketchRow.cell(column._leavesIdx);
                                sketchCell.value = value;
                            }
                        }
                    }
                }
            };

            /** @ignore */
            cellInfo.prototype.toString = function () {
                return this.cellIndex() + ":" + this.rowIndex();
            };

            // internal
            cellInfo.prototype._clip = function (range, absolute) {
                if (typeof absolute === "undefined") { absolute = false; }
                var flag = false, val;

                if (absolute) {
                    if (this.cellIndexAbs() < (val = range.topLeft().cellIndexAbs())) {
                        flag = true;
                        this._ci = range.topLeft().cellIndex();
                    }

                    if (this.cellIndexAbs() > (val = range.bottomRight().cellIndexAbs())) {
                        flag = true;
                        this._ci = range.bottomRight().cellIndex();
                    }

                    if (this.rowIndexAbs() < (val = range.topLeft().rowIndexAbs())) {
                        flag = true;
                        this._ri = range.topLeft().rowIndex();
                    }

                    if (this.rowIndexAbs() > (val = range.bottomRight().rowIndexAbs())) {
                        flag = true;
                        this._ri = range.bottomRight().rowIndex();
                    }
                } else {
                    if (this.cellIndex() < (val = range.topLeft().cellIndex())) {
                        flag = true;
                        this._ci = val;
                    }

                    if (this.cellIndex() > (val = range.bottomRight().cellIndex())) {
                        flag = true;
                        this._ci = val;
                    }

                    if (this.rowIndex() < (val = range.topLeft().rowIndex())) {
                        flag = true;
                        this._ri = val;
                    }

                    if (this.rowIndex() > (val = range.bottomRight().rowIndex())) {
                        flag = true;
                        this._ri = val;
                    }
                }

                return flag;
            };

            cellInfo.prototype._clone = function () {
                return new wijmo.grid.cellInfo(this.cellIndex(), this.rowIndex(), this._wijgrid, false, this._virtualize);
            };

            cellInfo.prototype._isValid = function () {
                return this.cellIndex() >= 0 && this.rowIndex() >= 0;
            };

            cellInfo.prototype._isRowRendered = function () {
                var view;

                if (this._wijgrid && (view = this._wijgrid._view()) && this._isValid()) {
                    var bodyIndex = view._isRowRendered(this.rowIndex());
                    return (bodyIndex >= 0);
                }

                return false;
            };

            cellInfo.prototype._isRendered = function () {
                var view;

                if (this._wijgrid && (view = this._wijgrid._view()) && this._isValid()) {
                    if (this.columnInst()._isRendered()) {
                        var bodyIndex = view._isRowRendered(this.rowIndex());
                        return (bodyIndex >= 0);
                    }
                }

                return false;
            };

            cellInfo.prototype._isPreparingForEditing = function (value) {
                if (arguments.length) {
                    this.mIsPreparingForEditing = value;
                }

                return this.mIsPreparingForEditing;
            };

            cellInfo.prototype._isEdit = function (value) {
                var tableCell = null, marker = wijmo.grid.wijgrid.CSS.editedCellMarker;

                if (this._isValid()) {
                    try  {
                        tableCell = this.tableCell();
                    } catch (e) {
                    }
                }

                if (!arguments.length) {
                    if (tableCell) {
                        return $(tableCell).hasClass(marker);
                    }

                    return this.mIsEdit;
                } else {
                    if (tableCell) {
                        $(tableCell)[value ? "addClass" : "removeClass"](marker);
                    }

                    var grid = this._wijgrid;

                    // add or remove the row header's icon
                    if (grid && this._wijgrid._showRowHeader() && this._isRowRendered()) {
                        var row = this.row(), container = $(row.$rows[0].cells[0]).children("div." + wijmo.grid.wijgrid.CSS.cellContainer);

                        if (value) {
                            container.empty().append($("<div>&nbsp;</div>").addClass(grid.options.wijCSS.icon + " " + grid.options.wijCSS.iconPencil));
                        } else {
                            container.html("&nbsp;"); // remove icon-pencil
                        }
                    }

                    this.mIsEdit = value;
                }
            };

            cellInfo.prototype._setGridView = function (value) {
                this._wijgrid = value;
            };

            // gets associated row from the sketchTable
            cellInfo.prototype._sketchRow = function () {
                var grid = this._wijgrid, row = this.row();

                if (grid && row && (row.sketchRowIndex >= 0)) {
                    return grid.mSketchTable.row(row.sketchRowIndex);
                }

                return null;
            };
            cellInfo.outsideValue = new cellInfo(-1, -1, null);
            return cellInfo;
        })();
        _grid.cellInfo = cellInfo;

        /** An object that specifies a range of cells determined by two cells. */
        var cellInfoRange = (function () {
            /** Creates an object that specifies a range of cells determined by two cells. Normally you do not need to use this method.
            * @example
            * var range = wijmo.grid.cellInfoRange(new wijmo.grid.cellInfo(0, 0), new wijmo.grid.cellInfo(0, 0));
            * @param {wijmo.grid.cellInfo} topLeft Object that represents the top left cell of the range.
            * @param {wijmo.grid.cellInfo} bottomRight Object that represents the bottom right cell of the range.
            * @returns {wijmo.grid.cellInfoRange} Object that specifies a range of cells determined by two cells.
            */
            function cellInfoRange(topLeft, bottomRight) {
                if (!topLeft || !bottomRight) {
                    throw "invalid arguments";
                }

                this._topLeft = topLeft._clone();
                this._bottomRight = bottomRight._clone();
            }
            /** Gets the object that represents the bottom right cell of the range.
            * @example
            * var cellInfoObj = range.bottomRight();
            * @returns {wijmo.grid.cellInfo} The object that represents the bottom right cell of the range.
            */
            cellInfoRange.prototype.bottomRight = function () {
                return this._bottomRight;
            };

            /** Compares the current range with a specified range and indicates whether they are identical.
            * @example
            * var isEqual = range1.isEqual(range2);
            * @param {wijmo.grid.cellInfoRange} range Range to compare.
            * @returns True if the ranges are identical, otherwise false.
            */
            cellInfoRange.prototype.isEqual = function (range) {
                return (range && this._topLeft.isEqual(range.topLeft()) && this._bottomRight.isEqual(range.bottomRight()));
            };

            /** Gets the object that represents the top left cell of the range.
            * @example
            * var cellInfoObj = range.topLeft();
            * @returns {wijmo.grid.cellInfo} The object that represents the top left cell of the range.
            */
            cellInfoRange.prototype.topLeft = function () {
                return this._topLeft;
            };

            /** @ignore */
            cellInfoRange.prototype.toString = function () {
                return this._topLeft.toString() + " - " + this._bottomRight.toString();
            };

            // public *
            // internal
            cellInfoRange.prototype._isIntersect = function (range) {
                var rangeH, thisH, rangeW, thisW;

                if (range) {
                    rangeH = range.bottomRight().rowIndex() - range.topLeft().rowIndex() + 1;
                    thisH = this._bottomRight.rowIndex() - this._topLeft.rowIndex() + 1;

                    if ((range.topLeft().rowIndex() + rangeH) - this._topLeft.rowIndex() < rangeH + thisH) {
                        rangeW = range.bottomRight().cellIndex() - range.topLeft().cellIndex() + 1;
                        thisW = this._bottomRight.cellIndex() - this._topLeft.cellIndex() + 1;

                        return ((range.topLeft().cellIndex() + rangeW) - this._topLeft.cellIndex() < rangeW + thisW);
                    }
                }

                return false;
            };

            cellInfoRange.prototype._isValid = function () {
                return this._topLeft._isValid() && this._bottomRight._isValid();
            };

            cellInfoRange.prototype._clip = function (clipBy, absolute) {
                if (typeof absolute === "undefined") { absolute = false; }
                var a = this._topLeft._clip(clipBy, absolute);
                var b = this._bottomRight._clip(clipBy, absolute);

                return a || b;
            };

            cellInfoRange.prototype._clone = function () {
                return new cellInfoRange(this._topLeft._clone(), this._bottomRight._clone());
            };

            cellInfoRange.prototype._containsCellInfo = function (info) {
                return (info && info.cellIndex() >= this._topLeft.cellIndex() && info.cellIndex() <= this._bottomRight.cellIndex() && info.rowIndex() >= this._topLeft.rowIndex() && info.rowIndex() <= this._bottomRight.rowIndex());
            };

            cellInfoRange.prototype._containsCellRange = function (range) {
                return (range && this._containsCellInfo(range.topLeft()) && this._containsCellInfo(range.bottomRight()));
            };

            cellInfoRange.prototype._extend = function (mode, borders) {
                if (mode === 1 /* column */) {
                    this._topLeft.rowIndex(borders.topLeft().rowIndex());
                    this._bottomRight.rowIndex(borders.bottomRight().rowIndex());
                } else {
                    if (mode === 2 /* row */) {
                        this._topLeft.cellIndex(borders.topLeft().cellIndex());
                        this._bottomRight.cellIndex(borders.bottomRight().cellIndex());
                    }
                }

                return this;
            };

            cellInfoRange.prototype._normalize = function () {
                var x0 = this._topLeft.cellIndex(), y0 = this._topLeft.rowIndex(), x1 = this._bottomRight.cellIndex(), y1 = this._bottomRight.rowIndex();

                this._topLeft.cellIndex(Math.min(x0, x1));
                this._topLeft.rowIndex(Math.min(y0, y1));

                this._bottomRight.cellIndex(Math.max(x0, x1));
                this._bottomRight.rowIndex(Math.max(y0, y1));
            };

            cellInfoRange.prototype._height = function () {
                return this._bottomRight.rowIndex() - this._topLeft.rowIndex();
            };

            cellInfoRange.prototype._width = function () {
                return this._bottomRight.cellIndex() - this._topLeft.cellIndex();
            };
            return cellInfoRange;
        })();
        _grid.cellInfoRange = cellInfoRange;

        // * compatibility: export members to the $.wijmo.wijgrid "namespace" *
        $.extend($.wijmo.wijgrid, {
            cellInfo: wijmo.grid.cellInfo,
            cellInfoRange: wijmo.grid.cellInfoRange
        });
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="interfaces.ts" />
/// <reference path="wijgrid.ts" />
/// <reference path="misc.ts" />
/// <reference path="rowAccessor.ts" />
/// <reference path="filterOperators.ts" />
/// <reference path="htmlTableAccessor.ts" />
var wijmo;
(function (wijmo) {
    (function (grid) {
        var $ = jQuery;

        /** @ignore */
        var baseView = (function () {
            function baseView(wijgrid, renderBounds) {
                this.mIsRendered = false;
                this.mIsLiveUpdate = false;
                this.mDetailsToInstantiate = [];
                this._sizesAdjCache = {
                    th: 0,
                    col: 0,
                    subTable: 0
                };
                if (!wijgrid) {
                    throw "'wijgrid' must be specified";
                }

                this._wijgrid = wijgrid;
                this._bounds = renderBounds;

                this._wijgrid.element.addClass(wijmo.grid.wijgrid.CSS.table).addClass(this._wijgrid.options.wijCSS.wijgridTable);
            }
            baseView.prototype.dispose = function () {
                this.toggleDOMSelection(true);
                this._wijgrid.element.removeClass(wijmo.grid.wijgrid.CSS.table).removeClass(this._wijgrid.options.wijCSS.wijgridTable);
            };

            baseView.prototype.currentRenderableColumns = function (value) {
                if (arguments.length) {
                    this.mCurrentRenderableColumns = value;
                }

                return this.mCurrentRenderableColumns;
            };

            baseView.prototype.ensureDisabledState = function () {
                var disabledClass = "wijmo-wijgrid" + "-disabled " + this._wijgrid.options.wijCSS.stateDisabled, disabled = this._wijgrid.options.disabled, self = this;

                $.each(this.subTables(), function (key, table) {
                    if (table) {
                        var $table = $(table.element());

                        if (disabled) {
                            $table.addClass(disabledClass);
                            self._wijgrid._setAttr($table, "aria-disabled", true);
                        } else {
                            $table.removeClass(disabledClass);
                            self._wijgrid._setAttr($table, "aria-disabled", false);
                        }
                    }
                });
            };

            //ensureWidth(index: number, value, oldValue) {
            //	this._setColumnWidth(index, value);
            //}
            baseView.prototype.ensureHeight = function (rowIndex) {
            };

            baseView.prototype.getScrollValue = function () {
                return null;
            };

            baseView.prototype.getVisibleAreaBounds = function (client) {
                throw "not implemented";
            };

            baseView.prototype.getVisibleContentAreaBounds = function () {
                throw "not implemented";
            };

            baseView.prototype.getFixedAreaVisibleBounds = function () {
                throw "not implemented";
            };

            baseView.prototype.isLiveUpdate = function () {
                return this.mIsLiveUpdate;
            };

            baseView.prototype.isRendered = function () {
                return this.mIsRendered;
            };

            baseView.prototype.render = function (live) {
                this.mIsLiveUpdate = live;

                if (!live) {
                    this._provideRealColumnsWidth();
                }

                this._ensureRenderBounds();
                this._ensureRenderHBounds();

                this._preRender();

                this._renderContent();

                this._postRender();

                this.mIsLiveUpdate = false;

                this._ensureRenderHBounds(); // reset after mIsLiveUpdate is changed
            };

            baseView.prototype.toggleDOMSelection = function (enable) {
                $.each(this.subTables(), function (index, table) {
                    (new wijmo.grid.domSelection(table.element())).toggleSelection(enable);
                });

                (new wijmo.grid.domSelection(this._wijgrid.mOuterDiv)).toggleSelection(enable);
            };

            baseView.prototype.updateSplits = function (scrollValue, rowsToAdjust) {
                throw "not implemented";
            };

            baseView.prototype.updateSplitsLive = function () {
                throw "not implemented";
            };

            baseView.prototype.getInlineTotalWidth = function () {
                throw "not implemented";
            };

            // public **
            // ** DOMTable abstraction
            // ** rows accessors
            baseView.prototype.bodyRows = function () {
                if (!this._bodyRowsAccessor) {
                    if (!this.isRendered()) {
                        throw "not rendered yet";
                    }

                    this._bodyRowsAccessor = new wijmo.grid.rowAccessor(this, 2 /* body */, 0, 0);
                }

                return this._bodyRowsAccessor;
            };

            baseView.prototype.filterRow = function () {
                if (this._wijgrid.options.showFilter) {
                    if (!this.isRendered()) {
                        throw "not rendered yet";
                    }

                    var accessor = new wijmo.grid.rowAccessor(this, 1 /* head */, 0, 0);
                    return accessor.item(accessor.length() - 1);
                }

                return null;
            };

            baseView.prototype.footerRow = function () {
                if (this._wijgrid.options.showFooter) {
                    if (!this.isRendered()) {
                        throw "not rendered yet";
                    }

                    var accessor = new wijmo.grid.rowAccessor(this, 3 /* foot */, 0, 0);
                    return accessor.item(0);
                }
            };

            baseView.prototype.headerRows = function () {
                var bottomOffset;

                if (!this._headerRowsAccessor) {
                    if (!this.isRendered()) {
                        throw "not rendered yet";
                    }

                    bottomOffset = this._wijgrid.options.showFilter ? 1 : 0;
                    this._headerRowsAccessor = new wijmo.grid.rowAccessor(this, 1 /* head */, 0, bottomOffset);
                }

                return this._headerRowsAccessor;
            };

            baseView.prototype.rows = function () {
                if (!this._rowsAccessor) {
                    if (!this.isRendered()) {
                        throw "not rendered yet";
                    }

                    this._rowsAccessor = new wijmo.grid.rowAccessor(this, 0 /* table */, 0, 0);
                }

                return this._rowsAccessor;
            };

            // rows accessors **
            baseView.prototype.focusableElement = function () {
                return this._wijgrid.mOuterDiv;
            };

            baseView.prototype.forEachColumnCell = function (columnIndex, callback, param) {
                throw "not implemented";
            };

            baseView.prototype.forEachRowCell = function (rowIndex, callback, param) {
                throw "not implemented";
            };

            // important: only body cells can be virtualized
            baseView.prototype.getAbsoluteCellInfo = function (domCell, virtualize) {
                throw "not implemented";
            };

            baseView.prototype.getAbsoluteCellIndex = function (domCell) {
                throw "not implemented";
            };

            baseView.prototype.getAbsoluteRowIndex = function (domRow) {
                throw "not implemented";
            };

            baseView.prototype.getCell = function (absColIdx, absRowIdx) {
                throw "not implemented";
            };

            baseView.prototype.getColumnIndex = function (domCell) {
                throw "not implemented";
            };

            baseView.prototype.getHeaderCell = function (absColIdx) {
                throw "not implemented";
            };

            // [col, col]
            baseView.prototype.getJoinedCols = function (columnIndex) {
                throw "not implemented";
            };

            // [row, row]
            baseView.prototype.getJoinedRows = function (rowIndex, rowScope) {
                throw "not implemented";
            };

            // [table, table, offset:number]
            baseView.prototype.getJoinedTables = function (byColumn, index) {
                throw "not implemented";
            };

            baseView.prototype.subTables = function () {
                throw "not implemented";
            };

            // DOMTable abstraction **
            // ** private abstract
            baseView.prototype._getMappedScrollMode = function () {
                var scrollMode = this._wijgrid._lgGetScrollMode(), vScrollBarVisibility = "auto", hScrollBarVisibility = "auto";

                switch (scrollMode) {
                    case "horizontal":
                        vScrollBarVisibility = "hidden";
                        hScrollBarVisibility = "visible";
                        break;

                    case "vertical":
                        vScrollBarVisibility = "visible";
                        hScrollBarVisibility = "hidden";
                        break;

                    case "both":
                        vScrollBarVisibility = "visible";
                        hScrollBarVisibility = "visible";
                        break;
                }

                return { vScrollBarVisibility: vScrollBarVisibility, hScrollBarVisibility: hScrollBarVisibility };
            };

            // ** rendering
            baseView.prototype._postRender = function () {
                this.mIsRendered = true;

                if (this.isLiveUpdate()) {
                    this.updateSplitsLive();
                    return;
                }

                this.ensureDisabledState();

                // ** cache some values to speedup sizes manipulation (using IE especially) **
                // reset
                this._sizesAdjCache.col = 0;
                this._sizesAdjCache.th = 0;
                this._sizesAdjCache.subTable = 0;

                // set a new values
                var leaves = this._wijgrid._visibleLeaves();
                if (leaves.length > 0) {
                    // note: we assume that the margins, paddings and borders are common to all of the th\ col elements.
                    var th = this.getHeaderCell(0), cols = this.getJoinedCols(0);

                    if (th) {
                        this._sizesAdjCache.th = $(th).leftBorderWidth() + $(th).rightBorderWidth();
                    }

                    if (cols && cols.length) {
                        this._sizesAdjCache.col = $(cols[0]).leftBorderWidth() + $(cols[0]).rightBorderWidth();
                    }
                }

                var subTable = this.subTables()[0];
                this._sizesAdjCache.subTable = $(subTable.element()).leftBorderWidth() + $(subTable.element()).rightBorderWidth();
            };

            baseView.prototype._preRender = function () {
                this.mIsRendered = false;

                var renderedIndex = 0, leaves = this._wijgrid._renderedLeaves();

                // re-calculate rendered indicies
                $.each(this._wijgrid._leaves(), function (i, column) {
                    if (column._isRendered()) {
                        column.options._renderedIndex = renderedIndex++;
                        leaves.push(column);
                    } else {
                        column.options._renderedIndex = -1;
                    }
                });
            };

            baseView.prototype._addDetailInstantiator = function (value) {
                this.mDetailsToInstantiate.push(value);
            };

            baseView.prototype._ensureRenderBounds = function () {
                var dataRange = this._wijgrid._getDataCellsRange(0 /* sketch */);

                // render all items of the sketchTable
                this._bounds.start = 0;
                this._bounds.end = dataRange.bottomRight().rowIndex();
            };

            baseView.prototype._ensureRenderHBounds = function () {
                // render all columns
                var renderableColumns = this._wijgrid._renderableColumnsRange();

                renderableColumns.clear();
                renderableColumns.add(0, this._wijgrid._leaves().length - 1);

                this.currentRenderableColumns(renderableColumns);
            };

            baseView.prototype._provideRealColumnsWidth = function () {
                var _this = this;
                var leaves = this._wijgrid._visibleLeaves(), outerDiv = this._wijgrid.mOuterDiv, hvScrolling = this._wijgrid._allowHVirtualScrolling();

                $.each(leaves, function (index, column) {
                    var width = column.options.width;

                    if (!width && (width !== 0) && hvScrolling) {
                        width = _this._wijgrid.options.scrollingSettings.virtualizationSettings.columnWidth;
                    }

                    if (width || (width === 0)) {
                        width = wijmo.grid.isPercentage(width) ? outerDiv.width() * parseFloat(width) / 100 : parseFloat(width);

                        column.options._realWidth = width;
                    }
                });
            };

            baseView.prototype._renderContent = function () {
                this._renderCOLS();
                this._renderHeader();

                if (this._wijgrid.options.showFilter) {
                    this._renderFilter();
                }

                this.mDetailsToInstantiate = [];

                this._renderBody();

                for (var i = 0; i < this.mDetailsToInstantiate.length; i++) {
                    this.mDetailsToInstantiate[i]();
                }

                if (this._wijgrid.options.showFooter) {
                    this._renderFooter();
                }
            };

            baseView.prototype._renderCOLS = function () {
                var _this = this;
                var leaves = this._wijgrid._leaves();
                this.currentRenderableColumns().forEachIndex(function (i) {
                    var leaf = leaves[i], domCol, visLeavesIdx;

                    if (leaf._visible()) {
                        visLeavesIdx = leaf.options._visLeavesIdx;
                        domCol = _this._createCol(leaf, visLeavesIdx);
                        _this._appendCol(domCol, leaf, visLeavesIdx);
                    }
                });
            };

            baseView.prototype._renderHeader = function () {
                var self = this, cht = self._wijgrid._columnsHeadersTable(), thX, row, thead, meta, hdr, cell, attr, column;

                if (cht && cht.length) {
                    thX = -self._wijgrid._virtualLeaves().length; // skip virtual leaves

                    for (var i = 0, chtRowLength = cht.length; i < chtRowLength; i++) {
                        row = self._insertEmptyRow(1 /* header */, 1 /* rendering */, i, -1, -1, -1, -1, undefined, {});
                        thead = self._wijgrid._tHead();
                        meta = thead && wijmo.grid.dataViewWrapper.getMetadata(thead[row.sectionRowIndex]); // rowInfo.sectionRowIndex == column._thY
                        hdr = (meta && meta.rowAttributes) ? new grid.SketchHeaderRow(meta.rowAttributes) : new grid.SketchHeaderRow(undefined);

                        for (var j = 0, chtCellLength = cht[i].length; j < chtCellLength; j++) {
                            cell = cht[i][j];
                            column = cell.column || undefined;

                            if (column) {
                                // provide cell attributes, that were read from the original header cell at initialization stage
                                attr = (meta && meta.cellsAttributes && meta.cellsAttributes[thX]) ? meta.cellsAttributes[thX] : {};
                                $.extend(attr, { colSpan: cell.colSpan, rowSpan: cell.rowSpan });
                                thX++;
                            }

                            hdr.add(new grid.HeaderCell(column, attr));
                        }

                        self._renderRow(row, null, hdr);
                    }
                }
            };

            baseView.prototype._renderFilter = function () {
                var rowInfo = this._insertEmptyRow(8 /* filter */, 1 /* rendering */, -1, -1, -1, -1, -1, undefined, {});
                this._renderRow(rowInfo, this._wijgrid._leaves(), null);
            };

            baseView.prototype._renderBody = function () {
                var rs = wijmo.grid.renderState, leaves = this._wijgrid._leaves(), sketch = this._wijgrid.mSketchTable, dataRowIndex = -1, virtualDataItemIndexBase = 0, cnt = 0, dataOffset = this._wijgrid.mDataOffset;

                // render rows
                var self = this;

                if (this._bounds.start >= 0 && this._bounds.end >= 0) {
                    this._wijgrid._renderableRowsRange().forEachIndex(this._bounds.start, this._bounds.end - this._bounds.start + 1, function (idx) {
                        var sketchRowIndex = idx - dataOffset, sketchRow = sketch.row(sketchRowIndex);
                        if (sketchRow) {
                            var isDataRow = sketchRow.isDataRow(), groupKey = sketchRow.groupByValue, rowInfo = self._insertEmptyRow(sketchRow.rowType, 1 /* rendering */, cnt++, isDataRow ? ++dataRowIndex : -1, sketchRow.dataItemIndex(), sketchRow.dataItemIndex(virtualDataItemIndexBase), sketchRowIndex, groupKey, sketchRow.extInfo);

                            self._renderRow(rowInfo, leaves, sketchRow);
                        }
                    });
                }
            };

            baseView.prototype._renderFooter = function () {
                var rowInfo = this._insertEmptyRow(64 /* footer */, 1 /* rendering */, -1, -1, -1, -1, -1, undefined, {});
                this._renderRow(rowInfo, this._wijgrid._leaves(), null);
            };

            baseView.prototype._insertEmptyRow = function (rowType, renderState, sectionRowIndex, dataRowIndex, dataItemIndex, virtualDataItemIndex, sketchRowIndex, groupByValue, extInfo) {
                var domRow = this._wijgrid._onViewInsertEmptyRow.apply(this._wijgrid, arguments), domRowArr = this._insertRow(rowType, sectionRowIndex, domRow);

                if (renderState === undefined) {
                    renderState = 1 /* rendering */;
                }

                return this._createRowInfo(domRowArr, rowType, renderState, sectionRowIndex, dataRowIndex, dataItemIndex, virtualDataItemIndex, sketchRowIndex, groupByValue, extInfo);
            };

            baseView.prototype._createEmptyCell = function (rowInfo, dataCellIndex, column) {
                var rt = wijmo.grid.rowType, domCell = this._wijgrid._onViewCreateEmptyCell.apply(this._wijgrid, arguments);

                return this._createCell(rowInfo.type, domCell);
            };

            // override
            baseView.prototype._insertRow = function (rowType, sectionRowIndex, domRow /* optional, used by c1gridview to clone rows of the original table */ ) {
                throw "not implemented";
            };

            baseView.prototype._createCell = function (rowType, domCell /* optional, used by c1gridview to clone cells of the original table */ ) {
                var rt = wijmo.grid.rowType, innerContainer, wrap;

                if (!domCell) {
                    if (rowType === 1 /* header */) {
                        domCell = document.createElement("th");
                    } else {
                        domCell = document.createElement("td");
                    }
                } else {
                    wrap = $(domCell).css("white-space");
                }

                if (rowType !== 8 /* filter */) {
                    // * analogue of domCell.wrapInner("<div class=\"wijmo-wijgrid-innercell\"></div>")
                    innerContainer = document.createElement("div");
                    innerContainer.className = wijmo.grid.wijgrid.CSS.cellContainer + " " + this._wijgrid.options.wijCSS.wijgridCellContainer;

                    if (domCell.firstChild) {
                        while (domCell.firstChild) {
                            innerContainer.appendChild(domCell.firstChild);
                        }
                    }

                    if (wrap && wrap !== "normal") {
                        $(innerContainer).css("white-space", wrap);
                        $(domCell).css("white-space", "");
                    }

                    domCell.appendChild(innerContainer);
                }

                return $(domCell);
            };

            baseView.prototype._appendCell = function (rowInfo, cellIndex, $cell) {
                throw "not implemented";
            };

            baseView.prototype._createCol = function (column, visibleIdx) {
                throw "not implemented";
            };

            baseView.prototype._appendCol = function (domCol, column, visibleIdx) {
                throw "not implemented";
            };

            baseView.prototype._renderRow = function (rowInfo, leaves, item) {
                var $rt = wijmo.grid.rowType, rowAttr, rowStyle;

                switch (rowInfo.type & ~(4 /* dataAlt */ | 256 /* dataHeader */)) {
                    case 8 /* filter */:
                        this._renderFilterRow(rowInfo, leaves);
                        break;

                    case 64 /* footer */:
                        this._renderFooterRow(rowInfo, leaves);
                        break;

                    case 1 /* header */:
                        this._renderHeaderRow(rowInfo, item);
                        rowAttr = item.attr();
                        rowStyle = item.style();
                        break;

                    case 2 /* data */:
                        this._renderDataRow(rowInfo, leaves, item);
                        rowAttr = item.attr();
                        rowStyle = item.style();
                        break;

                    case 1024 /* detail */:
                    case 2 /* data */ | 512 /* dataDetail */:
                    case 128 /* emptyDataRow */:
                    case 16 /* groupHeader */:
                    case 32 /* groupFooter */:
                        this._renderSpannedRow(rowInfo, leaves, item);
                        rowAttr = item.attr();
                        rowStyle = item.style();
                        break;

                    default:
                        throw "unknown rowType";
                }

                this._rowRendered(rowInfo, rowAttr, rowStyle);
            };

            baseView.prototype._renderCell = function (rowInfo, cellIndex, value, useHtml, leaf, state, attr, style) {
                var $cell = this._createEmptyCell(rowInfo, leaf.options.dataIndex, leaf);
                var $container = (rowInfo.type === 8 /* filter */) ? $cell : $($cell[0].firstChild);

                this._appendCell(rowInfo, cellIndex, $cell);

                if (useHtml) {
                    $container.html(value !== undefined ? value : "&nbsp;");
                } else {
                    this._wijgrid.mCellFormatter.format($cell, cellIndex, $container, leaf, value, rowInfo);
                }

                this._cellRendered(rowInfo, $cell, $container, cellIndex, leaf, state, attr, style);
            };

            baseView.prototype._renderDataRow = function (rowInfo, leaves, sketchRow) {
                var _this = this;
                //for (var i = 0, len = leaves.length; i < len; i++) {
                this.currentRenderableColumns().forEachIndex(function (i) {
                    var leaf = leaves[i];

                    if (leaf._visible()) {
                        var cell = sketchRow.cell(i), attr = cell.attr(), style = cell.style(), value, state = rowInfo.state;

                        if (leaf instanceof grid.c1field) {
                            if (!cell || !cell.visible()) {
                                //continue;
                                return;
                            }

                            value = _this._wijgrid.toStr(leaf.options, cell.value);
                            attr = cell.attr();
                            style = cell.style();
                        } else {
                            // unbound column
                            value = null;
                        }

                        if (leaf.options.readOnly) {
                            state &= ~16 /* editing */;
                        }

                        _this._renderCell(rowInfo, i, value, false, leaf, state, attr, style);
                    }
                });
            };

            baseView.prototype._renderFilterRow = function (rowInfo, leaves) {
                var _this = this;
                //for (var i = 0, len = leaves.length; i < len; i++) {
                this.currentRenderableColumns().forEachIndex(function (i) {
                    var leaf = leaves[i];

                    if (leaf._visible()) {
                        _this._renderCell(rowInfo, i, wijmo.grid.filterHelper.getSingleValue(leaf.options.filterValue), false, leaf, rowInfo.state);
                    }
                });
            };

            baseView.prototype._renderFooterRow = function (rowInfo, leaves) {
                var _this = this;
                //for (var i = 0, len = leaves.length; i < len; i++) {
                this.currentRenderableColumns().forEachIndex(function (i) {
                    var leaf = leaves[i];

                    if (leaf._visible()) {
                        _this._renderCell(rowInfo, i, "", false, leaves[i], rowInfo.state);
                    }
                });
            };

            baseView.prototype._renderHeaderRow = function (rowInfo, item) {
                var self = this, thX = 0, thX2 = -self._wijgrid._virtualLeaves().length;

                this.currentRenderableColumns().forEachIndex(function (i) {
                    var cell = item.cell(i), column = cell.column, instance;

                    if (column) {
                        column._thX2 = thX2++;

                        if (column._parentVis) {
                            column._thX = thX++;
                            column._thY = rowInfo.sectionRowIndex;

                            instance = self._wijgrid._findInstance(column);

                            self._renderCell(rowInfo, i, column.headerText, false, instance, rowInfo.state, cell.attr());
                        }
                    }
                });
            };

            baseView.prototype._renderSpannedRow = function (rowInfo, leaves, sketchRow) {
                var len = Math.min(leaves.length, sketchRow.cellCount());

                for (var i = 0; i < len; i++) {
                    var leaf = leaves[i];
                    var useHTML = rowInfo.type === 128 /* emptyDataRow */;
                    var cell = sketchRow.cell(i);

                    this._renderCell(rowInfo, i, cell.html, useHTML, leaf, rowInfo.state, cell.attr(), cell.style());
                }
            };

            baseView.prototype._cellRendered = function (row, cell, container, cellIndex, column, cellState, attr, style) {
                this._wijgrid.mCellStyleFormatter.format(cell, cellIndex, column, row, cellState, attr, style);

                this._changeCellRenderState(cell, cellState, false);

                this._wijgrid._onViewCellRendered(cell, container, row, cellIndex, column);

                column._cellRendered(cell, container, row);
            };

            baseView.prototype._rowRendered = function (rowInfo, rowAttr, rowStyle) {
                this._wijgrid.mRowStyleFormatter.format(rowInfo, rowAttr, rowStyle);

                // change renderState AND associate rowInfo object with DOMRow
                //this._changeRowRenderState(rowInfo, $.wijmo.wijgrid.renderState.rendering, false);
                rowInfo.state &= ~1 /* rendering */;
                this._setRowInfo(rowInfo.$rows, rowInfo);

                this._wijgrid._onViewRowRendered(rowInfo, rowAttr, rowStyle);
            };

            baseView.prototype._makeRowEditable = function (rowInfo) {
                var leaves = this._wijgrid._visibleLeaves(), cellEditor = new wijmo.grid.cellEditorHelper();

                if (leaves) {
                    for (var i = 0; i < leaves.length; i++) {
                        var column = leaves[i];

                        if ((column instanceof grid.c1field) && !column.options.readOnly) {
                            var absRowIndex = this.getAbsoluteRowIndex(rowInfo.$rows[0]);
                            var cell = this.getCell(i, absRowIndex);

                            if (cell) {
                                var $cell = $(cell);
                                var cellInfo = this.getAbsoluteCellInfo(cell, true);
                                this._changeCellRenderState($cell, 16 /* editing */, cellEditor.cellEditStart(this._wijgrid, cellInfo, null)); // add or remove editing state depends on cellEditStart result.
                            }
                            //var $cell = rowInfo.$rows.children("td, th").eq(i);
                            //if ($cell.length) {
                            //	var cellInfo = this.getAbsoluteCellInfo(<HTMLTableCellElement>$cell[0], true);
                            //	this._changeCellRenderState($cell, wijmo.grid.renderState.editing, cellEditor.cellEditStart(this._wijgrid, cellInfo, null));
                            //}
                        }
                    }
                }
            };

            baseView.prototype._isBodyRow = function (rowInfo) {
                var $rt = wijmo.grid.rowType, type = rowInfo.type;

                return ((type & 2 /* data */) || (type === 16 /* groupHeader */) || (type === 32 /* groupFooter */) || (type === 128 /* emptyDataRow */) || (type === 1024 /* detail */));
            };

            baseView.prototype._changeRowRenderState = function (rowInfo, state, combine) {
                if (combine) {
                    rowInfo.state |= state;
                } else {
                    rowInfo.state &= ~state;
                }

                this._setRowInfo(rowInfo.$rows, rowInfo);
            };

            baseView.prototype._changeCellRenderState = function ($obj, state, combine) {
                var $dp = wijmo.grid.dataPrefix, prefix = this._wijgrid.mDataPrefix, prevState = $dp($obj, prefix, "renderState");

                if (combine) {
                    state = prevState | state;
                    $dp($obj, prefix, "renderState", state);
                } else {
                    state = prevState & ~state;
                    $dp($obj, prefix, "renderState", state);
                }

                return state;
            };

            // rendering **
            // ** sizing
            baseView.prototype._resetWidth = function () {
                var _this = this;
                var leaves = this._wijgrid._visibleLeaves();

                $.each(leaves, function (index, column) {
                    _this._setColumnWidth(column, null);
                });

                $.each(this.subTables(), function (index, table) {
                    table.element().style.width = "100%";
                });
            };

            baseView.prototype._adjustWidthArray = function (maxWidthArray, minWidthArray, expectedWidth, ensureColumnsPxWidth) {
                var maxWidth = this._sumWidthArray(maxWidthArray), minWidth = this._sumWidthArray(minWidthArray), widthArray = [], adjustWidth, expandCount = 0, expandWidth, remainingWidth, bFirst = true;

                if (maxWidth <= expectedWidth) {
                    $.extend(true, widthArray, maxWidthArray);
                    if (maxWidth === expectedWidth || ensureColumnsPxWidth) {
                        return widthArray;
                    } else {
                        adjustWidth = expectedWidth - maxWidth;
                    }
                } else {
                    $.extend(true, widthArray, minWidthArray);
                    if (minWidth >= expectedWidth) {
                        return widthArray;
                    } else {
                        adjustWidth = expectedWidth - minWidth;
                    }
                }

                $.each(widthArray, function (index, colWidth) {
                    if (!colWidth.real) {
                        expandCount++;
                    }
                });

                if (expandCount !== 0) {
                    expandWidth = Math.floor(adjustWidth / expandCount);
                    remainingWidth = adjustWidth - expandWidth * expandCount;
                    $.each(widthArray, function (index, colWidth) {
                        if (!colWidth.real) {
                            colWidth.width += expandWidth;
                            if (bFirst) {
                                colWidth.width += remainingWidth;
                                bFirst = false;
                            }
                        }
                    });
                }

                return widthArray;
            };

            baseView.prototype._getColumnWidth = function (index) {
                var column = this._wijgrid._visibleLeaves()[index];

                if (column instanceof grid.c1rowheaderfield) {
                    return { width: grid.c1rowheaderfield.COLUMN_WIDTH, real: true };
                } else if (column.options._realWidth !== undefined && column._strictWidthMode()) {
                    return { width: column.options._realWidth, real: true, realPercent: wijmo.grid.isPercentage(column.options.width) };
                } else {
                    var maxW = 0, joinedTables = this.getJoinedTables(true, index), relIdx = joinedTables[2];

                    for (var i = 0; i < 2; i++) {
                        var table = joinedTables[i];

                        if (table !== null) {
                            var rows = table.element().rows, row = null, len = rows.length;

                            if (len > 0) {
                                for (var j = len - 1; j >= 0; j--) {
                                    if (rows[j].cells.length === table.width()) {
                                        row = rows[j];

                                        if (row.style.display !== "none") {
                                            break;
                                        }
                                    }
                                }

                                if (row) {
                                    var cell = row.cells[relIdx];
                                    maxW = Math.max(maxW, $(cell).outerWidth());
                                }
                            }
                        }
                    }

                    return { width: maxW, real: false };
                }
            };

            // px: null to reset.
            baseView.prototype._setColumnWidth = function (column, px) {
                var _this = this;
                if (!column || !column._isRendered()) {
                    return;
                }

                var visibleIndex = column.options._visLeavesIdx, th = this.getHeaderCell(visibleIndex), cols = this.getJoinedCols(visibleIndex), value;

                if (px || px === 0) {
                    if (th) {
                        value = px - this._sizesAdjCache.th;
                        if (value < 0) {
                            value = 0;
                        }

                        th.style.width = value + "px";
                    }

                    $.each(cols, function (i, col) {
                        if (col) {
                            value = px - _this._sizesAdjCache.col;
                            if (value < 0) {
                                value = 0;
                            }

                            col.style.width = value + "px";
                        }
                    });
                } else {
                    if (th) {
                        th.style.width = "";
                    }

                    $.each(cols, function (index, col) {
                        if (col) {
                            col.style.width = "";
                        }
                    });
                }
            };

            baseView.prototype._setTableWidth = function (subTables, expectedWidth, expandColumnWidth, expandColumn) {
                var after, diff, self = this;

                $.each(subTables, function (index, table) {
                    //table.css("table-layout", "fixed").setOutWidth(expectedWidth); // very slow in IE9
                    table[0].style.tableLayout = "fixed";
                    table[0].style.width = (expectedWidth - self._sizesAdjCache.subTable) + "px";
                });

                after = subTables[0].outerWidth();
                diff = after - expectedWidth;
                if (diff !== 0) {
                    this._setColumnWidth(expandColumn, expandColumnWidth - diff);
                }
            };

            baseView.prototype._sumWidthArray = function (widthArray, startIndex, endIndex) {
                var result = 0, leaves = this._wijgrid._visibleLeaves();

                $.each(widthArray, function (index, colWidth) {
                    if (startIndex !== undefined && endIndex !== undefined && (index < startIndex || index > endIndex || (startIndex >= 0 && !leaves[index]._isRendered()))) {
                        return true;
                    }
                    result += colWidth.width;
                });

                return result;
            };

            // sizing **
            // private abstract **
            baseView.prototype._clearBody = function () {
                $.each(this.subTables(), function (key, table) {
                    table.clearSection(2);
                });
            };

            baseView.prototype._rebuildOffsets = function () {
                $.each(this.subTables(), function (key, table) {
                    table.rebuildOffsets();
                });
            };

            baseView.prototype._removeBodyRow = function (sectionRowIndex, changeOffsets) {
                if (typeof changeOffsets === "undefined") { changeOffsets = true; }
                var rows = this._wijgrid._rows(), len;

                if ((sectionRowIndex >= 0) && (sectionRowIndex < (len = rows.length()))) {
                    // remove DOMRows
                    var rowInfo = this._getRowInfo(rows.item(sectionRowIndex), false), absRowIdx = this.getAbsoluteRowIndex(rowInfo.$rows[0]);

                    rowInfo.$rows.remove();

                    // ** update offsets
                    if (changeOffsets) {
                        var joinedTables = this.getJoinedTables(false, absRowIdx), ta;

                        if (ta = joinedTables[0]) {
                            ta.removeOffset(joinedTables[2]);
                        }

                        if (ta = joinedTables[1]) {
                            ta.removeOffset(joinedTables[2]);
                        }
                    }
                    // update offsets **
                }
            };

            baseView.prototype._insertBodyRow = function (sketchRow, sectionRowIndex, dataItemIndex, virtualDataItemIndex, sketchRowIndex) {
                var leaves = this._wijgrid._leaves(), $rt = wijmo.grid.rowType, view = this._wijgrid._view(), rows = this._wijgrid._rows(), len = rows.length(), isDataRow = sketchRow.isDataRow(), rowInfo, absRowIdx;

                if (sectionRowIndex < 0 || sectionRowIndex >= len || (!sectionRowIndex && sectionRowIndex !== 0)) {
                    sectionRowIndex = len; // append
                }

                rowInfo = this._insertEmptyRow(sketchRow.rowType, sketchRow.renderState, sectionRowIndex, -1, dataItemIndex, virtualDataItemIndex, sketchRowIndex, sketchRow.groupByValue, sketchRow.extInfo);

                this._renderRow(rowInfo, leaves, sketchRow);

                // ** update offsets
                absRowIdx = this.getAbsoluteRowIndex(rowInfo.$rows[0]);

                var joinedTables = this.getJoinedTables(false, absRowIdx), ta;

                if (ta = joinedTables[0]) {
                    ta.insertOffset(joinedTables[2]);
                }

                if (ta = joinedTables[1]) {
                    ta.insertOffset(joinedTables[2]);
                }

                // update offsets **
                return rowInfo;
            };

            baseView.prototype._setRowInfo = function (obj, row) {
                if (!obj) {
                    return;
                }

                var tmpRows = row.$rows, tmpData = row.data;

                row.$rows = undefined;
                row.data = undefined;

                wijmo.grid.dataPrefix(obj, this._wijgrid.mDataPrefix, "rowInfo", row);

                row.$rows = tmpRows;
                row.data = tmpData;
            };

            baseView.prototype._getRowInfo = function (rowObj, retrieveDataItem) {
                if (typeof retrieveDataItem === "undefined") { retrieveDataItem = true; }
                var wijgrid = this._wijgrid, $rows = rowObj[1] ? $(rowObj) : $(rowObj[0]), rowInfo = wijmo.grid.dataPrefix($rows, wijgrid.mDataPrefix, "rowInfo");

                // add $rows property
                rowInfo.$rows = $rows;

                // set data property
                if (retrieveDataItem && (rowInfo.dataItemIndex >= 0) && (rowInfo.type & 2 /* data */)) {
                    try  {
                        rowInfo.data = wijgrid._getDataItem(rowInfo.dataItemIndex);
                    } catch (ex) {
                        rowInfo.data = null; // underlying data item was removed?
                    }
                }

                return rowInfo;
            };

            baseView.prototype._getRowInfoBySketchRowIndex = function (sketchIndex, retrieveDataItem) {
                if (typeof retrieveDataItem === "undefined") { retrieveDataItem = true; }
                if (sketchIndex >= 0) {
                    var renderedRowIndex = this._isRowRendered(sketchIndex);

                    if (renderedRowIndex >= 0) {
                        var rowObj = this.bodyRows().item(renderedRowIndex);

                        if (rowObj) {
                            return this._getRowInfo(rowObj, retrieveDataItem);
                        }
                    } else {
                        // detached row
                        var sketchRow = this._wijgrid.mSketchTable.row(sketchIndex), rowInfo = null;

                        if (sketchRow) {
                            rowInfo = sketchRow.getRowInfo();

                            // set data property
                            if (retrieveDataItem && (rowInfo.dataItemIndex >= 0) && sketchRow.isDataRow()) {
                                try  {
                                    rowInfo.data = this._wijgrid._getDataItem(rowInfo.dataItemIndex);
                                } catch (ex) {
                                    rowInfo.data = null; // underlying data item was removed?
                                }
                            }
                        }

                        return rowInfo;
                    }
                }

                return null;
            };

            baseView.prototype._createRowInfo = function (row, type, state, sectionRowIndex, dataRowIndex, dataItemIndex, virtualDataItemIndex, sketchRowIndex, groupByValue, extInfo) {
                var rowInfo = {
                    type: type,
                    state: state,
                    sectionRowIndex: sectionRowIndex,
                    dataRowIndex: dataRowIndex,
                    dataItemIndex: dataItemIndex,
                    virtualDataItemIndex: virtualDataItemIndex,
                    sketchRowIndex: sketchRowIndex,
                    $rows: row ? $(row) : null,
                    _extInfo: extInfo
                };

                if (groupByValue !== undefined) {
                    rowInfo.groupByValue = groupByValue;
                }

                // set data property
                if ((dataItemIndex >= 0) && (type & 2 /* data */)) {
                    rowInfo.data = this._wijgrid._getDataItem(dataItemIndex);
                }

                return rowInfo;
            };

            // returns tbody row index or -1
            baseView.prototype._isRowRendered = function (sketchRowIndex) {
                var visibleIndex = this._wijgrid._renderableRowsRange().getRenderedIndex(sketchRowIndex);

                if (visibleIndex >= 0) {
                    if (visibleIndex >= this._bounds.start && visibleIndex <= this._bounds.end) {
                        return visibleIndex - this._bounds.start;
                    }
                }

                return -1;
            };
            return baseView;
        })();
        grid.baseView = baseView;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="interfaces.ts" />
/// <reference path="wijgrid.ts" />
/// <reference path="misc.ts" />
/// <reference path="baseView.ts" />
/// <reference path="htmlTableAccessor.ts" />
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    (function (grid) {
        var $ = jQuery;

        /** @ignore */
        var flatView = (function (_super) {
            __extends(flatView, _super);
            function flatView(wijgrid, renderBounds) {
                _super.call(this, wijgrid, renderBounds);
                this._dataTable = null;
                this._contentArea = null;
            }
            //ensureWidth(index: number, value, oldValue) {
            //	var $table = $(this._dataTable.element()),
            //		tableWidth = $table.width() + value - oldValue;
            //	super.ensureWidth(index, value, oldValue);
            //	this._setTableWidth([$table], tableWidth, value, index);
            //}
            flatView.prototype.getVisibleAreaBounds = function (client) {
                var bounds = wijmo.grid.bounds(this._dataTable.element(), client);

                return bounds;
            };

            flatView.prototype.getVisibleContentAreaBounds = function () {
                return this.getVisibleAreaBounds();
            };

            flatView.prototype.updateSplits = function (scrollValue, rowsToAdjust) {
                var _this = this;
                var self = this, wijgrid = this._wijgrid, o = wijgrid.options, gridElement = wijgrid.element, maxWidthArray = [], minWidthArray = [], resultWidthArray = [], visibleLeaves = wijgrid._visibleLeaves(), outerDiv = wijgrid.mOuterDiv, outerWidth, expandIndex;

                gridElement.css({
                    "table-layout": "",
                    "width": "auto"
                });

                // read column widths.
                $.each(visibleLeaves, function (index, leaf) {
                    if (leaf.options._realWidth !== undefined) {
                        _this._setColumnWidth(leaf, leaf.options._realWidth);
                    }

                    maxWidthArray.push(_this._getColumnWidth(index));
                });

                gridElement.css("width", "1px");

                $.each(visibleLeaves, function (index, leaf) {
                    minWidthArray.push(self._getColumnWidth(index));
                });

                outerWidth = outerDiv.width(); // using width() instead of innerWidth() to exclude padding.
                resultWidthArray = this._adjustWidthArray(maxWidthArray, minWidthArray, outerWidth, o.ensureColumnsPxWidth);

                $.each(resultWidthArray, function (index, colWidth) {
                    var leaf = visibleLeaves[index];

                    if (leaf.options._realWidth !== undefined && leaf._strictWidthMode()) {
                        //delete leaf.options._realWidth;
                        return;
                    }

                    self._setColumnWidth(leaf, colWidth.width);
                });

                gridElement.css("table-layout", "fixed");

                expandIndex = resultWidthArray.length - 1;
                if (expandIndex !== -1) {
                    var delta = outerDiv.width() - outerWidth;
                    resultWidthArray[expandIndex].width += delta;

                    this._setTableWidth([gridElement], this._sumWidthArray(resultWidthArray, 0, expandIndex), resultWidthArray[expandIndex].width, visibleLeaves[expandIndex]);
                }
            };

            flatView.prototype.getInlineTotalWidth = function () {
                var table = this._dataTable.element(), width = table.style.width;

                if (width && (width !== "auto")) {
                    return width;
                }

                return "";
            };

            // public **
            // ** DOMTable abstraction
            flatView.prototype.forEachColumnCell = function (columnIndex, callback, param) {
                return this._dataTable.forEachColumnCell(columnIndex, callback, param);
            };

            flatView.prototype.forEachRowCell = function (rowIndex, callback, param) {
                return this._dataTable.forEachRowCell(rowIndex, callback, param);
            };

            flatView.prototype.getAbsoluteCellInfo = function (domCell, virtualize) {
                return new wijmo.grid.cellInfo(this.getColumnIndex(domCell), domCell.parentNode.rowIndex, this._wijgrid, true, virtualize);
            };

            flatView.prototype.getAbsoluteCellIndex = function (domCell) {
                return this.getColumnIndex(domCell);
            };

            flatView.prototype.getAbsoluteRowIndex = function (domRow) {
                return domRow.rowIndex;
            };

            flatView.prototype.getCell = function (absColIdx, absRowIdx) {
                var cellIdx = this._dataTable.getCellIdx(absColIdx, absRowIdx), rowObj;

                if (cellIdx >= 0) {
                    rowObj = this.getJoinedRows(absRowIdx, 0);
                    if (rowObj[0]) {
                        return rowObj[0].cells[cellIdx];
                    }
                }

                return null;
            };

            flatView.prototype.getColumnIndex = function (domCell) {
                return this._dataTable.getColumnIdx(domCell);
            };

            flatView.prototype.getHeaderCell = function (absColIdx) {
                var leaf = this._wijgrid._visibleLeaves()[absColIdx], headerRow;

                if (leaf && (headerRow = this._wijgrid._headerRows())) {
                    return wijmo.grid.rowAccessor.getCell(headerRow.item(leaf.options._thY), leaf.options._thX);
                }

                return null;
            };

            flatView.prototype.getJoinedCols = function (columnIndex) {
                var $colGroup = $(this._dataTable.element()).find("> colgroup");

                if ($colGroup.length) {
                    if (columnIndex < $colGroup[0].childNodes.length) {
                        return [$colGroup[0].childNodes[columnIndex], null];
                    }
                }

                return [null, null];
            };

            flatView.prototype.getJoinedRows = function (rowIndex, rowScope) {
                return [this._dataTable.getSectionRow(rowIndex, rowScope), null];
            };

            flatView.prototype.getJoinedTables = function (byColumn, index) {
                return [this._dataTable, null, index];
            };

            flatView.prototype.subTables = function () {
                return [this._dataTable];
            };

            // DOMTable abstraction **
            // ** private abstract
            //  ** render
            flatView.prototype._preRender = function () {
                _super.prototype._preRender.call(this);
                this._dataTable = new wijmo.grid.htmlTableAccessor(this._wijgrid.element[0], true, true, true); // skip offsets, ensure tbody + colgroup
            };

            flatView.prototype._postRender = function () {
                this._wijgrid.element.find("> tbody").addClass(this._wijgrid.options.wijCSS.content);

                this._dataTable = new wijmo.grid.htmlTableAccessor(this._wijgrid.element[0]); // create with offsets

                this._wijgrid._setAttr(this._wijgrid.element, {
                    role: "grid",
                    cellpadding: "0",
                    border: "0",
                    cellspacing: "0"
                });

                this._wijgrid.element.css("border-collapse", "separate");

                _super.prototype._postRender.call(this);
            };

            flatView.prototype._insertRow = function (rowType, sectionRowIndex, domRow /* optional, used by c1gridview to clone rows of the original table */ ) {
                var $rt = wijmo.grid.rowType, tableSection;

                switch (rowType) {
                    case 1 /* header */:
                    case 8 /* filter */:
                        tableSection = this._dataTable.ensureTHead();
                        break;

                    case 64 /* footer */:
                        tableSection = this._dataTable.ensureTFoot();
                        break;

                    default:
                        tableSection = this._dataTable.ensureTBody();
                }

                if (domRow) {
                    // append only
                    return [tableSection.appendChild(domRow)];
                } else {
                    if (sectionRowIndex > tableSection.rows.length) {
                        sectionRowIndex = -1;
                    }

                    return [tableSection.insertRow(sectionRowIndex)];
                }
            };

            flatView.prototype._rowRendered = function (rowInfo, rowAttr, rowStyle) {
                var domRow = rowInfo.$rows[0];

                if (!domRow.cells.length && this._isBodyRow(rowInfo)) {
                    domRow.parentNode.removeChild(domRow);
                } else {
                    _super.prototype._rowRendered.call(this, rowInfo, rowAttr, rowStyle);
                }
            };

            flatView.prototype._appendCell = function (rowInfo, cellIndex, $cell) {
                rowInfo.$rows[0].appendChild($cell[0]);
                //rowInfo.$rows.append($cell);
            };

            flatView.prototype._createCol = function (column, visibleIdx) {
                return [document.createElement("col")];
            };

            flatView.prototype._appendCol = function (domCol, column, visibleIdx) {
                this._dataTable.appendCol(domCol[0]);
            };
            return flatView;
        })(grid.baseView);
        grid.flatView = flatView;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="../../../wijsuperpanel/jquery.wijmo.wijsuperpanel.ts" />
/// <reference path="../../../wijlist/jquery.wijmo.wijlist.ts" />
/// <reference path="interfaces.ts" />
/// <reference path="wijgrid.ts" />
/// <reference path="misc.ts" />
/// <reference path="baseView.ts" />
/// <reference path="uiVirtualScroller.ts" />
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    (function (_grid) {
        var $ = jQuery;

        /** @ignore */
        var fixedView = (function (_super) {
            __extends(fixedView, _super);
            function fixedView(wijgrid, renderBounds) {
                _super.call(this, wijgrid, renderBounds);
                this._verScrollBarSize = wijmo.grid.getSuperPanelScrollBarSize();
                this._viewTables = {};
                this._splitAreas = {};
                this._superPanelElementsCache = {};
                this.mHVSOffset = 0;

                this.mRowsHeights = [];

                this.element = wijgrid.element; // table element

                this._staticDataRowIndex = wijgrid._getStaticIndex(true);
                this._staticRowIndex = wijgrid._getRealStaticRowIndex();
                this._staticColumnIndex = wijgrid._getRealStaticColumnIndex();
                this._staticAllColumnIndex = (this._staticColumnIndex === -1) ? -1 : wijgrid._visibleLeaves()[this._staticColumnIndex].options._leavesIdx;

                this._mouseWheelHandler = $.proxy(this._onMouseWheel, this);
            }
            fixedView.prototype.dispose = function () {
                _super.prototype.dispose.call(this);

                this.element.css({ width: "", height: "" }); // 48969
                this._wijgrid.mOuterDiv.unbind("mousewheel", this._mouseWheelHandler);
            };

            //ensureWidth(index, value, oldValue) {
            //	var wijgrid = this._wijgrid,
            //		staticColumnIndex = this._staticColumnIndex,
            //		bWest = index <= staticColumnIndex,
            //		$tableNW = $(this._viewTables.nw.element()),
            //		$tableNE = $(this._viewTables.ne.element()),
            //		$tableSW = $(this._viewTables.sw.element()),
            //		$tableSE = $(this._viewTables.se.element()),
            //		tableArray = bWest ? [$tableNW, $tableSW] : [$tableNE, $tableSE],
            //		tableWidth = (bWest ? $tableNW.width() : $tableNE.width()) + value - oldValue,
            //		scrollValue = this.getScrollValue();
            //	this._destroySuperPanel();
            //	super.ensureWidth(index, value, oldValue);
            //	this._setTableWidth(tableArray, tableWidth, value, index);
            //	try {
            //		if (staticColumnIndex >= 0) {
            //			wijgrid.mSplitDistanceX = $tableNW[0].offsetWidth;
            //		} else {
            //			wijgrid.mSplitDistanceX = 0;
            //		}
            //	} catch (ex) { }
            //	this._updateSplitAreaBounds(0);
            //	this._adjustRowsHeights();
            //	try {
            //		if (this._staticRowIndex >= 0) {
            //			wijgrid.mSplitDistanceY = Math.max($tableNW[0].offsetHeight, $tableNE[0].offsetHeight);
            //		} else {
            //			wijgrid.mSplitDistanceY = 0;
            //		}
            //	} catch (ex) { }
            //	this._updateSplitAreaBounds(1);
            //	this.refreshPanel(scrollValue);
            //	var frozener = wijgrid._UIFrozener();
            //	if (frozener) {
            //		frozener.refresh();
            //	}
            //}
            fixedView.prototype.render = function (live) {
                if (!live) {
                    this.resetRowsHeightsCache();
                }

                _super.prototype.render.apply(this, arguments);
            };

            fixedView.prototype._resetWidth = function () {
                this._getSuperPanelContentWrapper().width("");

                _super.prototype._resetWidth.apply(this, arguments);
            };

            fixedView.prototype.resetRowsHeightsCache = function () {
                this.mRowsHeights = [];
            };

            fixedView.prototype.ensureHeight = function (rowIndex) {
                var wijgrid = this._wijgrid, $tableNW = $(this._viewTables.nw.element()), $tableNE = $(this._viewTables.ne.element()), $tableSW = $(this._viewTables.sw.element()), $tableSE = $(this._viewTables.se.element()), scrollValue = this.getScrollValue();

                this._destroySuperPanel();

                $tableSE.css("height", "");
                $tableSW.css("height", "");

                if (arguments.length > 0) {
                    var rowObjsArray = this.getJoinedRows(rowIndex, 2);
                    this._setRowHeight(rowObjsArray, this._getRowHeight(rowObjsArray));
                }

                var maxHeight = Math.max($tableSE.height(), $tableSW.height());

                $tableSE.height(maxHeight);
                $tableSW.height(maxHeight);

                try  {
                    if (this._staticRowIndex >= 0) {
                        wijgrid.mSplitDistanceY = Math.max($tableNW[0].offsetHeight, $tableNE[0].offsetHeight);
                    } else {
                        wijgrid.mSplitDistanceY = 0;
                    }
                } catch (ex) {
                }

                this._updateSplitAreaBounds(1);

                this._refreshPanel(scrollValue);

                wijgrid._UIFrozener().refresh();
            };

            fixedView.prototype.getScrollValue = function () {
                var superPanelObj = this._getSuperPanel();

                return superPanelObj ? { x: superPanelObj.options.hScroller.scrollValue, y: superPanelObj.options.vScroller.scrollValue } : null;
            };

            fixedView.prototype.getVisibleAreaBounds = function (client) {
                var bounds = this._isNativeSuperPanel() ? wijmo.grid.bounds(this._getSuperPanelStateContainer(), client) : wijmo.grid.bounds(this._getSuperPanelContentWrapper(), client);

                if (!bounds) {
                    bounds = wijmo.grid.bounds(this._wijgrid.mOuterDiv, client);
                }

                return bounds;
            };

            fixedView.prototype.getVisibleContentAreaBounds = function () {
                var visibleBounds = this.getVisibleAreaBounds(true), b00 = wijmo.grid.bounds(this._viewTables.nw.element()) || {}, b01 = wijmo.grid.bounds(this._viewTables.ne.element()) || {}, b10 = wijmo.grid.bounds(this._viewTables.sw.element()) || {}, b11 = wijmo.grid.bounds(this._viewTables.se.element()) || {}, contentBounds = {
                    top: visibleBounds.top,
                    left: visibleBounds.left,
                    width: Math.max(b00.width + b01.width, b10.width + b11.width),
                    height: Math.max(b00.height + b10.height, b01.height + b11.height)
                };

                // truncate
                contentBounds.width = Math.min(visibleBounds.width, contentBounds.width);
                contentBounds.height = Math.min(visibleBounds.height, contentBounds.height);

                return contentBounds;
            };

            fixedView.prototype._getRowAreaHeight = function () {
                var container = this._getSuperPanelContentWrapper();
                if (container.length == 0) {
                    container = this._wijgrid.mOuterDiv;
                }
                var height = container.height();

                // subtract top fixed area
                var topFixedAreaHeight = this._wijgrid.mSplitDistanceY;
                if (topFixedAreaHeight) {
                    height -= topFixedAreaHeight;
                }

                // subtract footer height
                if (this._wijgrid.options.showFooter) {
                    var footer, footerHeight = (this.isRendered() && (footer = this.footerRow())) ? $(footer).height() : this.getDefaultRowHeight();

                    height -= footerHeight;
                }

                return height;
            };

            fixedView.prototype.getVirtualPageSize = function (upper) {
                if (typeof upper === "undefined") { upper = true; }
                var rowHeight = this._wijgrid.mRowOuterHeight && (this._wijgrid.mRowOuterHeight > 0) ? this._wijgrid.mRowOuterHeight : this.getDefaultRowHeight();

                var vPageSize = this._getRowAreaHeight() / rowHeight;

                return upper ? Math.ceil(vPageSize) : Math.floor(vPageSize);
            };

            fixedView.prototype.getFixedAreaVisibleBounds = function () {
                var bounds = this.getVisibleAreaBounds(), neBounds = wijmo.grid.bounds(this._splitAreas.ne), nwBounds = wijmo.grid.bounds(this._splitAreas.nw), horBounds = null, verBounds = null;

                if (neBounds.height || nwBounds.height) {
                    horBounds = {
                        left: bounds.left,
                        top: bounds.top,
                        width: bounds.width,
                        height: Math.min(neBounds.height || nwBounds.height, bounds.height)
                    };
                }

                if (nwBounds.width) {
                    verBounds = {
                        //left: bounds.left,
                        left: nwBounds.left,
                        top: bounds.top,
                        width: Math.min(nwBounds.width, bounds.width),
                        height: bounds.height
                    };
                }

                return [horBounds, verBounds];
            };

            fixedView.prototype.getDefaultRowHeight = function () {
                return this._wijgrid._lgGetRowHeight();
            };

            fixedView.prototype._refreshPanel = function (scrollValue) {
                var self = this, wijgrid = this._wijgrid, options = wijgrid.options, panelModes = this._getMappedScrollMode(), firstRow = wijgrid._rows().item(0), recreateSuperPanel = false, defCSS = wijmo.grid.wijgrid.CSS, neScrollableContent, seScrollableContent;

                wijgrid.mRowOuterHeight = firstRow && firstRow[0] ? $(firstRow[0]).outerHeight() : this.getDefaultRowHeight();

                //clear the marginleft , make sure wijsuperpanel can get the correct width when using the HVirtualScrolling.(#120224)
                if (this.mHVSOffset && this.mHVSOffset > 0) {
                    neScrollableContent = $(this._viewTables.ne.element()).closest("." + defCSS.scrollableContent)[0];
                    seScrollableContent = $(this._viewTables.se.element()).closest("." + defCSS.scrollableContent)[0];
                    neScrollableContent.style.marginLeft = "";
                    seScrollableContent.style.marginLeft = "";
                }

                if (!this._scroller.data("wijmo-wijsuperpanel")) {
                    recreateSuperPanel = true;

                    if (this._wijgrid._allowVirtualScrolling()) {
                        this.vsUI = new wijmo.grid.uiVirtualScroller(wijgrid, this._splitAreas.se, wijgrid.mSplitDistanceY, wijgrid.mRowOuterHeight);
                    }

                    if (scrollValue && (panelModes.hScrollBarVisibility === "hidden")) {
                        scrollValue.x = 0;
                    }

                    this._scroller.wijsuperpanel({
                        disabled: wijgrid.options.disabled,
                        scroll: $.proxy(this._onScroll, this),
                        bubbleScrollingEvent: true,
                        customScrolling: this._wijgrid._allowVVirtualScrolling(),
                        vScroller: { scrollBarVisibility: panelModes.vScrollBarVisibility, "scrollValue": scrollValue ? scrollValue.y : null },
                        hScroller: { scrollBarVisibility: panelModes.hScrollBarVisibility, "scrollValue": scrollValue ? scrollValue.x : null },
                        hScrollerActivating: $.proxy(this._onHScrollerActivating, this),
                        animationOptions: this._wijgrid._allowHVirtualScrolling() ? { disabled: true } : undefined
                    });

                    // wijsuperpanel.hScrollerActivating event is not raised if touch environment is used, simulate it.
                    if (this._isNativeSuperPanel()) {
                        var container = this._getSuperPanelStateContainer();
                        if (container.length && (container[0].offsetHeight !== container[0].clientHeight)) {
                            this._onHScrollerActivating(null, { contentLength: container[0].clientHeight });
                        }
                    }

                    if (!this._isNativeSuperPanel()) {
                        this._getSuperPanelContentWrapper().bind("scroll", function (e) {
                            // #50496: when a overflowing div contains focusable elements it will be scrolled automatically to fit the focused element into view.
                            // Prevent native scrolling to avoid disalignment of the fixed and unfixed areas in IE\ Chrome when partially visible cell gets focus.
                            e.target.scrollLeft = 0;
                            e.target.scrollTop = 0;

                            e.preventDefault();
                        });
                    }

                    if (this._wijgrid._allowVirtualScrolling()) {
                        this.vsUI.attach(this._scroller);
                    }
                } else {
                    this._scroller.wijsuperpanel("paintPanel");
                }

                if (!this._wijgrid._allowVirtualScrolling()) {
                    var totalRowsCount = this._splitAreas.se.find("table").find("tr").length, hScrollbarHeight = this._scroller.find('.wijmo-wijsuperpanel-hbarcontainer').height(), columnHeaderHeight = this._splitAreas.ne.height(), rowHeight = wijgrid.mRowOuterHeight, pagerHeight = (!wijgrid.mBottomPagerDiv ? 0 : wijgrid.mBottomPagerDiv.outerHeight()) + (!wijgrid.mTopPagerDiv ? 0 : wijgrid.mTopPagerDiv.outerHeight()), visibleRowsCount = (this._scroller.height() - columnHeaderHeight - hScrollbarHeight - pagerHeight) / rowHeight, largeChange = Math.floor(visibleRowsCount), smallChange = Math.floor(largeChange / 2), vScroller = this._scroller.wijsuperpanel("option", "vScroller");

                    vScroller.scrollLargeChange = largeChange;
                    vScroller.scrollSmallChange = smallChange;
                    vScroller.scrollMax = totalRowsCount;

                    if ($.browser.msie) {
                        this._scroller.wijsuperpanel("option", "keyDownInterval", Math.max(totalRowsCount / 5, 100));
                    }
                }

                var needVBar = this._testNeedVBar(wijgrid.mOuterDiv, wijgrid.element, $(this._viewTables.ne.element()), wijgrid._lgGetScrollMode(), wijgrid.mAutoHeight), excludeVBarWidth = needVBar && !this._testAutohiddenScrollbars();

                var contentWidth = this.getVisibleContentAreaBounds().width;
                this._splitAreas.ne.width(contentWidth - wijgrid.mSplitDistanceX);

                if (recreateSuperPanel && (scrollValue && scrollValue.x) && this._wijgrid.element.is(":visible")) {
                    // synchronize unfixed areas: NE and SE (#47277)
                    var hPxValue = this._scroller.wijsuperpanel("scrollValueToPx", scrollValue.x, "h");
                    this._setFixedAreaPosition(this._splitAreas.ne, "h", hPxValue, null, true);
                }

                if (wijgrid._lgGetStaticColumnsAlignment() === "right") {
                    this._splitAreas.nw.css({
                        "left": "",
                        "right": excludeVBarWidth ? this._verScrollBarSize : 0
                    });

                    this._splitAreas.sw.css({
                        "left": "",
                        "right": excludeVBarWidth ? this._verScrollBarSize : 0
                    });
                }

                this._scroller.find(".wijmo-wijsuperpanel-hbarcontainer, .wijmo-wijsuperpanel-vbarcontainer").css("zIndex", 5);

                if (this._wijgrid._allowVVirtualScrolling()) {
                    this._wijgrid._handleVerticalVirtualScrolling(this._bounds.start); // re-render
                }

                //Restore the marginleft.(#120224)
                if (neScrollableContent && seScrollableContent) {
                    neScrollableContent.style.marginLeft = this.mHVSOffset + "px";
                    seScrollableContent.style.marginLeft = this.mHVSOffset + "px";
                }
            };

            fixedView.prototype._getLeftOffset = function (column) {
                var offset = 0, leaves = this._wijgrid._leaves();

                for (var i = 0; i < leaves.length; i++) {
                    var leaf = leaves[i];

                    if (column.options._leavesIdx <= leaf.options._visLeavesIdx) {
                        break;
                    }

                    if (leaf._visible()) {
                        offset += leaf.options._realWidth;
                    }
                }

                return offset;
            };

            fixedView.prototype.scrollTo = function (cell, callback, info) {
                var grid = this._wijgrid, virtualRow = null, virtualColumn = null;

                if (grid._allowVVirtualScrolling()) {
                    var rowIndex = grid._renderableRowsRange().getRenderedIndex(cell.rowIndex()), vab, rowsLen = grid._rows().length(), $rows, handleLastRow = (rowIndex - grid._viewPortBounds().start >= rowsLen - 1);

                    // determine whether virtual scrolling is needed or not
                    if (!cell._isRowRendered() || (handleLastRow && (vab = this.getVisibleAreaBounds(true)) && ($rows = cell.row().$rows) && ($rows.offset().top + $rows.outerHeight() > vab.top + vab.height))) {
                        virtualRow = rowIndex;

                        if (cell.rowIndex() > info.changingEventArgs.oldRowIndex) {
                            virtualRow -= rowsLen - 1;
                            virtualRow += 1;
                        }
                    }
                }

                if (grid._allowHVirtualScrolling() && !cell._isRendered()) {
                    virtualColumn = cell.columnInst();
                }

                var superPanelObj = this._getSuperPanel();

                if (virtualRow !== null || virtualColumn) {
                    info.setFocus = true; // to listen key events
                    info.hasFocusedChild = false;
                }

                if (virtualRow !== null) {
                    if (superPanelObj) {
                        this.vsUI.scrollToRow(virtualRow, function () {
                            callback();
                        });
                    } else {
                        callback();
                    }
                } else {
                    var $tableCell = virtualColumn ? null : $(cell.tableCell()), resultLeft = null, resultTop = null;

                    if (superPanelObj && (virtualColumn || $tableCell.is(":visible"))) {
                        var content = superPanelObj.getContentElement(), wrapper = content.parent(), el, area, staticRowIndex = grid._getStaticIndex(true), staticColIndex = grid._getStaticIndex(false), currentRowIndex = cell.rowIndex(), currentCellIndex = cell.cellIndex();

                        if (this._isNativeSuperPanel()) {
                            if (virtualColumn) {
                                el = {
                                    left: this._getLeftOffset(virtualColumn), top: 0, height: 0, width: virtualColumn.options._realWidth
                                };
                            } else {
                                el = {
                                    left: $tableCell[0].offsetLeft,
                                    top: $tableCell[0].offsetTop,
                                    height: $tableCell.outerHeight(),
                                    width: $tableCell.outerWidth()
                                };
                            }

                            area = {
                                left: wrapper[0].scrollLeft,
                                top: wrapper[0].scrollTop,
                                height: wrapper[0].clientHeight - grid.mSplitDistanceY,
                                width: wrapper[0].clientWidth - grid.mSplitDistanceX
                            };
                        } else {
                            if (virtualColumn) {
                                el = {
                                    left: this._getLeftOffset(virtualColumn), top: 0, height: 0, width: virtualColumn.options._realWidth
                                };
                            } else {
                                var elementPosition = $tableCell.position();

                                el = {
                                    left: grid._allowHVirtualScrolling() ? this._getLeftOffset(cell.columnInst()) : elementPosition.left,
                                    top: elementPosition.top,
                                    height: $tableCell.outerHeight(),
                                    width: $tableCell.outerWidth()
                                };
                            }

                            area = {
                                left: -(parseInt((content.css("left") + "").replace("px", ""), 10) || 0),
                                top: -(parseInt((content.css("top") + "").replace("px", ""), 10) || 0),
                                height: wrapper.outerHeight() - grid.mSplitDistanceY,
                                width: wrapper.outerWidth() - grid.mSplitDistanceX
                            };
                        }

                        if (currentRowIndex <= staticRowIndex) {
                            if (currentCellIndex <= staticColIndex) {
                                //resultLeft = 0;
                                //resultTop = 0;
                                resultLeft = null; // fixed column - do not scroll horizontally
                                resultTop = null; // fixed row - do not scroll vertically
                            } else {
                                el.left += area.left;
                                if (el.left + el.width > area.left + area.width) {
                                    area.left = resultLeft = el.left + el.width - area.width;
                                }
                                if (el.left < area.left) {
                                    resultLeft = el.left;
                                }

                                //resultTop = 0;
                                resultTop = null; // fixed row - do not scroll vertically
                            }
                        } else {
                            if (currentCellIndex <= staticColIndex) {
                                // elementTop += visibleTop;
                                el.top += this._splitAreas.sw.scrollTop();

                                if (el.top + el.height > area.top + area.height) {
                                    area.top = resultTop = el.top + el.height - area.height;
                                }

                                if (el.top < area.top) {
                                    resultTop = el.top;
                                }

                                //resultLeft = 0;
                                resultLeft = null; // fixed column - do not scroll horizontally
                            } else {
                                el.left -= grid.mSplitDistanceX;
                                if (el.top + el.height > area.top + area.height) {
                                    area.top = resultTop = el.top + el.height - area.height;
                                }

                                if (el.left + el.width > area.left + area.width) {
                                    area.left = resultLeft = el.left + el.width - area.width;
                                }

                                if (el.top < area.top) {
                                    resultTop = el.top;
                                }

                                if (el.left < area.left) {
                                    resultLeft = el.left;
                                }
                            }
                        }

                        if (resultLeft !== null) {
                            resultTop = null;

                            if (virtualColumn) {
                                this.vsUI.scrollToColumn(virtualColumn, resultLeft, function () {
                                    callback();
                                });
                                return;
                            } else {
                                superPanelObj.hScrollTo(resultLeft);
                            }
                        }

                        if (resultTop !== null) {
                            superPanelObj.vScrollTo(resultTop);
                        }
                    }

                    callback();
                }
            };

            fixedView.prototype.updateSplits = function (scrollValue, rowsToAdjust) {
                var _this = this;
                var grid = this._wijgrid, minWidths = [], maxWidths = [], visibleLeaves = grid._visibleLeaves(), se = $(this._viewTables.se.element()), ne = $(this._viewTables.ne.element()), sw = $(this._viewTables.sw.element()), nw = $(this._viewTables.nw.element()), outerDiv = grid.mOuterDiv, hasDataRows = false, strictWidth = this._strictWidthMode(), live = this.isLiveUpdate(), defCSS = wijmo.grid.wijgrid.CSS;

                if (!live) {
                    this._destroySuperPanel();

                    outerDiv.unbind("mousewheel", this._mouseWheelHandler);

                    this._clearNorthTablesHeight();
                }

                // * if there is no data in a table, we must enlarge the table to prevent the width from being 0
                var tBody = (se[0].tBodies && se[0].tBodies[0]);
                if (tBody) {
                    for (var i = 0; i < tBody.rows.length; i++) {
                        if (!$(tBody.rows[i]).hasClass(wijmo.grid.wijgrid.CSS.groupHeaderRow)) {
                            hasDataRows = true;
                            break;
                        }
                    }

                    if (!hasDataRows) {
                        grid.element.css("width", "100%");
                    }
                }

                $.each([se, ne, sw, nw], function (index, table) {
                    table.css({ "table-layout": "", "width": "" });
                });

                $.each(visibleLeaves, function (index, leaf) {
                    if (leaf.options._realWidth !== undefined) {
                        _this._setColumnWidth(leaf, leaf.options._realWidth);
                    }

                    maxWidths.push(_this._getColumnWidth(index));
                });

                $.each([se, ne, sw, nw], function (index, table) {
                    table.css({ "width": "1px" });
                });

                $.each(visibleLeaves, function (index, leaf) {
                    minWidths.push(_this._getColumnWidth(index));
                });

                var viewAreaWidth = outerDiv.width();
                var resultWidths = this._adjustWidthArray(maxWidths, minWidths, viewAreaWidth, strictWidth);
                this._setResultWidth(resultWidths, viewAreaWidth, rowsToAdjust);

                //adjust width if showing vertical scrollbar
                if (this._testNeedVBar(grid.mOuterDiv, se, ne, grid._lgGetScrollMode(), grid.mAutoHeight)) {
                    var recalculate = false;

                    viewAreaWidth -= this._verScrollBarSize;

                    if (strictWidth) {
                        $.each(visibleLeaves, function (index, leaf) {
                            var opt = leaf.options;

                            if (wijmo.grid.isPercentage(opt.width)) {
                                maxWidths[index].width = minWidths[index].width = viewAreaWidth * parseFloat(opt.width) / 100;
                                recalculate = true;
                            }
                        });
                    } else {
                        recalculate = true;
                    }

                    if (recalculate) {
                        resultWidths = this._adjustWidthArray(maxWidths, minWidths, viewAreaWidth, strictWidth);
                        this._setResultWidth(resultWidths, viewAreaWidth, rowsToAdjust);
                    }
                }

                this._setNorthTablesHeight();

                if (this._wijgrid._allowHVirtualScrolling()) {
                    var totalScrollableWidth = this._sumWidthArray(resultWidths);
                    ne.closest("." + defCSS.scrollableContent).width(totalScrollableWidth - grid.mSplitDistanceX);
                    se.closest("." + defCSS.scrollableContent).width(totalScrollableWidth - grid.mSplitDistanceX);
                }

                if (!live) {
                    this._refreshPanel(scrollValue); // refresh super panel after width is set.
                    outerDiv.bind("mousewheel", $.proxy(this._mouseWheelHandler, this));
                }

                this.mResultWidths = resultWidths;
            };

            fixedView.prototype.updateSplitsLive = function () {
                var _this = this;
                var leaves = this._wijgrid._leaves(), visLeaves = this._wijgrid._visibleLeaves(), renderedColumnsWidth = 0;

                this.currentRenderableColumns().forEachIndex(function (i) {
                    var leaf = leaves[i];

                    if (leaf._isRendered()) {
                        var width = _this.mResultWidths[leaf.options._visLeavesIdx].width;

                        _this._setColumnWidth(leaf, width);

                        renderedColumnsWidth += width;
                    }
                });

                var ne = $(this._viewTables.ne.element()), se = $(this._viewTables.se.element()), last = this.mResultWidths.length - 1;

                this._setTableWidth([ne, se], renderedColumnsWidth, this.mResultWidths[last].width, visLeaves[last]);
                //var hPxValue = this._scroller.wijsuperpanel("scrollValueToPx", this._wijgrid.mScrollingState.x, "h");
                //this._setFixedAreaPosition(this._splitAreas.ne, "h", hPxValue, null, true);
            };

            fixedView.prototype._setResultWidth = function (resultWidths, viewAreaWidth, rowsToAdjust) {
                var _this = this;
                var grid = this._wijgrid, visLeaves = grid._visibleLeaves(), staticColumnIndex = this._staticColumnIndex, strictWidth = this._strictWidthMode(), expandIndex, sum, se = $(this._viewTables.se.element()), ne = $(this._viewTables.ne.element()), sw = $(this._viewTables.sw.element()), nw = $(this._viewTables.nw.element()), live = this.isLiveUpdate();

                $.each(resultWidths, function (index, colWidth) {
                    if (!colWidth.real || colWidth.realPercent) {
                        _this._setColumnWidth(visLeaves[index], colWidth.width);
                    }
                });

                if ((expandIndex = staticColumnIndex) >= 0) {
                    sum = this._sumWidthArray(resultWidths, 0, expandIndex);
                    this._setTableWidth([nw, sw], sum, resultWidths[expandIndex].width, visLeaves[expandIndex]);
                }

                if (!live) {
                    try  {
                        grid.mSplitDistanceX = staticColumnIndex >= 0 ? nw[0].offsetWidth : 0;
                    } catch (ex) {
                    }

                    this._updateSplitAreaBounds(0); //width
                }

                if (!strictWidth) {
                    this._splitAreas.ne.width(viewAreaWidth - grid.mSplitDistanceX);
                }

                if ((expandIndex = resultWidths.length - 1) >= 0) {
                    sum = this._sumWidthArray(resultWidths, staticColumnIndex + 1, expandIndex);
                    this._setTableWidth([ne, se], sum, resultWidths[expandIndex].width, visLeaves[expandIndex]);
                }

                if (!live) {
                    this._adjustRowsHeights(rowsToAdjust);

                    try  {
                        grid.mSplitDistanceY = this._staticRowIndex >= 0 ? Math.max(nw[0].offsetHeight, ne[0].offsetHeight) : 0;
                    } catch (ex) {
                    }

                    this._updateSplitAreaBounds(1); //height
                }
            };

            fixedView.prototype.getInlineTotalWidth = function () {
                if (this._scroller) {
                    var stateContainer = this._getSuperPanelStateContainer();

                    if (stateContainer.length) {
                        var width = stateContainer[0].style.width;

                        if (width && (width !== "auto")) {
                            return width;
                        }
                    }
                }

                return "";
            };

            // public **
            // ** DOMTable abstraction
            fixedView.prototype._clearBody = function () {
                _super.prototype._clearBody.call(this);
            };

            fixedView.prototype.bodyRows = function () {
                var accessor = _super.prototype.bodyRows.call(this);
                return accessor;
            };

            fixedView.prototype.forEachColumnCell = function (columnIndex, callback, param) {
                var joinedTables = this.getJoinedTables(true, columnIndex), relIdx, callbackRes;

                if (joinedTables[0] !== null) {
                    relIdx = joinedTables[2];
                    callbackRes = joinedTables[0].forEachColumnCell(relIdx, callback, param);
                    if (callbackRes !== true) {
                        return callbackRes;
                    }

                    if (joinedTables[1] !== null) {
                        callbackRes = joinedTables[1].forEachColumnCell(relIdx, callback, param);
                        if (callbackRes !== true) {
                            return callbackRes;
                        }
                    }
                }

                return true;
            };

            fixedView.prototype.forEachRowCell = function (rowIndex, callback, param) {
                var joinedTables = this.getJoinedTables(false, rowIndex), table0 = joinedTables[0], table1 = joinedTables[1], relIdx, callbackResult;

                if (table0 !== null) {
                    relIdx = joinedTables[2];
                    if (relIdx < table0.element().rows.length) {
                        callbackResult = table0.forEachRowCell(relIdx, callback, param);
                        if (callbackResult !== true) {
                            return callbackResult;
                        }
                    }

                    if ((table1 !== null) && (relIdx < table1.element().rows.length)) {
                        callbackResult = table1.forEachRowCell(relIdx, callback, param);
                        if (callbackResult !== true) {
                            return callbackResult;
                        }
                    }
                }

                return true;
            };

            fixedView.prototype.getAbsoluteCellInfo = function (domCell, virtualize) {
                return new wijmo.grid.cellInfo(this.getAbsoluteCellIndex(domCell), this.getAbsoluteRowIndex(domCell.parentNode), this._wijgrid, true, virtualize);
            };

            fixedView.prototype.getAbsoluteCellIndex = function (domCell) {
                var index = domCell.cellIndex, table = domCell.parentNode;

                while (table && table.tagName && table.tagName.toLowerCase() !== "table") {
                    table = table.parentNode;
                }

                //order by the hit probability.
                if (table === this._viewTables.se.element()) {
                    index = this._viewTables.se.getColumnIdx(domCell) + this._staticColumnIndex + 1;
                    return index;
                }

                if (table === this._viewTables.sw.element()) {
                    index = this._viewTables.sw.getColumnIdx(domCell);
                    return index;
                }

                if (table === this._viewTables.ne.element()) {
                    index = this._viewTables.ne.getColumnIdx(domCell) + this._staticColumnIndex + 1;
                    return index;
                }

                if (table === this._viewTables.nw.element()) {
                    index = this._viewTables.nw.getColumnIdx(domCell);
                    return index;
                }

                return index;
            };

            fixedView.prototype.getAbsoluteRowIndex = function (domRow) {
                var index = domRow.rowIndex, table = domRow.parentNode;

                while (table && table.tagName && table.tagName.toLowerCase() !== "table") {
                    table = table.parentNode;
                }

                return (table === this._viewTables.nw.element() || table === this._viewTables.ne.element()) ? index : index + this._staticRowIndex + 1;
            };

            fixedView.prototype.getCell = function (absColIdx, absRowIdx) {
                var joinedTablesRow = this.getJoinedTables(false, absRowIdx), joinedTablesCol, relRowIdx, relColIdx, table, cellIdx;

                if (joinedTablesRow[0] !== null) {
                    joinedTablesCol = this.getJoinedTables(true, absColIdx);
                    if (joinedTablesCol[0] !== null) {
                        relRowIdx = joinedTablesRow[2];
                        relColIdx = joinedTablesCol[2];

                        table = null;
                        if (joinedTablesRow[1] !== null) {
                            table = (absColIdx === relColIdx) ? joinedTablesRow[0] : joinedTablesRow[1];
                        } else {
                            table = joinedTablesRow[0];
                        }

                        cellIdx = table.getCellIdx(relColIdx, relRowIdx);
                        if (cellIdx >= 0) {
                            return table.element().rows[relRowIdx].cells[cellIdx];
                        }
                    }
                }

                return null;
            };

            fixedView.prototype.getColumnIndex = function (domCell) {
                var owner = null, htmlTable = null, flag = false, colIdx;

                for (owner = domCell.parentNode; owner.tagName.toLowerCase() !== "table"; owner = owner.parentNode) {
                }

                if (owner !== null) {
                    if (owner === this._viewTables.nw.element()) {
                        htmlTable = this._viewTables.nw;
                    } else {
                        if (owner === this._viewTables.ne.element()) {
                            htmlTable = this._viewTables.ne;
                            flag = true;
                        } else {
                            if (owner === this._viewTables.sw.element()) {
                                htmlTable = this._viewTables.sw;
                            } else {
                                if (owner === this._viewTables.se.element()) {
                                    htmlTable = this._viewTables.se;
                                    flag = true;
                                }
                            }
                        }
                    }

                    if (htmlTable !== null) {
                        colIdx = htmlTable.getColumnIdx(domCell);
                        if (flag) {
                            colIdx += this._staticColumnIndex + 1;
                        }

                        return this._wijgrid._renderedLeaves()[colIdx].options._visLeavesIdx;
                        //return colIdx;
                    }
                }

                return -1;
            };

            fixedView.prototype.getHeaderCell = function (absColIdx) {
                var leaf = this._wijgrid._visibleLeaves()[absColIdx], headerRow;

                if (leaf && (headerRow = this._wijgrid._headerRows())) {
                    return wijmo.grid.rowAccessor.getCell(headerRow.item(leaf.options._thY), leaf.options._thX);
                }

                return null;
            };

            fixedView.prototype.getJoinedCols = function (columnIndex) {
                var leaf = this._wijgrid._visibleLeaves()[columnIndex], result = [], joinedTables = this.getJoinedTables(true, leaf.options._renderedIndex), relIndex = joinedTables[2];

                joinedTables.splice(joinedTables.length - 1, 1);
                $.each(joinedTables, function (index, table) {
                    result.push(table ? $(table.element()).find("col")[relIndex] : null);
                });

                return result;
            };

            fixedView.prototype.getJoinedRows = function (rowIndex, rowScope) {
                var row0 = null, row1 = null, table0 = null, table1 = null, fixedRowIdx = this._staticRowIndex, fixedColIdx = this._staticColumnIndex, lastColIdx = this._wijgrid._visibleLeaves().length - 1, lastRowIdx = this._rowsCountRaw() - 1, allRowsFixed = (fixedRowIdx === lastRowIdx), allsRowUnfixed = (fixedRowIdx < 0), rowsFixedSlice = !allRowsFixed && !allsRowUnfixed, sectionLength = 0;

                if (allRowsFixed || rowsFixedSlice) {
                    if (fixedColIdx >= 0 && fixedColIdx < lastColIdx) {
                        table0 = this._viewTables.nw;
                        table1 = this._viewTables.ne;
                    } else {
                        table0 = (fixedColIdx < 0) ? this._viewTables.ne : this._viewTables.nw;
                    }
                    sectionLength = table0.getSectionLength(rowScope);
                    if (rowIndex < sectionLength) {
                        row0 = table0.getSectionRow(rowIndex, rowScope);
                        if (table1 !== null) {
                            row1 = table1.getSectionRow(rowIndex, rowScope);
                        }
                    }
                }

                if (allsRowUnfixed || (rowsFixedSlice && (row0 === null))) {
                    if (!allsRowUnfixed) {
                        rowIndex -= sectionLength;
                    }

                    if (fixedColIdx >= 0 && fixedColIdx < lastColIdx) {
                        table0 = this._viewTables.sw;
                        table1 = this._viewTables.se;
                    } else {
                        table0 = (fixedColIdx < 0) ? this._viewTables.se : this._viewTables.sw;
                    }

                    row0 = table0.getSectionRow(rowIndex, rowScope);

                    if (table1 !== null) {
                        row1 = table1.getSectionRow(rowIndex, rowScope);
                    }
                }

                return (row0 === null && row1 === null) ? null : [row0, row1];
            };

            fixedView.prototype.getJoinedTables = function (byColumn, index) {
                var t0 = null, t1 = null, idx = index, wijgrid = this._wijgrid, fixedRowIdx = this._staticRowIndex, fixedColIdx = this._staticColumnIndex;

                if (byColumn) {
                    if (index <= fixedColIdx) {
                        t0 = this._viewTables.nw;
                        t1 = this._viewTables.sw;
                    } else {
                        t0 = this._viewTables.ne;
                        t1 = this._viewTables.se;

                        idx = idx - (fixedColIdx + 1);
                    }

                    if (fixedRowIdx < 0) {
                        t0 = null;
                    }

                    if (fixedRowIdx === this._rowsCountRaw() - 1) {
                        t1 = null;
                    }
                } else {
                    if (index <= fixedRowIdx) {
                        t0 = this._viewTables.nw;
                        t1 = this._viewTables.ne;
                    } else {
                        t0 = this._viewTables.sw;
                        t1 = this._viewTables.se;

                        idx = idx - (fixedRowIdx + 1);
                    }

                    if (fixedColIdx < 0) {
                        t0 = null;
                    }
                    if (fixedColIdx === wijgrid._leaves().length - 1) {
                        t1 = null;
                    }
                }

                if (t0 === null) {
                    t0 = t1;
                    t1 = null;
                }
                return [t0, t1, idx];
            };

            fixedView.prototype.subTables = function () {
                return [this._viewTables.nw, this._viewTables.ne, this._viewTables.sw, this._viewTables.se];
            };

            // DOMTable abstraction **
            // ** private abstract
            fixedView.prototype._getSuperPanel = function () {
                return this._scroller ? this._scroller.data("wijmo-wijsuperpanel") : null;
            };

            // ** render
            fixedView.prototype._ensureRenderHBounds = function () {
                if (this._wijgrid._allowHVirtualScrolling()) {
                    var renderableColumns = this._wijgrid._renderableColumnsRange();

                    // update global range and calculate left offset
                    this.mHVSOffset = this._getRenderableColumnsBounds(renderableColumns, this._wijgrid.mScrollingState.scrollLeft);

                    // set current range
                    if (this.isLiveUpdate()) {
                        var currentRenderable = new _grid.renderableColumnsCollection();
                        currentRenderable.add(renderableColumns.item(1)); // scrollable (horizontal) area only, ne+se
                        this.currentRenderableColumns(currentRenderable);
                    } else {
                        this.currentRenderableColumns(renderableColumns);
                    }
                } else {
                    _super.prototype._ensureRenderHBounds.call(this); // render all columns
                }
            };

            fixedView.prototype._getRenderableColumnsBounds = function (range, offset) {
                var staticLeafIdx = this._staticAllColumnIndex, fix = { start: -1, end: -1 }, scroll = { start: -1, end: -1 };

                range.clear();
                range.add(fix);
                range.add(scroll);

                if (staticLeafIdx >= 0) {
                    fix.start = 0;
                    fix.end = staticLeafIdx;
                }

                var leaves = this._wijgrid._leaves(), startIdxFound = false, offsetLeft = 0, scrollableAreaWidth = this.getVisibleAreaBounds(true).width, colTotalWidth = 0;

                if (staticLeafIdx >= 0) {
                    for (var i = 0; i <= staticLeafIdx; i++) {
                        var leaf = leaves[i];

                        if (leaf._visible()) {
                            scrollableAreaWidth -= leaf.options._realWidth;
                        }
                    }
                }

                for (var i = staticLeafIdx + 1; i < leaves.length; i++) {
                    var leaf = leaves[i];

                    if (leaf._visible()) {
                        var width = leaves[i].options._realWidth;

                        colTotalWidth += width;

                        if (colTotalWidth <= offset) {
                            offsetLeft = colTotalWidth;
                        }

                        if (!startIdxFound) {
                            if (colTotalWidth - offset > 0) {
                                scroll.start = i;
                                startIdxFound = true;
                            }
                        } else {
                            //if (colTotalWidth - offset >= scrollableAreaWidth) { // overflow, stop
                            //	scroll.end = i;
                            //	break;
                            //}
                            scroll.end = i;
                            if (colTotalWidth - offset >= scrollableAreaWidth) {
                                break;
                            }
                        }
                    }
                }

                if (scroll.end < scroll.start) {
                    scroll.end = scroll.start;
                }

                return offsetLeft;
            };

            fixedView.prototype._ensureRenderBounds = function () {
                if (this._wijgrid._allowVVirtualScrolling()) {
                    var virtualPageSize = this.getVirtualPageSize(), b = this._bounds;

                    this._wijgrid._ensureRenderableBounds(b);

                    b.end = b.start + virtualPageSize - 1;

                    if (this._wijgrid._serverSideVirtualScrolling()) {
                        var delta = (b.end - b.start + 1) - this._wijgrid.mSketchTable.count();

                        if (delta > 0) {
                            b.end -= delta;
                        }
                    } else {
                        if (this._wijgrid.mRenderCounter == 0) {
                            b.end = b.start; // render a single row, just to calculate a real height.
                        } else {
                            this._wijgrid._ensureRenderableBounds(b);

                            if (this._isLastItemRendered()) {
                                virtualPageSize = this.getVirtualPageSize(false); // use floor, don't overlap a visible area
                            }

                            var num = Math.max(Math.min(this._wijgrid._renderableRowsCount(), virtualPageSize), 0), delta = num - (b.end - b.start + 1);

                            if (delta > 0) {
                                b.start = b.start - delta;
                            }
                        }
                    }

                    this._wijgrid._ensureRenderableBounds(b);

                    if (this._isLastItemRendered()) {
                        if (this._canRenderMoreItems()) {
                            virtualPageSize = this.getVirtualPageSize(false); // use floor, don't overlap a visible area
                            b.start = b.end - virtualPageSize + 1; // adjust the start position to stick the items to the bottom
                        }

                        this._wijgrid._ensureRenderableBounds(b);

                        if (b.start !== this._wijgrid.mScrollingState.index) {
                            this._wijgrid.mScrollingState.index = this._wijgrid.mScrollingState.y = b.start; //
                        }
                    }
                } else {
                    _super.prototype._ensureRenderBounds.call(this); // render all items
                }
            };

            fixedView.prototype._isLastItemRendered = function () {
                return (this._bounds.start > 0) && (this._bounds.end === this._wijgrid.mSketchTable.count() - 1);
            };

            fixedView.prototype._canRenderMoreItems = function () {
                var virtualPageSize = this.getVirtualPageSize(false), itemsToRender = this._bounds.end - this._bounds.start + 1;

                return itemsToRender < virtualPageSize;
            };

            fixedView.prototype._preRender = function () {
                _super.prototype._preRender.call(this);

                var defCSS = wijmo.grid.wijgrid.CSS;

                if (this.isLiveUpdate()) {
                    // clear scrollable (horizontal) sections
                    this._viewTables.ne.clearContent();
                    this._viewTables.se.clearContent();

                    // set offset to wijmo-wijgrid-scrollable-content elements.
                    $(this._viewTables.ne.element()).closest("." + defCSS.scrollableContent)[0].style.marginLeft = this.mHVSOffset + "px";
                    $(this._viewTables.se.element()).closest("." + defCSS.scrollableContent)[0].style.marginLeft = this.mHVSOffset + "px";
                } else {
                    var docFragment = document.createDocumentFragment(), HTA = wijmo.grid.htmlTableAccessor, wijCSS = this._wijgrid.options.wijCSS;

                    this._wijgrid.mOuterDiv.wrapInner("<div class=\"" + defCSS.fixedView + " " + wijCSS.wijgridFixedView + "\"><div class=\"" + defCSS.scroller + " " + wijCSS.wijgridScroller + "\"><div class=\"wijmo-wijgrid-split-area-se wijmo-wijgrid-content-area\"></div></div></div>");
                    this._scroller = this._wijgrid.mOuterDiv.find("." + defCSS.scroller);
                    this._scroller.css("padding", 0); // disable padding (inherited)

                    this._scroller.after(this._splitAreas.nw = $("<div class=\"wijmo-wijgrid-split-area wijmo-wijgrid-split-area-nw\" style=\"overflow:hidden;position:absolute;z-index:4;top:0px;left:0px;\"></div>"));
                    this._scroller.after(this._splitAreas.ne = $("<div class=\"wijmo-wijgrid-split-area wijmo-wijgrid-split-area-ne\" style=\"overflow:hidden;position:absolute;z-index:4;top:0px;left:0px;\"></div>"));
                    this._scroller.after(this._splitAreas.sw = $("<div class=\"wijmo-wijgrid-split-area wijmo-wijgrid-split-area-sw\" style=\"overflow:hidden;position:absolute;z-index:4;top:0px;left:0px;\"></div>"));
                    this._splitAreas.se = this._scroller.find(".wijmo-wijgrid-split-area-se:first");

                    this._viewTables = {
                        nw: new HTA(docFragment.appendChild(document.createElement("table")), true, true, true),
                        ne: new HTA(docFragment.appendChild(document.createElement("table")), true, true, true),
                        sw: new HTA(docFragment.appendChild(document.createElement("table")), true, true, true),
                        se: new HTA(docFragment.appendChild(this._wijgrid.element[0]), true, true, true)
                    };

                    var vT = this._viewTables, sw = vT.sw.element(), se = vT.se.element(), nw = vT.nw.element(), ne = vT.ne.element(), allowVirtualHScrolling = this._wijgrid._allowHVirtualScrolling(), defCSS = wijmo.grid.wijgrid.CSS;
                    this._splitAreas.nw.empty().append(nw);
                    if (allowVirtualHScrolling) {
                        this._splitAreas.ne.empty().append($("<div class=\"" + defCSS.scrollableContent + "\"></div>").append(ne));
                    } else {
                        this._splitAreas.ne.empty().append(ne);
                    }
                    this._splitAreas.sw.empty().append(sw);
                    if (allowVirtualHScrolling) {
                        this._splitAreas.se.empty().append($("<div class=\"" + defCSS.scrollableContent + "\"></div>").append(se));
                    } else {
                        this._splitAreas.se.empty().append(se);
                    }
                }
            };

            fixedView.prototype._postRender = function () {
                var t10 = this._viewTables.sw.element(), t11 = this._viewTables.se.element(), leftRows = t10.rows, rightRows = t11.rows;

                if (!this.isLiveUpdate()) {
                    var t00 = this._viewTables.nw.element(), t01 = this._viewTables.ne.element(), HTA = wijmo.grid.htmlTableAccessor, allowVirtualHScrolling = this._wijgrid._allowHVirtualScrolling(), defCSS = wijmo.grid.wijgrid.CSS, self = this;

                    this._viewTables = {
                        nw: new HTA(t00),
                        ne: new HTA(t01),
                        sw: new HTA(t10),
                        se: new HTA(t11)
                    };

                    $.each(this._viewTables, function (idx, hta) {
                        var $element = $(hta.element());

                        self._wijgrid._setAttr($element, {
                            role: "grid",
                            border: "0",
                            cellpadding: "0",
                            cellspacing: "0"
                        });

                        $element.addClass(wijmo.grid.wijgrid.CSS.table).addClass(self._wijgrid.options.wijCSS.wijgridTable).css("border-collapse", "separate").find("> tbody").addClass(self._wijgrid.options.wijCSS.content);
                    });

                    this._setNorthTablesHeight();
                } else {
                    this._rebuildOffsets();
                }

                if (leftRows != null && rightRows != null && leftRows.length > 0 && rightRows.length > 0 && leftRows[0].offsetHeight !== rightRows[0].offsetHeight) {
                    this._adjustRowsHeights();
                }

                _super.prototype._postRender.call(this);
            };

            fixedView.prototype._setNorthTablesHeight = function () {
                $(this._viewTables.ne.element()).height("100%");
                $(this._viewTables.nw.element()).height("100%");
            };

            fixedView.prototype._clearNorthTablesHeight = function (clearRows) {
                if (typeof clearRows === "undefined") { clearRows = false; }
                var tables = $([this._viewTables.ne.element(), this._viewTables.nw.element()]);

                tables.height("");

                if (clearRows) {
                    tables.find("> thead > tr").height("");
                }
            };

            fixedView.prototype._rowsCountRaw = function () {
                var t00 = this._viewTables.nw.element(), t01 = this._viewTables.ne.element(), t10 = this._viewTables.sw.element(), t11 = this._viewTables.se.element(), res;

                res = Math.max(t00.rows.length, t01.rows.length) + Math.max(t10.rows.length, t11.rows.length);

                return res;
            };

            fixedView.prototype._createCol = function (column, visibleIdx) {
                return [
                    document.createElement("col"),
                    document.createElement("col")
                ];
            };

            fixedView.prototype._appendCol = function (domCol, column, visibleIdx) {
                if (visibleIdx <= this._staticColumnIndex) {
                    this._viewTables.nw.appendCol(domCol[0]);
                    this._viewTables.sw.appendCol(domCol[1]);
                } else {
                    this._viewTables.ne.appendCol(domCol[0]);
                    this._viewTables.se.appendCol(domCol[1]);
                }
            };

            fixedView.prototype._insertRow = function (rowType, sectionRowIndex, domRow /* optional, used by c1gridview to clone rows of the original table */ ) {
                var $rt = wijmo.grid.rowType, leftSection, rightSection, vt = this._viewTables;

                switch (rowType) {
                    case 1 /* header */:
                    case 8 /* filter */:
                        leftSection = vt.nw.ensureTHead();
                        rightSection = vt.ne.ensureTHead();
                        break;

                    case 64 /* footer */:
                        leftSection = vt.sw.ensureTFoot();
                        rightSection = vt.se.ensureTFoot();
                        break;

                    default:
                        if (sectionRowIndex <= this._staticDataRowIndex) {
                            leftSection = vt.nw.ensureTBody();
                            rightSection = vt.ne.ensureTBody();
                        } else {
                            sectionRowIndex -= this._staticDataRowIndex + 1; // subtracts fixed offset
                            leftSection = vt.sw.ensureTBody();
                            rightSection = vt.se.ensureTBody();
                        }
                }

                if (domRow) {
                    // append only
                    return [
                        leftSection.appendChild(domRow),
                        rightSection.appendChild(domRow.cloneNode(false))
                    ];
                } else {
                    return [
                        leftSection.insertRow(sectionRowIndex > leftSection.rows.length ? -1 : sectionRowIndex),
                        rightSection.insertRow(sectionRowIndex > rightSection.rows.length ? -1 : sectionRowIndex)
                    ];
                }
            };

            fixedView.prototype._rowRendered = function (rowInfo, rowAttr, rowStyle) {
                var leftRow = rowInfo.$rows[0], rightRow = rowInfo.$rows[1], liveUpdate = this.isLiveUpdate();

                // Do not remove empty rows from header. The number of header rows in the fixed and unfixed tables should be the same to handle unbanded columns headers correctly when the staticSolumnIndex option is used:
                //
                // row0 |   band  | |  col2  | (rowSpan = 2)
                //      |---------| |--------|
                // row1 |col0|col1| |        | <- empty row
                if (!leftRow.cells.length && (this._isBodyRow(rowInfo) || liveUpdate)) {
                    leftRow.parentNode.removeChild(leftRow);
                    leftRow = null;
                }

                if (!rightRow.cells.length && this._isBodyRow(rowInfo)) {
                    rightRow.parentNode.removeChild(rightRow);
                    rightRow = null;
                }

                if (leftRow || rightRow) {
                    if (!leftRow || !rightRow) {
                        rowInfo.$rows = leftRow ? $(leftRow) : $(rightRow);
                    }

                    if (this.mRowsHeights.length) {
                        // use results of the previous _adjustRowsHeights' call here instead of calling the _adjustRowsHeights itself later (to improve performance).
                        var globIdx = rowInfo.sectionRowIndex;

                        if (rowInfo.type === 64 /* footer */) {
                            globIdx = this.mRowsHeights.length - 1;
                        } else if (!(rowInfo.type === 1 /* header */ || rowInfo.type === 8 /* filter */)) {
                            globIdx += this._wijgrid._columnsHeadersTable().length; // skip header rows
                            globIdx += this._wijgrid.options.showFilter ? 1 : 0;
                        }

                        if (this.mRowsHeights[globIdx]) {
                            this._setRowHeight(rowInfo.$rows, this.mRowsHeights[globIdx]);
                        }
                    }

                    _super.prototype._rowRendered.call(this, rowInfo, rowAttr, rowStyle);
                }
            };

            fixedView.prototype._appendCell = function (rowInfo, cellIndex, $cell) {
                if (cellIndex <= this._staticAllColumnIndex) {
                    rowInfo.$rows[0].appendChild($cell[0]);
                } else {
                    rowInfo.$rows[1].appendChild($cell[0]);
                }
            };

            // render **
            fixedView.prototype._getRowHeight = function (rowObj, ignoreSpannedCells) {
                if (rowObj[0] && rowObj[1]) {
                    var lRow = rowObj[0], rRow = rowObj[1], $lRow = $(lRow), $rRow = $(rRow), lRowH, rRowH, customHeight, getRowHeightUsingUnspannedCells = function ($row) {
                        var i, domRow = $row[0], domCell;

                        for (i = 0; i < domRow.cells.length; i++) {
                            domCell = domRow.cells[i];

                            if (!domCell.rowSpan || domCell.rowSpan === 1) {
                                return $(domCell).outerHeight();
                            }
                        }
                        ;

                        return $row.height();
                    };

                    if (customHeight = $.data(lRow, "customHeight")) {
                        lRowH = rRowH = parseInt(customHeight);
                    } else {
                        $lRow.css("height", "");
                        $rRow.css("height", "");

                        if (ignoreSpannedCells) {
                            lRowH = getRowHeightUsingUnspannedCells($lRow);
                            rRowH = getRowHeightUsingUnspannedCells($rRow);
                        } else {
                            lRowH = $lRow.height();
                            rRowH = $rRow.height();
                        }
                    }

                    return Math.max(lRowH, rRowH);
                }

                return null;
            };

            fixedView.prototype._setRowHeight = function (rowObj, maxHeight) {
                var isLiveUpdate = this.isLiveUpdate();

                if (rowObj[0] && (maxHeight || maxHeight === 0)) {
                    if (rowObj[1] || isLiveUpdate) {
                        var row = wijmo.grid.rowObjToJQuery(rowObj);

                        maxHeight += 1;

                        for (var i = 0; i < row.length; i++) {
                            var el = $(row[i]);

                            el.height(maxHeight);

                            if (!isLiveUpdate) {
                                var dif = maxHeight - el.height();
                                if (dif) {
                                    el.height(maxHeight + dif);
                                }
                            }
                        }
                    }
                }
            };

            fixedView.prototype._adjustRowHeight = function (bodyRowsToAdjust) {
                var wijgrid = this._wijgrid, fixedColIdx = this._staticColumnIndex, lastColIdx = wijgrid._visibleLeaves().length - 1;

                this.resetRowsHeightsCache();

                // setting row height only if grid is divided into leftern and rightern parts
                if (fixedColIdx > -1 && fixedColIdx < lastColIdx) {
                    var tableNE = this._viewTables.ne.element(), tableNEParent = tableNE.parentNode, talbeNEParentScrollLeft, tableNW = this._viewTables.nw.element(), tableNWParent = tableNW.parentNode, tableSE = this._viewTables.se.element(), tableSEParent = tableSE.parentNode, tableSW = this._viewTables.sw.element(), tableSWParent = tableSW.parentNode, leftRows, rightRows, fixedRowIdx = this._staticRowIndex, lastRowIdx = this._rowsCountRaw() - 1;

                    var totalRows = Math.max(Math.max(tableNE.rows.length, tableSE.rows.length), Math.max(tableNW.rows.length, tableSW.rows.length));

                    if (bodyRowsToAdjust && (bodyRowsToAdjust.r2 - bodyRowsToAdjust.r1 + 1 > totalRows * 0.9)) {
                        bodyRowsToAdjust = null; // adjust all rows if bodyRowsToAdjust takes over 90% of all of the rows (to reduce overhead of getting joined rows).
                    }

                    if (bodyRowsToAdjust) {
                        for (i = bodyRowsToAdjust.r1; i <= bodyRowsToAdjust.r2; i++) {
                            this.mRowsHeights.push(this._getRowHeight(this.getJoinedRows(i, 2 /* body */)));
                        }
                    } else {
                        // getting the height of northern tables
                        if (fixedRowIdx > -1 && fixedRowIdx <= lastRowIdx) {
                            leftRows = tableNW.rows;
                            rightRows = tableNE.rows;

                            for (var i = 0, len = leftRows.length; i < len; i++) {
                                this.mRowsHeights.push(this._getRowHeight([leftRows[i], rightRows[i]], true)); // row height will be calculated using unspanned cells (TFS issue #33399).
                            }
                        }

                        // getting the height of southern tables
                        if (fixedRowIdx >= -1 && fixedRowIdx < lastRowIdx) {
                            leftRows = tableSW.rows;
                            rightRows = tableSE.rows;

                            for (var i = 0, len = leftRows.length; i < len; i++) {
                                this.mRowsHeights.push(this._getRowHeight([leftRows[i], rightRows[i]]));
                            }
                        }
                    }

                    // removing elments from dom to improve performance
                    if (fixedRowIdx > -1 && fixedRowIdx <= lastRowIdx) {
                        tableNWParent.removeChild(tableNW);
                        talbeNEParentScrollLeft = tableNEParent.scrollLeft; // store value, because property will be reset on child collection changes
                        tableNEParent.style.visibility = "hidden"; // to avoid flickering in IE when scrollLeft property will be restored.
                        tableNEParent.removeChild(tableNE);
                    }
                    if (fixedRowIdx >= -1 && fixedRowIdx < lastRowIdx) {
                        tableSWParent.removeChild(tableSW);
                        tableSEParent.removeChild(tableSE);
                    }

                    if (bodyRowsToAdjust) {
                        var j = 0;

                        for (var i = bodyRowsToAdjust.r1; i <= bodyRowsToAdjust.r2; i++, j++) {
                            this._setRowHeight(this.getJoinedRows(i, 2 /* body */), this.mRowsHeights[j]);
                        }
                    } else {
                        var j = 0;

                        // setting the height of northern tables
                        if (fixedRowIdx > -1 && fixedRowIdx <= lastRowIdx) {
                            leftRows = tableNW.rows;
                            rightRows = tableNE.rows;

                            for (var i = 0, len = leftRows.length, j = 0; i < len; i++, j++) {
                                this._setRowHeight([leftRows[i], rightRows[i]], this.mRowsHeights[j]);
                            }
                        }

                        // setting the height of southern tables
                        if (fixedRowIdx >= -1 && fixedRowIdx < lastRowIdx) {
                            leftRows = tableSW.rows;
                            rightRows = tableSE.rows;

                            for (var i = 0, len = leftRows.length; i < len; i++) {
                                this._setRowHeight([leftRows[i], rightRows[i]], this.mRowsHeights[j++]);
                            }
                        }
                    }

                    // adding elments back to dom to improve performance
                    if (fixedRowIdx > -1 && fixedRowIdx <= lastRowIdx) {
                        tableNWParent.appendChild(tableNW);
                        tableNEParent.appendChild(tableNE);

                        if (talbeNEParentScrollLeft) {
                            tableNEParent.scrollLeft = talbeNEParentScrollLeft;
                        }

                        tableNEParent.style.visibility = "visible";
                    }

                    if (fixedRowIdx >= -1 && fixedRowIdx < lastRowIdx) {
                        tableSWParent.appendChild(tableSW);
                        tableSEParent.appendChild(tableSE);
                    }
                }
            };

            // private abstract **
            // ** private specific
            fixedView.prototype._adjustRowsHeights = function (rowsToAdjust) {
                var $tableSW = $(this._viewTables.sw.element()), $tableSE = $(this._viewTables.se.element()), height;

                $tableSE.css("height", "");
                $tableSW.css("height", "");

                this._adjustRowHeight(rowsToAdjust);

                height = Math.max($tableSE.height(), $tableSW.height());

                $tableSW.height(height);
                $tableSE.height(height);
            };

            fixedView.prototype._destroySuperPanel = function () {
                if (this._scroller.data("wijmo-wijsuperpanel")) {
                    if (this.vsUI) {
                        this.vsUI.dispose();
                    }

                    this._superPanelElementsCache = {};
                    this._scroller.wijsuperpanel("destroy");
                }
            };

            fixedView.prototype._onScroll = function (e, data) {
                var spInstance = this._getSuperPanel();

                if (this._wijgrid._allowVVirtualScrolling()) {
                    if (data.dir === "h") {
                        // do horizontal scrolling
                        this._setFixedAreaPosition(spInstance.getContentElement(), data.dir, data.position, data.animationOptions, false);
                        this._setFixedAreaPosition(this._splitAreas.ne, data.dir, data.position, data.animationOptions, true);
                    }
                } else {
                    this._setFixedAreaPosition(data.dir === "h" ? this._splitAreas.ne : this._splitAreas.sw, data.dir, data.position, data.animationOptions, true);
                }

                this._wijgrid._trackScrollingPosition(spInstance.options.hScroller.scrollValue, spInstance.options.vScroller.scrollValue, data.dir === "h" ? data.position : null);
            };

            fixedView.prototype._onHScrollerActivating = function (e, args) {
                // auto adjusting height with hscrollbar shown
                if (this._wijgrid.mAutoHeight) {
                    var diff = this._wijgrid.element.height() + this._wijgrid.mSplitDistanceY - args.contentLength;
                    if (diff > 0) {
                        this._scroller.height(this._scroller.height() + diff);
                        this._scroller.wijsuperpanel("paintPanel");
                        return false;
                    }
                }

                this._splitAreas.sw.height(args.contentLength - this._wijgrid.mSplitDistanceY);
            };

            fixedView.prototype._onMouseWheel = function (e, delta) {
                // force superpanel to do scrolling when cursor is placed over then non-scrollable (fixed) areas of the wijgrid.
                var bounds, dir = (delta > 0) ? "top" : "bottom", isOverFixedArea = false, vPos;

                if (this._wijgrid._canInteract()) {
                    bounds = this.getFixedAreaVisibleBounds(); // an array (horizonta area, verticalw area)

                    $.each(bounds, function (i, o) {
                        if (o && wijmo.grid.isOver(e.pageY, e.pageX, o.top, o.left, o.height, o.width)) {
                            isOverFixedArea = true;
                            return false;
                        }
                    });

                    if (isOverFixedArea && this._scroller.data("wijmo-wijsuperpanel")) {
                        vPos = this._scroller.wijsuperpanel("option", "vScroller").scrollValue;

                        this._scroller.wijsuperpanel("doScrolling", dir);

                        // simulate wijsuperpanel behaviour: prevent window scrolling until superpanel is not scrolled to the end.
                        if (vPos !== this._scroller.wijsuperpanel("option", "vScroller").scrollValue) {
                            e.stopPropagation();
                            e.preventDefault();
                        }
                    }
                }
            };

            fixedView.prototype._setFixedAreaPosition = function (element, direction, position, animation, useScrollProp) {
                var prop = {}, key;

                if (direction === "h") {
                    key = useScrollProp ? "scrollLeft" : "left";
                } else {
                    key = useScrollProp ? "scrollTop" : "top";
                }

                if (!useScrollProp) {
                    position = -position; // invert
                }

                if (animation) {
                    prop[key] = position;
                    element.animate(prop, animation);
                } else {
                    if (useScrollProp) {
                        element[0][key] = position;
                    } else {
                        element.css(key, position);
                    }
                }
            };

            fixedView.prototype._testNeedVBar = function (outerDiv, gridElement, tableNE, mode, autoHeight) {
                var excludeVBarWidth = false, wijgrid = this._wijgrid, gridWidth = tableNE.width() + wijgrid.mSplitDistanceX, gridHeight = gridElement.height() + wijgrid.mSplitDistanceY, outerWidth = outerDiv.width(), outerHeight = outerDiv.height(), contentHeight, topHeight = 0, bottomHeight = 0;

                if (wijgrid.mSuperPanelHeader !== null) {
                    topHeight = wijgrid.mSuperPanelHeader.outerHeight(true);
                }

                if (wijgrid.mBottomPagerDiv !== null) {
                    bottomHeight = wijgrid.mBottomPagerDiv.outerHeight(true);
                }

                contentHeight = outerHeight - topHeight - bottomHeight;

                switch (mode) {
                    case "both":
                    case "vertical":
                        excludeVBarWidth = true;
                        break;

                    case "auto":
                        // When the height needs to be auto adjusted, the vertical scrollbar should not be shown
                        excludeVBarWidth = (gridHeight > contentHeight) || (!autoHeight && gridWidth > outerWidth && gridHeight > contentHeight - this._verScrollBarSize);

                        if (!excludeVBarWidth && this._wijgrid._allowVVirtualScrolling()) {
                            var itemsToRender = wijgrid._view().getVirtualPageSize();

                            //itemsToRender = this._bounds.end - this._bounds.start;
                            excludeVBarWidth = (itemsToRender > 0 && itemsToRender < wijgrid._totalRowsCount());
                        }

                        break;
                }

                return excludeVBarWidth;
            };

            //bSet: 0-width, 1-height, 2-all
            fixedView.prototype._updateSplitAreaBounds = function (bSet) {
                var wijgrid = this._wijgrid, controlHeight, contentHeight, topHeight = 0, bottomHeight = 0, controlRect;

                if (bSet === 0 || bSet === 2) {
                    this._splitAreas.nw.width(wijgrid.mSplitDistanceX);
                    this._splitAreas.sw.width(wijgrid.mSplitDistanceX);

                    if (wijgrid._lgGetStaticColumnsAlignment() === "right") {
                        this._splitAreas.se.css("marginRight", wijgrid.mSplitDistanceX);
                        this._splitAreas.ne.css("marginRight", wijgrid.mSplitDistanceX);
                    } else {
                        this._splitAreas.se.css("marginLeft", wijgrid.mSplitDistanceX);
                        this._splitAreas.ne.css("marginLeft", wijgrid.mSplitDistanceX);
                    }
                }

                if (bSet === 1 || bSet === 2) {
                    this._scroller.css("height", "");
                    this._splitAreas.se.css("marginTop", 0);

                    controlRect = wijgrid.mOuterDiv[0].getBoundingClientRect();
                    controlHeight = Math.ceil(controlRect.height || (controlRect.bottom - controlRect.top));

                    if (!wijgrid.mAutoHeight) {
                        this._scroller.height(controlHeight);
                    } else {
                        // no height is set for outer div, we need to expand the grid.
                        this._scroller.height(controlHeight + wijgrid.mSplitDistanceY);
                        //this._noHeight = true;
                    }

                    this._splitAreas.nw.height(wijgrid.mSplitDistanceY);
                    this._splitAreas.ne.height(wijgrid.mSplitDistanceY);

                    if (wijgrid.mSuperPanelHeader !== null) {
                        topHeight = wijgrid.mSuperPanelHeader.outerHeight(true);
                    }
                    if (wijgrid.mBottomPagerDiv !== null) {
                        bottomHeight = wijgrid.mBottomPagerDiv.outerHeight(true);
                    }
                    contentHeight = controlHeight - topHeight - bottomHeight;

                    if (wijgrid.mSuperPanelHeader !== null) {
                        this._splitAreas.nw.css("top", topHeight + "px");
                        this._splitAreas.ne.css("top", topHeight + "px");
                    }

                    if (!wijgrid.mAutoHeight) {
                        this._splitAreas.sw.height(contentHeight - wijgrid.mSplitDistanceY);
                    } else {
                        this._splitAreas.sw.height(contentHeight);
                    }

                    this._splitAreas.sw.css("top", wijgrid.mSplitDistanceY + topHeight);
                    this._splitAreas.se.css("marginTop", wijgrid.mSplitDistanceY);
                }
            };

            fixedView.prototype._strictWidthMode = function () {
                return this._wijgrid.options.ensureColumnsPxWidth || this._wijgrid._allowHVirtualScrolling();
            };

            // private specific **
            // ** wijsuperpanel specific
            fixedView.prototype._getSuperPanelContentWrapper = function () {
                if (!this._superPanelElementsCache.contentWrapper || !this._superPanelElementsCache.contentWrapper.length) {
                    this._superPanelElementsCache.contentWrapper = this._wijgrid.mOuterDiv.find(".wijmo-wijsuperpanel-contentwrapper:first"); // not available in native mode?
                }

                return this._superPanelElementsCache.contentWrapper;
            };

            fixedView.prototype._getSuperPanelStateContainer = function () {
                if (!this._superPanelElementsCache.stateContainer || !this._superPanelElementsCache.stateContainer.length) {
                    this._superPanelElementsCache.stateContainer = this._wijgrid.mOuterDiv.find(".wijmo-wijsuperpanel-statecontainer:first");
                }

                return this._superPanelElementsCache.stateContainer;
            };

            fixedView.prototype._getSuperPanelTemplateWrapper = function () {
                if (!this._superPanelElementsCache.templateWrapper || !this._superPanelElementsCache.templateWrapper.length) {
                    this._superPanelElementsCache.templateWrapper = this._wijgrid.mOuterDiv.find(".wijmo-wijsuperpanel-templateouterwrapper:first"); // not available in native mode?
                }

                return this._superPanelElementsCache.templateWrapper;
            };

            fixedView.prototype._isNativeSuperPanel = function () {
                return this._wijgrid._isTouchEnv();
            };

            fixedView.prototype._testAutohiddenScrollbars = function () {
                if (this._isNativeSuperPanel()) {
                    var container = this._getSuperPanelStateContainer();
                    if (container.length) {
                        return container[0].offsetWidth === container[0].clientWidth;
                    }
                }

                return false;
            };
            return fixedView;
        })(_grid.baseView);
        _grid.fixedView = fixedView;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="interfaces.ts" />
/// <reference path="wijgrid.ts" />
/// <reference path="misc.ts" />
var wijmo;
(function (wijmo) {
    (function (grid) {
        var $ = jQuery;

        /** An object that represents selection in the grid. You do not need to create instances of this class. */
        var selection = (function () {
            /** Creates an object that represents selection in the grid. Normally you do not need to use this method.
            * @example
            * var selection = new wijmo.grid.selection(wijgrid);
            * @param {wijmo.wijgrid} wijgrid wijgrid
            * @returns {wijmo.grid.selection} Object that represents selection in the grid
            */
            function selection(wijgrid) {
                this._updates = 0;
                this._selectedColumns = null;
                this._selectedRows = null;
                // n: none (0), c: extendToColumn (1), r: extendToRow (2)
                //
                //              extendMode
                // selectionMode| n | c | r
                // ------------------------
                // singlecell   | n | n | n
                // singlecolumn | c | c | c
                // singlerow    | r | r | r
                // singlerange  | n | c | r
                // multicolumn  | c | c | c
                // multirow     | r | r | r
                // multirange   | n | c | r
                this._extend_rules = {
                    "singlecell": [0, 0, 0],
                    "singlecolumn": [1, 1, 1],
                    "singlerow": [2, 2, 2],
                    "singlerange": [0, 1, 2],
                    "multicolumn": [1, 1, 1],
                    "multirow": [2, 2, 2],
                    "multirange": [0, 1, 2]
                };
                if (!wijgrid) {
                    throw "invalid arguments";
                }

                this._wijgrid = wijgrid;

                this._addedCells = new cellInfoOrderedCollection(wijgrid);
                this._removedCells = new cellInfoOrderedCollection(wijgrid);
                this._selectedCells = new cellInfoOrderedCollection(wijgrid);
                this._addedDuringCurTransactionCells = new cellInfoOrderedCollection(wijgrid);
            }
            /** Gets a read-only collection of the selected cells.
            * @example
            * var selectedCells = selectionObj.selectedCells();
            * for (var i = 0, len = selectedCells.length(); i < len; i++) {
            *	alert(selectedCells.item(i).value().toString());
            * }
            * @returns {wijmo.grid.cellInfoOrderedCollection} A read-only collection of the selected cells.
            */
            selection.prototype.selectedCells = function () {
                return this._selectedCells;
            };

            /** Gets a read-only collection of the selected rows.
            * @example
            * alert(selectionObj.selectedRows().length());
            * @returns {wijmo.grid.selectedRowsAccessor} A read-only collection of the selected rows.
            */
            selection.prototype.selectedRows = function () {
                if (!this._selectedRows) {
                    this._selectedRows = new selectedRowsAccessor(this._wijgrid);
                }

                return this._selectedRows;
            };

            /** Adds a column range to the current selection.
            * Usage:
            * 1. addColumns(0)
            * 2. addColumns(0, 2)
            * @example
            * // Add the first column to the current selection.
            * selectionObj.addColumns(0);
            * @remarks
            * The result depends upon the chosen selection mode in the grid. For example, if current selection mode does not allow multiple selection the previous selection will be removed.
            * @param {Number} start The index of the first column to select.
            * @param {Number} end The index of the last column to select.
            */
            selection.prototype.addColumns = function (start, end /* opt */ ) {
                if (!end && end !== 0) {
                    end = start;
                }

                this.addRange(start, 0, end, 0xFFFFFF);
            };

            /** @ignore */
            selection.prototype.addRange = function (cellRange /* x0 */ , y0 /* opt */ , x1 /* opt */ , y1 /* opt */ ) {
                if (!cellRange && (arguments.length === 1)) {
                    throw "invalid argument";
                }

                var range = (arguments.length === 4) ? new wijmo.grid.cellInfoRange(new wijmo.grid.cellInfo(cellRange, y0), new wijmo.grid.cellInfo(x1, y1)) : cellRange._clone();

                range._normalize();

                if (!range._isValid()) {
                    throw "invalid argument";
                }

                this.beginUpdate();

                this._startNewTransaction(this._wijgrid._currentCell());
                this._selectRange(range, false, true, 0 /* none */, null);

                this.endUpdate();
            };

            /** Adds a row range to the current selection.
            * Usage:
            * 1. addRows(0)
            * 2. addRows(0, 2)
            * @example
            * // Add the first row to the selection.
            * selectionObj.addRows(0);
            * @remarks
            * The result depends upon the chosen selection mode in the grid. For example, if current selection mode does not allow multiple selection the previous selection will be removed.
            * @param {Number} start The index of the first row to select.
            * @param {Number} end The index of the last row to select.
            */
            selection.prototype.addRows = function (start, end /* opt */ ) {
                if (!end && end !== 0) {
                    end = start;
                }

                this.addRange(0, start, 0xFFFFFF, end);
            };

            /** @ignore */
            selection.prototype.removeRange = function (cellRange /* x0 */ , y0 /* opt */ , x1 /* opt */ , y1 /* opt */ ) {
                if (!cellRange && (arguments.length === 1)) {
                    throw "invalid argument";
                }

                var range = (arguments.length === 4) ? new wijmo.grid.cellInfoRange(new wijmo.grid.cellInfo(cellRange, y0), new wijmo.grid.cellInfo(x1, y1)) : cellRange._clone();

                range._normalize();

                if (!range._isValid()) {
                    throw "invalid argument";
                }

                this.beginUpdate();

                this._startNewTransaction(this._wijgrid._currentCell());
                this._clearRange(range, 0 /* none */);

                this.endUpdate();
            };

            /**
            * Removes a range of columns from the current selection.
            * Usage:
            * 1. removeColumns(0)
            * 2. removeColumns(0, 2)
            * @example
            * // Remove the first columm from the selection.
            * selectionObj.removeColumns(0);
            * @remarks
            * The result depends upon the chosen selection mode in the grid.
            * @param {Number} start The index of the first column to remove.
            * @param {Number} end The index of the last column to remove.
            */
            selection.prototype.removeColumns = function (start, end /* opt */ ) {
                if (!end && end !== 0) {
                    end = start;
                }

                this.removeRange(start, 0, end, 0xFFFFFF);
            };

            /** Removes a range of rows from the current selection.
            * Usage:
            * 1. removeRows(0)
            * 2. removeRows(0, 2)
            * @example
            * // Remove the first row from the selection.
            * selectionObj.removeRows(0);
            * @remarks
            * The result depends upon the chosen selection mode in the grid.
            * @param {Number} start The index of the first row to remove.
            * @param {Number} end The index of the last row to remove.
            */
            selection.prototype.removeRows = function (start, end /* opt */ ) {
                if (!end && end !== 0) {
                    end = start;
                }

                this.removeRange(0, start, 0xFFFFFF, end);
            };

            /**
            * Clears the selection.
            * @example
            * // Clear the selection.
            * selectionObj.clear();
            */
            selection.prototype.clear = function () {
                this.beginUpdate();

                this._removedCells._clear();
                this._removedCells._addFrom(this._selectedCells);

                this.endUpdate();
            };

            /**
            * Selects all the cells in a grid.
            * @example
            * selectionObj.selectAll();
            * @remarks
            * The result depends upon the chosen selection mode in the grid. For example, if the selection mode is set to "singleCell", then only the top left cell will be selected.
            */
            selection.prototype.selectAll = function () {
                this.beginUpdate();

                this._selectRange(this._wijgrid._getDataCellsRange(0 /* sketch */), false, false, 0 /* none */, null);

                this.endUpdate();
            };

            /**
            * Begins the update. Any changes won't take effect until endUpdate() is called.
            * @example
            * selectionObj.beginUpdate();
            */
            selection.prototype.beginUpdate = function () {
                this._updates++;
            };

            /**
            * Ends the update. The pending changes are executed and the selectionChanged event is raised.
            * @example
            * selectionObj.endUpdate();
            * @param {JQueryEventObject} e The original event object passed through by wijgrid.
            */
            selection.prototype.endUpdate = function (e) {
                if (this._updates > 0) {
                    this._updates--;

                    if (this._updates === 0) {
                        this.doSelection(); // values must be clipped before this step

                        if (this._addedCells.length() || this._removedCells.length()) {
                            if (this._selectedColumns !== null) {
                                this._selectedColumns.UnderlyingDataChanged(); // notify
                            }

                            if (this._selectedRows !== null) {
                                this._selectedRows._setDirty(); // notify
                            }

                            this._wijgrid._trigger("selectionChanged", e, { addedCells: this._addedCells, removedCells: this._removedCells });
                        }

                        this._addedCells = new wijmo.grid.cellInfoOrderedCollection(this._wijgrid);
                        this._removedCells._clear();
                    }
                }
            };

            // * internal
            selection.prototype._multipleRangesAllowed = function () {
                var mode = this._wijgrid.options.selectionMode;
                return (mode && ((mode = mode.toLowerCase()) === "multicolumn" || mode === "multirow" || mode === "multirange"));
            };

            selection.prototype._multipleEntitiesAllowed = function () {
                var mode = this._wijgrid.options.selectionMode;
                return (mode && ((mode = mode.toLowerCase()) === "multicolumn" || mode === "multirow" || mode === "multirange" || mode === "singlerange"));
            };

            selection.prototype._anchorCell = function () {
                return this.__anchorCell;
            };

            selection.prototype._startNewTransaction = function (dataCellInfo) {
                if (dataCellInfo) {
                    this.__anchorCell = dataCellInfo._clone();
                    this._addedDuringCurTransactionCells = new wijmo.grid.cellInfoOrderedCollection(this._wijgrid);
                }
            };

            selection.prototype._clearRange = function (range, extendMode) {
                var selectionMode = this._wijgrid.options.selectionMode.toLowerCase(), dataRange = this._wijgrid._getDataCellsRange(0 /* sketch */);

                if (range._isValid() && (selectionMode !== "none") && (this._selectedCells.length() > 0)) {
                    var rangeToClear = range._clone();

                    rangeToClear._normalize();
                    rangeToClear._clip(dataRange);

                    if (!range._isValid()) {
                        return;
                    }

                    // extend
                    rangeToClear._extend(this._extend_rules[selectionMode][extendMode], dataRange);

                    this.beginUpdate();

                    for (var i = 0, len = this._selectedCells.length(); i < len; i++) {
                        var cellInfo = this._selectedCells.item(i);

                        if (rangeToClear._containsCellInfo(cellInfo)) {
                            this._removedCells._add(cellInfo);
                        }
                    }

                    this.endUpdate();
                }
            };

            selection.prototype._selectRange = function (range, ctrlKey, shiftKey, extendMode, endPoint) {
                var selectionMode = this._wijgrid.options.selectionMode.toLowerCase(), rangeToSelect, dataRange = this._wijgrid._getDataCellsRange(0 /* sketch */);

                if ((selectionMode !== "none") && range._isValid()) {
                    rangeToSelect = range._clone();
                    rangeToSelect._normalize();
                    rangeToSelect._clip(dataRange);

                    if (!rangeToSelect._isValid()) {
                        return;
                    }

                    this.beginUpdate();

                    if (!this._multipleRangesAllowed()) {
                        this.clear();
                    } else {
                        if (ctrlKey || shiftKey) {
                            if (shiftKey) {
                                this._removedCells._clear();
                                this._removedCells._addFrom(this._addedDuringCurTransactionCells);
                            }
                        } else {
                            this.clear();
                        }
                    }

                    switch (selectionMode) {
                        case "singlecell":
                        case "singlecolumn":
                        case "singlerow":
                            rangeToSelect = (endPoint === null) ? new wijmo.grid.cellInfoRange(rangeToSelect.topLeft(), rangeToSelect.topLeft()) : new wijmo.grid.cellInfoRange(endPoint, endPoint);
                            break;
                    }

                    // extend
                    rangeToSelect._extend(this._extend_rules[selectionMode][extendMode], dataRange);

                    // do selection
                    this.doRange(rangeToSelect, true);

                    this.endUpdate();
                }
            };

            selection.prototype._ensureSelection = function () {
                var view = this._wijgrid._view(), prevRowIndex = -2, rowInfo;

                for (var i = 0; i < this._selectedCells.length(); i++) {
                    var cellInfo = this._selectedCells.item(i);

                    if (cellInfo._isRendered()) {
                        if (prevRowIndex !== cellInfo.rowIndex()) {
                            rowInfo = cellInfo.row();
                            prevRowIndex = cellInfo.rowIndex();
                        }

                        this.selectCell(cellInfo, rowInfo, view, true);
                    }
                }
            };

            selection.prototype._ensureSelectionInRow = function (sketchRowIndex) {
                var _this = this;
                var view = this._wijgrid._view();

                if (view._isRowRendered(sketchRowIndex) >= 0) {
                    var rowInfo = view._getRowInfoBySketchRowIndex(sketchRowIndex, false), selectedCells = this.selectedCells();

                    if (rowInfo && selectedCells && (selectedCells.length() > 0)) {
                        rowInfo.$rows.children("td, th").each(function (i, cell) {
                            var idx = selectedCells.indexOf(i, sketchRowIndex);
                            if (idx >= 0) {
                                _this.selectCell(selectedCells.item(idx), rowInfo, view, true);
                            }
                        });
                    }
                }
            };

            // * internal
            // * private
            selection.prototype.doSelection = function () {
                var view = this._wijgrid._view(), wijCSS = this._wijgrid.options.wijCSS, rowInfo, prevRowIndex = -1;

                for (var i = 0, len = this._removedCells.length(); i < len; i++) {
                    var cellInfo = this._removedCells.item(i);

                    if (this._addedCells.indexOf(cellInfo) < 0) {
                        if (prevRowIndex !== cellInfo.rowIndex()) {
                            rowInfo = cellInfo.row();
                            prevRowIndex = cellInfo.rowIndex();
                        }

                        this.selectCell(cellInfo, rowInfo, view, false);
                        if (rowInfo.$rows) {
                            rowInfo.$rows.removeClass(wijCSS.stateDefault + " " + wijCSS.stateHover);
                        }

                        this._selectedCells._remove(cellInfo);
                        this._addedDuringCurTransactionCells._remove(cellInfo);
                    } else {
                        this._removedCells._removeAt(i);
                        i--;
                        len--;
                    }
                }

                prevRowIndex = -1;

                for (var i = 0, len = this._addedCells.length(); i < len; i++) {
                    var cellInfo = this._addedCells.item(i), index = this._selectedCells.indexOf(cellInfo);

                    if (index < 0) {
                        if (prevRowIndex !== cellInfo.rowIndex()) {
                            rowInfo = cellInfo.row();
                            prevRowIndex = cellInfo.rowIndex();
                        }

                        this.selectCell(cellInfo, rowInfo, view, true);

                        this._selectedCells._insertUnsafe(cellInfo, ~index);
                        this._addedDuringCurTransactionCells._add(cellInfo);
                    } else {
                        this._addedCells._removeAt(i);
                        i--;
                        len--;
                    }
                }
            };

            selection.prototype.selectCell = function (cellInfo, rowInfo, view, select) {
                if (cellInfo._isRendered()) {
                    var bounds = this._wijgrid._viewPortBounds(), cell = view.getCell(cellInfo.cellIndexAbs(), cellInfo.rowIndexAbs());

                    if (cell) {
                        var $cell = $(cell), state = view._changeCellRenderState($cell, 8 /* selected */, select === true);

                        this._wijgrid.mCellStyleFormatter.format($cell, cellInfo.cellIndex(), cellInfo.columnInst(), rowInfo, state);
                    }
                }
            };

            selection.prototype.doRange = function (range, add) {
                var x0 = range.topLeft().cellIndex(), y0 = range.topLeft().rowIndex(), x1 = range.bottomRight().cellIndex(), y1 = range.bottomRight().rowIndex(), view = this._wijgrid._view(), renderBounds = this._wijgrid._viewPortBounds();

                if (add) {
                    var cnt = this._addedCells.length(), rows = this._wijgrid._rows();

                    for (var row = y0; row <= y1; row++) {
                        var rowInfo = view._getRowInfoBySketchRowIndex(row);

                        if (rowInfo && rowInfo.type & 2 /* data */) {
                            for (var col = x0; col <= x1; col++) {
                                var cell = new wijmo.grid.cellInfo(col, row);

                                if (cnt === 0) {
                                    this._addedCells._appendUnsafe(cell);
                                } else {
                                    this._addedCells._add(cell);
                                }
                            }
                        }
                    }
                } else {
                    var cnt = this._removedCells.length();

                    for (var row = y0; row <= y1; row++) {
                        for (var col = x0; col <= x1; col++) {
                            var cell = new wijmo.grid.cellInfo(col, row);

                            if (cnt === 0) {
                                this._removedCells._appendUnsafe(cell);
                            } else {
                                this._removedCells._add(cell);
                            }
                        }
                    }
                }
            };
            return selection;
        })();
        grid.selection = selection;

        /** An ordered read-only collection of wijmo.grid.cellInfo objects */
        var cellInfoOrderedCollection = (function () {
            /**
            * Creates an ordered read-only collection of wijmo.grid.cellInfo objects. Normally you do not need to use this method.
            * @example
            * var collection = new wijmo.grid.cellInfoOrderedCollection(wijgrid);
            * @param {wijmo.wijgrid} wijgrid wijgrid
            * @returns {wijmo.grid.cellInfoOrderedCollection}  An ordered read-only collection of wijmo.grid.cellInfo objects
            */
            function cellInfoOrderedCollection(wijgrid) {
                if (!wijgrid) {
                    throw "invalid arguments";
                }

                this._wijgrid = wijgrid;
                this._list = [];
            }
            // public
            /** Gets an item at the specified index.
            * @example
            * var cellInfoObj = collection.item(0);
            * @param {Number} index The zero-based index of the item to get.
            * @returns {wijmo.grid.cellInfo} The wijmo.grid.cellInfo object at the specified index.
            */
            cellInfoOrderedCollection.prototype.item = function (index) {
                return this._list[index];
            };

            /** Gets the total number of the items in the collection.
            * @example
            * var len = collection.length();
            * @returns {Number} The total number of the items in the collection.
            */
            cellInfoOrderedCollection.prototype.length = function () {
                return this._list.length;
            };

            /** @ignore */
            cellInfoOrderedCollection.prototype.indexOf = function (cellIndex, rowIndex) {
                if (arguments.length === 1) {
                    rowIndex = cellIndex.rowIndex();
                    cellIndex = cellIndex.cellIndex();
                }

                var lo = 0, hi = this._list.length - 1, med, current, cmp;

                while (lo <= hi) {
                    med = lo + ((hi - lo) >> 1);
                    current = this._list[med];

                    cmp = current.rowIndex() - rowIndex;
                    if (cmp === 0) {
                        cmp = current.cellIndex() - cellIndex;
                    }

                    if (cmp < 0) {
                        lo = med + 1;
                    } else {
                        if (cmp > 0) {
                            hi = med - 1;
                        } else {
                            return med;
                        }
                    }
                }

                return ~lo;
            };

            /** @ignore */
            cellInfoOrderedCollection.prototype.toString = function () {
                var val = "";

                for (var i = 0, len = this._list.length; i < len; i++) {
                    val += this._list[i].toString() + "\n";
                }

                return val;
            };

            // public *
            // internal
            cellInfoOrderedCollection.prototype._add = function (value) {
                var idx = this.indexOf(value);
                if (idx < 0) {
                    this._list.splice(~idx, 0, value);
                    value._setGridView(this._wijgrid);
                    return true;
                }

                return false;
            };

            cellInfoOrderedCollection.prototype._addFrom = function (addFrom) {
                if (addFrom) {
                    var fromLen = addFrom.length(), thisLen = this._list.length, i;

                    if (thisLen === 0) {
                        this._list.length = fromLen;

                        for (i = 0; i < fromLen; i++) {
                            this._list[i] = addFrom.item(i);
                            this._list[i]._setGridView(this._wijgrid);
                        }
                    } else {
                        for (i = 0; i < fromLen; i++) {
                            this._add(addFrom.item(i));
                        }
                    }
                }
            };

            cellInfoOrderedCollection.prototype._appendUnsafe = function (value) {
                this._list[this._list.length] = value;
                value._setGridView(this._wijgrid);
            };

            cellInfoOrderedCollection.prototype._insertUnsafe = function (value, index) {
                this._list.splice(index, 0, value);
            };

            cellInfoOrderedCollection.prototype._clear = function () {
                this._list.length = 0;
            };

            cellInfoOrderedCollection.prototype._remove = function (value) {
                var idx = this.indexOf(value);
                if (idx >= 0) {
                    this._list.splice(idx, 1);
                    return true;
                }

                return false;
            };

            cellInfoOrderedCollection.prototype._removeAt = function (index) {
                this._list.splice(index, 1);
            };

            cellInfoOrderedCollection.prototype._getCellsIndicies = function () {
                var cells = [], list = this._list, len = list.length;

                if (len) {
                    var dict = {};

                    for (var i = 0; i < len; i++) {
                        var cellIndex = list[i].cellIndex();
                        dict[cellIndex] = cellIndex;
                    }

                    for (var key in dict) {
                        if (dict.hasOwnProperty(key)) {
                            cells.push(dict[key]);
                        }
                    }
                }

                return cells;
            };

            cellInfoOrderedCollection.prototype._getSelectedRowsIndicies = function () {
                var rows = [], list = this._list, len = list.length;

                if (len) {
                    var dict = {};

                    for (var i = 0; i < len; i++) {
                        var rowIndex = list[i].rowIndex();
                        dict[rowIndex] = rowIndex;
                    }

                    for (var key in dict) {
                        if (dict.hasOwnProperty(key)) {
                            rows.push(dict[key]);
                        }
                    }
                }

                return rows;
            };

            cellInfoOrderedCollection.prototype._rectangulate = function () {
                var x0 = 0xFFFFFFFF, y0 = 0xFFFFFFFF, x1 = 0, y1 = 0, len = this._list.length;

                if (len) {
                    for (var i = 0; i < len; i++) {
                        var cellInfo = this._list[i];

                        x0 = Math.min(x0, cellInfo.cellIndex());
                        y0 = Math.min(y0, cellInfo.rowIndex());
                        x1 = Math.max(x1, cellInfo.cellIndex());
                        y1 = Math.max(y1, cellInfo.rowIndex());
                    }

                    return new wijmo.grid.cellInfoRange(new wijmo.grid.cellInfo(x0, y0), new wijmo.grid.cellInfo(x1, y1));
                }

                return null;
            };
            return cellInfoOrderedCollection;
        })();
        grid.cellInfoOrderedCollection = cellInfoOrderedCollection;

        /** Provides a read-only access to rows which cells are selected. */
        var selectedRowsAccessor = (function () {
            /**
            * Constructor. Normally you do not need to use this method.
            * @example
            * var collection = new wijmo.grid.selectedRowsAccessor(wijgrid);
            * @param {wijmo.wijgrid} wijgrid wijgrid
            * @returns {wijmo.grid.selectedRowsAccessor} A new instance of the selectedRowsAccessor class.
            */
            function selectedRowsAccessor(wijgrid) {
                this.mLength = 0;
                this.mDirty = true;
                this.mRowIndicies = [];
                this.mWijgrid = wijgrid;
            }
            /** Gets the total number of the items in the collection.
            * @example
            * var len = $("#demo").wijgrid("selection").selectedRows().length();
            * @returns {Number} The total number of the items in the collection.
            */
            selectedRowsAccessor.prototype.length = function () {
                this._ensure();
                return this.mLength;
            };

            /** Gets an object representing grid's row at the specified index.
            * @example
            * var row = $("#demo").wijgrid("selection").selectedRows().item(0);
            * @param {Number} index The zero-based index of the item to get.
            * @returns {wijmo.grid.IRowInfo} An object representing grid's row at the specified index.
            */
            selectedRowsAccessor.prototype.item = function (index) {
                this._ensure();

                var rowInfo = this.mWijgrid._view()._getRowInfoBySketchRowIndex(this.mRowIndicies[index]);

                return rowInfo;
            };

            selectedRowsAccessor.prototype._ensure = function () {
                if (this.mDirty) {
                    this.mRowIndicies = this.mWijgrid.selection().selectedCells()._getSelectedRowsIndicies();
                    this.mLength = this.mRowIndicies.length;
                    this.mDirty = false;
                }
            };

            /** @ignore */
            selectedRowsAccessor.prototype._setDirty = function () {
                this.mDirty = true;
            };
            return selectedRowsAccessor;
        })();
        grid.selectedRowsAccessor = selectedRowsAccessor;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="interfaces.ts"/>
/// <reference path="wijgrid.ts"/>
/// <reference path="cellInfo.ts"/>
/// <reference path="rowAccessor.ts"/>
var wijmo;
(function (wijmo) {
    (function (grid) {
        var $ = jQuery;

        /** @ignore */
        var uiSelection = (function () {
            function uiSelection(wijgrid) {
                this._gap_to_start = 10;
                this._inProgress = false;
                this._additionalEventsAttached = false;
                this._wijgrid = wijgrid;

                this._evntFormat = "{0}." + this._wijgrid.widgetName + ".selectionui";
                this._addedCells = new wijmo.grid.cellInfoOrderedCollection(this._wijgrid);
                this._view = this._wijgrid._view();
                this._rootElement = this._view.focusableElement();

                this._rootElement.bind(this._eventKey("mousedown"), $.proxy(this._onGridMouseDown, this));
            }
            uiSelection.prototype.dispose = function () {
                this._rootElement.unbind(this._eventKey("mousedown"), this._onGridMouseDown);
                this._detachAdditionalEvents();
            };

            uiSelection.prototype._onGridMouseDown = function (args) {
                if (!this._wijgrid._canInteract() || this._wijgrid.options.selectionMode.toLowerCase() === "none") {
                    return;
                }

                var visibleBounds = this._view.getVisibleContentAreaBounds(), mouse = { x: args.pageX, y: args.pageY }, tag = ((args.target && args.target.tagName !== undefined) ? args.target.tagName.toLowerCase() : undefined), $target = $(args.target), defCSS = wijmo.grid.wijgrid.CSS;

                if ((!tag || $target.is("td." + defCSS.TD + ", th." + defCSS.TD + ", div." + defCSS.cellContainer)) && (mouse.x > visibleBounds.left && mouse.x < visibleBounds.left + visibleBounds.width) && (mouse.y > visibleBounds.top && mouse.y < visibleBounds.top + visibleBounds.height)) {
                    this._attachAdditionalEvents();
                    this._startPos = mouse;

                    this._startCellInfo = this._coordToDataCellInfo(this._startPos);
                }
            };

            uiSelection.prototype._onDocumentMouseMove = function (args) {
                if (!this._startCellInfo || !this._startCellInfo._isValid()) {
                    return;
                }

                var mouse = { x: args.pageX, y: args.pageY }, rowInfo, view = this._wijgrid._view(), $rs = wijmo.grid.renderState;

                if (!this._inProgress) {
                    this._inProgress = (Math.abs(this._startPos.x - mouse.x) > this._gap_to_start) || (Math.abs(this._startPos.y - mouse.y) > this._gap_to_start);
                }

                if (this._inProgress) {
                    var tmp = this._coordToDataCellInfo(mouse);
                    if (!tmp._isValid()) {
                        return;
                    }

                    this._endCellInfo = tmp;

                    if (!this._wijgrid.selection()._multipleEntitiesAllowed()) {
                        this._startCellInfo = this._endCellInfo;
                    }

                    var range = new wijmo.grid.cellInfoRange(this._startCellInfo, this._endCellInfo);
                    range._normalize();
                    range._clip(this._wijgrid._getDataCellsRange(0 /* sketch */));

                    if (range._isValid() && !range.isEqual(this._prevMouseMoveRange)) {
                        this._prevMouseMoveRange = range;

                        var desiredCells = new wijmo.grid.cellInfoOrderedCollection(this._wijgrid);

                        for (var i = range.topLeft().rowIndex(), len = range.bottomRight().rowIndex(); i <= len; i++) {
                            rowInfo = view._getRowInfoBySketchRowIndex(i);

                            if (rowInfo.type & 2 /* data */) {
                                for (var j = range.topLeft().cellIndex(), len2 = range.bottomRight().cellIndex(); j <= len2; j++) {
                                    desiredCells._appendUnsafe(new wijmo.grid.cellInfo(j, i));
                                }
                            }
                        }

                        var prevRowIndex = -1;

                        for (var i = 0, len = this._addedCells.length(); i < len; i++) {
                            var cellInfo = this._addedCells.item(i);

                            if (desiredCells.indexOf(cellInfo) < 0) {
                                if (this._wijgrid.selection().selectedCells().indexOf(cellInfo) < 0) {
                                    var cell = this._view.getCell(cellInfo.cellIndexAbs(), cellInfo.rowIndexAbs());

                                    if (cell) {
                                        if (prevRowIndex !== cellInfo.rowIndex()) {
                                            rowInfo = cellInfo.row();
                                            prevRowIndex = cellInfo.rowIndex();
                                        }

                                        var $cell = $(cell);
                                        var state = view._changeCellRenderState($cell, 8 /* selected */, false);
                                        this._wijgrid.mCellStyleFormatter.format($cell, cellInfo.cellIndex(), cellInfo.columnInst(), rowInfo, state);
                                    }
                                }

                                this._addedCells._removeAt(i);
                                i--;
                                len--;
                            }
                        }

                        prevRowIndex = -1;
                        for (var i = 0, len = desiredCells.length(); i < len; i++) {
                            var cellInfo = desiredCells.item(i);

                            if (this._addedCells.indexOf(cellInfo) < 0 && this._wijgrid.selection().selectedCells().indexOf(cellInfo) < 0) {
                                if (this._addedCells._add(cellInfo)) {
                                    var cell = this._view.getCell(cellInfo.cellIndexAbs(), cellInfo.rowIndexAbs());

                                    if (cell) {
                                        if (prevRowIndex !== cellInfo.rowIndex()) {
                                            rowInfo = cellInfo.row();
                                            prevRowIndex = cellInfo.rowIndex();
                                        }

                                        var $cell = $(cell);
                                        var state = view._changeCellRenderState($cell, 8 /* selected */, true);
                                        this._wijgrid.mCellStyleFormatter.format($cell, cellInfo.cellIndex(), cellInfo.columnInst(), rowInfo, state);
                                    }
                                }
                            }
                        }
                    }
                }
            };

            uiSelection.prototype._onDocumentMouseUp = function (args) {
                this._detachAdditionalEvents();

                if (this._inProgress) {
                    this._inProgress = false;

                    if (this._prevMouseMoveRange && this._prevMouseMoveRange._isValid()) {
                        this._wijgrid._changeCurrentCell(args, this._endCellInfo, { changeSelection: false, setFocus: false });

                        if (!args.shiftKey || !this._wijgrid.selection()._multipleEntitiesAllowed()) {
                            this._wijgrid.selection()._startNewTransaction(this._startCellInfo);
                        }

                        this._wijgrid.selection().beginUpdate();
                        this._wijgrid.selection()._selectRange(this._prevMouseMoveRange, args.shiftKey, args.ctrlKey, 0 /* none */, this._endCellInfo);
                        this._wijgrid.selection().endUpdate();

                        var view = this._wijgrid._view(), prevRowIndex = -1, rowInfo, $rs = wijmo.grid.renderState;

                        for (var i = 0, len = this._addedCells.length(); i < len; i++) {
                            var cellInfo = this._addedCells.item(i);

                            if (this._wijgrid.selection().selectedCells().indexOf(cellInfo) < 0) {
                                var cell = view.getCell(cellInfo.cellIndexAbs(), cellInfo.rowIndexAbs());

                                if (cell !== null) {
                                    if (prevRowIndex !== cellInfo.rowIndex()) {
                                        rowInfo = cellInfo.row();
                                        prevRowIndex = cellInfo.rowIndex();
                                    }

                                    var $cell = $(cell), state = view._changeCellRenderState($cell, 8 /* selected */, false);

                                    this._wijgrid.mCellStyleFormatter.format($cell, cellInfo.cellIndex(), cellInfo.columnInst(), rowInfo, state);
                                }
                            }
                        }

                        this._addedCells._clear();
                        this._startCellInfo = this._endCellInfo = this._prevMouseMoveRange = null;

                        return false;
                    }
                }
            };

            uiSelection.prototype._attachAdditionalEvents = function () {
                if (!this._additionalEventsAttached) {
                    try  {
                        this._view.toggleDOMSelection(false); // disable selection

                        $(document).bind(this._eventKey("mousemove"), $.proxy(this._onDocumentMouseMove, this)).bind(this._eventKey("mouseup"), $.proxy(this._onDocumentMouseUp, this));
                    } finally {
                        this._additionalEventsAttached = true;
                    }
                }
            };

            uiSelection.prototype._detachAdditionalEvents = function () {
                if (this._additionalEventsAttached) {
                    try  {
                        this._view.toggleDOMSelection(true); // enable selection

                        $(document).unbind(this._eventKey("mousemove"), this._onDocumentMouseMove).unbind(this._eventKey("mouseup"), this._onDocumentMouseUp);
                    } finally {
                        this._additionalEventsAttached = false;
                    }
                }
            };

            uiSelection.prototype._eventKey = function (eventType) {
                return wijmo.grid.stringFormat(this._evntFormat, eventType);
            };

            uiSelection.prototype._coordToDataCellInfo = function (pnt) {
                var left = 0, right = this._wijgrid._renderedLeaves().length - 1, median = 0, cellIdx = -1, bounds, gridRowsAccessor = new wijmo.grid.rowAccessor(this._view, 2, 0, 0), row;

                while (left <= right) {
                    median = ((right - left) >> 1) + left;

                    bounds = wijmo.grid.bounds(this._view.getHeaderCell(median)); // get header cell
                    if (!bounds) {
                        row = gridRowsAccessor.item(0);
                        bounds = wijmo.grid.bounds(wijmo.grid.rowAccessor.getCell(row, median)); // get data cell
                    }

                    if (!bounds) {
                        break;
                    }

                    if (pnt.x < bounds.left) {
                        right = median - 1;
                    } else if (pnt.x > bounds.left + bounds.width) {
                        left = median + 1;
                    } else {
                        cellIdx = median;
                        break;
                    }
                }

                if (cellIdx === -1) {
                    return wijmo.grid.cellInfo.outsideValue;
                }

                gridRowsAccessor = new wijmo.grid.rowAccessor(this._view, 0, 0, 0);

                var rowIdx = -1;
                left = 0;
                right = gridRowsAccessor.length() - 1;
                median = 0;

                while (left <= right) {
                    median = ((right - left) >> 1) + left;
                    row = gridRowsAccessor.item(median);
                    bounds = wijmo.grid.bounds(wijmo.grid.rowAccessor.getCell(row, 0));

                    if (pnt.y < bounds.top) {
                        right = median - 1;
                    } else if (pnt.y > bounds.top + bounds.height) {
                        left = median + 1;
                    } else {
                        rowIdx = median;
                        break;
                    }
                }

                if (rowIdx === -1) {
                    return wijmo.grid.cellInfo.outsideValue;
                }

                var result = new wijmo.grid.cellInfo(cellIdx, rowIdx, this._wijgrid, true);

                return result;
            };
            return uiSelection;
        })();
        grid.uiSelection = uiSelection;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="interfaces.ts"/>
/// <reference path="baseView.ts"/>
var wijmo;
(function (wijmo) {
    (function (grid) {
        var $ = jQuery;

        /**
        * Class for convenient access to rows of a wijgrid.
        * @ignore
        */
        var rowAccessor = (function () {
            function rowAccessor(view, scope, offsetTop, offsetBottom) {
                this._view = view;
                this._scope = scope;
                this._offsetBottom = offsetBottom;
                this._offsetTop = offsetTop;
            }
            /** Gets an array of the table row elements that represents a wijgrid widget row at the specified index.
            * size of returning array is always two.
            * @param {Number} index The zero-based index of the row to retrieve.
            * @returns {Object[]} The array of the table row elements at the specified index.
            * @remarks
            */
            rowAccessor.prototype.item = function (index) {
                var len = this.length();

                return (index >= 0 && index < len) ? this._view.getJoinedRows(index + this._offsetTop, this._scope) : null;
            };

            /**
            * Gets the total number of elements.
            * @returns {Number} The total number of elements.
            */
            rowAccessor.prototype.length = function () {
                var joinedTables = this._view.getJoinedTables(true, 0), len = 0, htmlAccessor;

                if (htmlAccessor = joinedTables[0]) {
                    len = htmlAccessor.getSectionLength(this._scope);
                }

                if (htmlAccessor = joinedTables[1]) {
                    len += htmlAccessor.getSectionLength(this._scope);
                }

                len -= this._offsetTop + this._offsetBottom;

                if (len < 0) {
                    len = 0;
                }

                return len;
            };

            /** @ignore */
            rowAccessor.prototype.find = function (startFrom, callback, retrieveDataItem) {
                if (typeof retrieveDataItem === "undefined") { retrieveDataItem = false; }
                var f = this.findEx(startFrom, callback, retrieveDataItem);
                return f ? f.val : null;
            };

            /** @ignore */
            rowAccessor.prototype.findIndex = function (startFrom, callback, retrieveDataItem) {
                if (typeof retrieveDataItem === "undefined") { retrieveDataItem = false; }
                var f = this.findEx(startFrom, callback, retrieveDataItem);
                return f ? f.at : -1;
            };

            /** @ignore */
            rowAccessor.prototype.findRowObj = function (startFrom, callback, retrieveDataItem) {
                if (typeof retrieveDataItem === "undefined") { retrieveDataItem = false; }
                var f = this.findEx(startFrom, callback, retrieveDataItem);
                return f ? this.item(f.at) : null;
            };

            /** @ignore */
            rowAccessor.prototype.findEx = function (startFrom, callback, retrieveDataItem) {
                if (typeof retrieveDataItem === "undefined") { retrieveDataItem = false; }
                var len = this.length();

                for (var i = 0; i < len; i++) {
                    var rowObj = this.item(i), rowInfo = this._view._getRowInfo(rowObj, retrieveDataItem);

                    if (callback(rowInfo) === true) {
                        return {
                            at: i,
                            val: rowInfo
                        };
                    }
                }

                return null;
            };

            /** Sequentially iterates the cells in a rowObj argument.
            * @param {Array} rowObj Array of rows to be iterated.
            * @param {Function} callback Function that will be called each time a new cell is reached.
            * @param {Object} param Parameter that can be handled within the callback function.
            */
            rowAccessor.iterateCells = function (rowObj, callback, param) {
                if (rowObj && callback) {
                    var globCellIdx = 0;

                    for (var i = 0, len = rowObj.length; i < len; i++) {
                        var domRow = rowObj[i];

                        if (domRow) {
                            for (var j = 0, cellLen = domRow.cells.length; j < cellLen; j++) {
                                var result = callback(domRow.cells[j], globCellIdx++, param);
                                if (result !== true) {
                                    return;
                                }
                            }
                        }
                    }
                }
            };

            /** Gets a cell by its global index in a row's array passed in rowObj.
            * @example:
            * Suppose rows is an array containing the following data: [ ["a", "b"], ["c", "d", "e"] ]
            * "a" symbol has a global index 0.
            * "c" symbol has a global index 2.
            * @param {Array} rowObj Array of table row elements.
            * @param {Number} index Zero-based global index of a cell.
            * @returns {HTMLTableCellElement} A cell or null if a cell with provided index is not found.
            */
            rowAccessor.getCell = function (rowObj, globCellIndex) {
                var domRow, cellLen;

                if (rowObj && (domRow = rowObj[0])) {
                    cellLen = domRow.cells.length;
                    if (globCellIndex < cellLen) {
                        return domRow.cells[globCellIndex];
                    }

                    globCellIndex -= cellLen;

                    if (domRow = rowObj[1]) {
                        cellLen = domRow.cells.length;
                        if (globCellIndex < cellLen) {
                            return domRow.cells[globCellIndex];
                        }
                    }
                }

                return null;
            };

            /** @ignore */
            rowAccessor.getCell$ = function (row, globCellIndex) {
                var domCell = wijmo.grid.rowAccessor.getCell(row, globCellIndex);

                return (domCell) ? $(domCell) : $([]);
            };

            /** @ignore */
            rowAccessor.cellsCount = function (rowObj) {
                var res = 0, domRow;

                if (rowObj && (domRow = rowObj[0])) {
                    res = domRow.cells.length;

                    if (domRow = rowObj[1]) {
                        res += domRow.cells.length;
                    }
                }

                return res;
            };
            return rowAccessor;
        })();
        grid.rowAccessor = rowAccessor;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="interfaces.ts" />
/// <reference path="wijgrid.ts" />
/// <reference path="misc.ts" />
var wijmo;
(function (wijmo) {
    (function (_grid) {
        var $ = jQuery;

        /** @ignore */
        (function (updateCellResult) {
            updateCellResult[updateCellResult["error"] = 0] = "error";
            updateCellResult[updateCellResult["continueEditing"] = 1] = "continueEditing";
            updateCellResult[updateCellResult["success"] = 2] = "success";

            // ESC key is pressed or cell in not rendered.
            updateCellResult[updateCellResult["cancel"] = 4] = "cancel";
            updateCellResult[updateCellResult["notEdited"] = 8] = "notEdited";
        })(_grid.updateCellResult || (_grid.updateCellResult = {}));
        var updateCellResult = _grid.updateCellResult;
        ;

        /** @ignore */
        var cellEditorHelper = (function () {
            function cellEditorHelper() {
                this._timeout = 25;
            }
            cellEditorHelper.prototype.cellEditStart = function (grid, cell, e) {
                var result = false, view = grid._view();

                if (cell._isValid() && !cell._isPreparingForEditing() && !cell._isEdit() && (cell.columnInst() instanceof wijmo.grid.c1field)) {
                    var rowInfo = cell.row();

                    if (rowInfo) {
                        var rowType = rowInfo.type;

                        if (rowType & 2 /* data */) {
                            var args = {
                                cell: cell,
                                event: e,
                                handled: false
                            };

                            cell._isPreparingForEditing(true); // to avoid recursion because of changing focus\ selection and wijgrid.onfocusin event handler

                            if (result = (grid._onBeforeCellEdit(args) || (grid.options.editingMode === "row"))) {
                                if (!args.handled) {
                                    result = this._defaultBeforeCellEdit(grid, args);
                                }
                            }

                            if (result) {
                                cell._isEdit(true);
                            }

                            cell._isPreparingForEditing(false);
                        }
                    }
                }

                return result;
            };

            cellEditorHelper.prototype.updateCell = function (grid, cell, e, reject) {
                var row;

                if (cell && !cell._isEdit()) {
                    return 2 /* success */ | 8 /* notEdited */;
                }

                if (!cell || !cell._isValid() || !(row = cell.row()) || !(row.type & 2 /* data */)) {
                    return 0 /* error */;
                }

                if (reject || !cell._isRendered()) {
                    return 2 /* success */ | 4 /* cancel */;
                }

                var result = 2 /* success */, column = cell.column();

                var bcuArgs = {
                    cell: cell,
                    value: undefined
                };

                if (grid._onBeforeCellUpdate(bcuArgs) || (grid.options.editingMode === "row")) {
                    if (bcuArgs.value === undefined) {
                        bcuArgs.value = this._getCellValue(grid, cell); // get raw value from editor using  default implementation
                    }

                    var a = bcuArgs.value, b = cell.value();

                    try  {
                        var inputType = this._getHTMLInputElementType(cell);

                        if (wijmo.grid.HTML5InputSupport.isExtendSupportRequired(inputType)) {
                            bcuArgs.value = wijmo.grid.HTML5InputSupport.parse(bcuArgs.value, inputType);
                            bcuArgs.value = wijmo.grid.HTML5InputSupport.extend(b, bcuArgs.value, inputType);
                        } else {
                            bcuArgs.value = grid.parse(cell.column(), bcuArgs.value); // try to parse raw value
                        }

                        a = bcuArgs.value;
                    } catch (ex) {
                        bcuArgs.value = a; // restore raw value
                    }

                    if (wijmo.grid.getDataType(column) === "datetime") {
                        if (a instanceof Date) {
                            a = a.getTime();
                        }

                        if (b instanceof Date) {
                            b = b.getTime();
                        }
                    }

                    if (a !== b) {
                        try  {
                            cell.value(bcuArgs.value);
                        } catch (ex) {
                            var icvArgs = {
                                cell: cell,
                                value: bcuArgs.value
                            };

                            result = 0 /* error */;
                            grid._onInvalidCellValue(icvArgs);
                        }

                        if (result & 2 /* success */) {
                            var acuArgs = {
                                cell: cell
                            };

                            grid._onAfterCellUpdate(acuArgs);
                        }
                    }
                } else {
                    return 1 /* continueEditing */;
                }

                return result;
            };

            // must be called only after the updateCell().
            cellEditorHelper.prototype.cellEditEnd = function (grid, cell, e) {
                var rowInfo = cell.row(), aceArgs = {
                    cell: cell,
                    event: e,
                    handled: false
                };

                cell._isEdit(false);

                if (cell._isRendered()) {
                    grid._onAfterCellEdit(aceArgs);

                    if (!aceArgs.handled) {
                        this._defaultAfterCellEdit(grid, aceArgs);
                    }
                }
            };

            // private
            cellEditorHelper.prototype._defaultBeforeCellEdit = function (grid, args) {
                var column = args.cell.column(), result = false, $container, $input;

                if (column.dataIndex >= 0) {
                    var value = args.cell.value(), keyCodeEnum = wijmo.getKeyCodeEnum(), inputType = wijmo.grid.HTML5InputSupport.getDefaultInputType(grid._isMobileEnv(), column), allowCellEditing = grid._allowCellEditing(), serverSideCheckbox = false;

                    result = true;

                    try  {
                        $container = args.cell.container();

                        if (wijmo.grid.getDataType(column) === "boolean") {
                            var $span = $container.children("span");

                            if (serverSideCheckbox = !!($span.length && ($span.prop("disabled") || (grid.options._aspNetDisabledClass && $span.hasClass(grid.options._aspNetDisabledClass))))) {
                                $.data($span[0], "serverSideCheckbox", true);

                                $span.prop("disabled", false); // ASP.NET 3

                                if (grid.options._aspNetDisabledClass) {
                                    $span.removeClass(grid.options._aspNetDisabledClass); // ASP.NET 4
                                }
                            }

                            $input = $container.find(":checkbox");

                            if (serverSideCheckbox || !allowCellEditing) {
                                $input.prop("disabled", false);
                            }

                            if (args.event && args.event.type === "keypress") {
                                $input.one("keyup", function (e) {
                                    if (e.which === keyCodeEnum.SPACE) {
                                        e.preventDefault();
                                        $input[0].checked = !value;
                                    }
                                });
                            }
                        } else {
                            $input = $("<input type='" + inputType + "' />").css("ime-mode", column.imeMode || "auto").attribute("aria-label", inputType).addClass(wijmo.grid.wijgrid.CSS.inputMarker).addClass("wijmo-wijinput " + grid.options.wijCSS.stateFocus).bind("keydown", grid, $.proxy(this._checkBoxOrInputKeyDown, this));

                            //the problem of inputing
                            $input.bind(($.support.selectstart ? "selectstart" : "mousedown"), function (event) {
                                event.stopPropagation();
                            });

                            if (args.event && (args.event.type === "keydown") && (args.event.which !== 113)) {
                                // "edit on keypress", leave the editor empty.
                            } else {
                                switch (wijmo.grid.getDataType(column)) {
                                    case "currency":
                                    case "number":
                                        if (value !== null) {
                                            $input.val(value); // ignore formatting
                                            break;
                                        }
                                    case "datetime":
                                        if (wijmo.grid.HTML5InputSupport.isExtendSupportRequired(inputType)) {
                                            $input.val(wijmo.grid.HTML5InputSupport.toStr(value, inputType));
                                            break;
                                        }

                                    default:
                                        $input.val(grid.toStr(column, value));
                                        break;
                                }
                            }

                            $container.empty().append($input);

                            if (allowCellEditing) {
                                var len = $input.val().length;
                                if (inputType === "text") {
                                    // move caret to the end of the text
                                    new wijmo.grid.domSelection($input[0]).setSelection({ start: len, end: len });
                                }
                            }
                        }

                        if (allowCellEditing) {
                            $input.focus();
                            setTimeout(function () {
                                $input.focus();
                            }, this._timeout * 2);
                        }
                    } catch (ex) {
                        alert(ex.message);
                        result = false;
                    }
                }

                return result;
            };

            cellEditorHelper.prototype._defaultAfterCellEdit = function (grid, args) {
                var leaf = args.cell.columnInst(), opt = leaf.options, result = false;

                if (opt.dataIndex >= 0) {
                    result = true;

                    var view = grid._view();

                    try  {
                        var $container = args.cell.container(), cellValue = grid.toStr(opt, args.cell.value()), rowInfo = view._getRowInfoBySketchRowIndex(args.cell.rowIndex());

                        if (wijmo.grid.getDataType(opt) === "boolean") {
                            var $span = $container.children("span"), disable = $span.length && $.data($span[0], "serverSideCheckbox"), $input = $container.find(":checkbox");

                            $input.prop("checked", cellValue === "true");

                            /*if (cellValue === "true") {
                            $input.attr("checked", "checked");
                            }
                            else {
                            $input.removeAttr("checked");
                            }*/
                            if (disable) {
                                $span.prop("disabled", true); // ASP.NET 3

                                if (grid.options._aspNetDisabledClass) {
                                    $span.addClass(grid.options._aspNetDisabledClass);
                                }

                                $input.prop("disabled", true);
                            }
                        } else {
                            grid.mCellFormatter.format($(args.cell.tableCell()), args.cell.cellIndex(), $container, leaf, cellValue, rowInfo);
                        }
                    } catch (ex) {
                        alert("defaultAfterCellEdit: " + ex.message);
                        result = false;
                    }
                }

                return result;
            };

            cellEditorHelper.prototype._checkBoxOrInputKeyDown = function (args) {
                var keyCodeEnum = wijmo.getKeyCodeEnum();

                if (args.which === keyCodeEnum.ENTER) {
                    var grid = args.data;

                    if (grid) {
                        grid._endEditInternal(args);
                        return false;
                    }
                }
            };

            cellEditorHelper.prototype._getCellValue = function (grid, currentCell) {
                var $input = currentCell.container().find(":input:first"), result = null;

                if ($input.length) {
                    result = ($input.attr("type") === "checkbox") ? $input[0].checked : $input.val();
                }

                return result;
            };

            cellEditorHelper.prototype._getHTMLInputElementType = function (currentCell) {
                return currentCell.container().find(":input:first").attr("type");
            };
            return cellEditorHelper;
        })();
        _grid.cellEditorHelper = cellEditorHelper;

        // IME support.
        /** @ignore */
        var keyDownEventListener = (function () {
            function keyDownEventListener(grid, container) {
                this.mGrid = grid;

                this.mWrapper = $("<div />");

                if (this.mGrid._allowCellEditing()) {
                    this.mHiddenElement = $("<input type=\"text\" />").keydown($.proxy(this._onKeyDown, this));
                } else {
                    this.mHiddenElement = $("<input type=\"button\" />"); // use any focusable element other than textbox (to avoid keyboard popup in mobile).
                }

                this.mHiddenElement.css({
                    position: "relative",
                    border: 0,
                    padding: 0,
                    margin: 0,
                    width: 1,
                    height: 1,
                    "font-size": wijmo.grid.isMobileSafari() ? "0em" : "1px"
                });

                this.mHiddenElement.attribute("aria-label", "hiddenElement");

                this.mFakeFocusable = $("<input tabindex=\"-1\" type=\"button\" />").css({
                    position: "relative",
                    width: 1,
                    height: 1,
                    border: 0,
                    padding: 0,
                    margin: 0
                });

                this.mFakeFocusable.attribute("aria-label", "fakeFocusable");

                this.mWrapper.append(this.mHiddenElement).append(this.mFakeFocusable).css({
                    position: "absolute",
                    width: "0px",
                    height: "0px",
                    overflow: "hidden",
                    "z-index": 999999
                });

                container.append(this.mWrapper);
            }
            keyDownEventListener.prototype.dispose = function () {
                if (this.mWrapper) {
                    try  {
                        this.mWrapper.remove();
                    } catch (ex) {
                    } finally {
                        this.mWrapper = null;
                        this.mHiddenElement = null;
                        this.mGrid = null;
                    }
                }
            };

            keyDownEventListener.prototype.focus = function (coord, column) {
                if (coord && coord.length) {
                    var offset = coord.offset();

                    this.mWrapper.offset({
                        top: offset.top,
                        left: offset.left
                    });

                    if ($.browser.msie) {
                        this.mFakeFocusable.focus(); // move focus out of the mHiddenElement first to resolve an issue with changing the IME in IE11
                    }

                    var imeMode = 'auto';
                    if (column && (column instanceof _grid.c1field)) {
                        var field = column;
                        imeMode = (field.options.readOnly === true) ? 'disabled' : field.options.imeMode;
                    }

                    this.mHiddenElement.css("ime-mode", imeMode);
                    if (imeMode !== 'disabled') {
                        this.mHiddenElement.focus();
                    }
                }
            };

            keyDownEventListener.prototype.isHiddenInput = function (element) {
                return element && ((element[0] === this.mHiddenElement[0]) || (element[0] === this.mFakeFocusable[0]));
            };

            keyDownEventListener.prototype.canHandle = function (e) {
                return (this.mGrid._allowCellEditing() && this.isPrintableKeyCode(e));
            };

            keyDownEventListener.prototype.isPrintableKeyCode = function (e) {
                var k = e.keyCode;

                /* ported from the SpeadJS */
                return !e.ctrlKey && !e.altKey && ((k >= 65 && k <= 90) || ((k >= 48 && k <= 57) || (k >= 96 && k <= 105)) || (k >= 186 && k <= 192) || (k >= 220 && k <= 222 || k === 219) || (k >= 106 && k <= 111) || (k === 32) || (k === 61) || (k === 173) || (k === 229 || e.keyCode === 0));
            };

            keyDownEventListener.prototype._onKeyDown = function (e) {
                if (this.canHandle(e)) {
                    //if (targetOuterDiv.length && (targetOuterDiv[0] === this.outerDiv[0])) {
                    this.mGrid._beginEditInternal(e); // pass input (onKeyUp event) to the editor.
                } else {
                    var keyCodeEnum = wijmo.getKeyCodeEnum();

                    switch (e.keyCode) {
                        case keyCodeEnum.ESCAPE:
                        case keyCodeEnum.ENTER:
                            e.preventDefault();
                            break;
                    }
                }
            };
            return keyDownEventListener;
        })();
        _grid.keyDownEventListener = keyDownEventListener;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="interfaces.ts" />
/// <reference path="c1commandbutton.ts" />
/// <reference path="wijgrid.ts" />
/// <reference path="misc.ts" />
var wijmo;
(function (wijmo) {
    (function (grid) {
        var $ = jQuery;

        /** @ignore */
        var cellFormatterHelper = (function () {
            function cellFormatterHelper() {
                this._div = document.createElement("div");
                this._div.style.display = "none";

                if (document && document.body) {
                    document.body.appendChild(this._div);
                }
            }
            cellFormatterHelper.prototype.dispose = function () {
                try  {
                    if (this._div && this._div.parentNode) {
                        this._div.parentNode.removeChild(this._div);
                    }
                } catch (ex) {
                } finally {
                    this._div = null;
                }
            };

            cellFormatterHelper.prototype.format = function ($cell, cellIndex, $container, column, formattedValue, rowInfo) {
                column._initializeCell($cell, cellIndex, $container, formattedValue, rowInfo);
            };

            cellFormatterHelper.prototype.updateHTML = function (container, value, encodeHTML) {
                if (typeof encodeHTML === "undefined") { encodeHTML = false; }
                // container.html(value || "&nbsp;"); // -- very slow in IE when table content is recreated more than once (after paging, sorting etc, especially in flat mode).
                var domContainer = container[0];

                // reset content
                if (domContainer.firstChild) {
                    while (domContainer.firstChild) {
                        domContainer.removeChild(domContainer.firstChild);
                    }
                }

                wijmo.grid.setContent(this._div, encodeHTML, value);

                while (this._div.firstChild) {
                    domContainer.appendChild(this._div.firstChild);
                }
            };
            return cellFormatterHelper;
        })();
        grid.cellFormatterHelper = cellFormatterHelper;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="interfaces.ts"/>
/// <reference path="wijgrid.ts"/>
var wijmo;
(function (wijmo) {
    (function (grid) {
        var $ = jQuery;

        /** @ignore */
        var uiResizer = (function () {
            function uiResizer(wijgrid) {
                this.MIN_WIDTH = 5;
                this._elements = [];
                this._gap = 10;
                this._step = 1;
                this._inProgress = false;
                this._hoveredColumn = null;
                this._startLocation = null;
                this._lastLocation = null;
                this._proxy = null;
                this._wijgrid = wijgrid;

                this._evntFormat = "{0}." + this._wijgrid.widgetName + ".resizer";
            }
            uiResizer.prototype.addElement = function (column) {
                if (column && column.element) {
                    column.element.bind(this._eventKey("mousemove"), $.proxy(this._onMouseMove, this)).bind(this._eventKey("mousedown"), $.proxy(this._onMouseDown, this)).bind(this._eventKey("mouseout"), $.proxy(this._onMouseOut, this));

                    this._elements.push(column);
                }
            };

            uiResizer.prototype.dispose = function () {
                var _this = this;
                $.each(this._elements, function (index, field) {
                    field.element.unbind(_this._eventKey("mousemove"), _this._onMouseMove).unbind(_this._eventKey("mousedown"), _this._onMouseDown).unbind(_this._eventKey("mouseout"), _this._onMouseOut);
                });

                this._detachDocEvents();
            };

            uiResizer.prototype.inProgress = function () {
                return this._inProgress;
            };

            uiResizer.prototype._onMouseMove = function (e) {
                if (!this._inProgress) {
                    var hoveredField = this._getFieldByPos({ x: e.pageX, y: e.pageY });
                    if (hoveredField && hoveredField._canSize() && this._wijgrid._canInteract()) {
                        hoveredField.element.css("cursor", "e-resize");

                        this._hoveredColumn = hoveredField;

                        e.stopPropagation(); // prevent frozener from taking effect
                    } else {
                        this._onMouseOut(e);
                    }
                }
            };

            uiResizer.prototype._onMouseOut = function (e) {
                if (!this._inProgress) {
                    if (this._hoveredColumn) {
                        this._hoveredColumn.element.css("cursor", "");
                        this._hoveredColumn = null;
                    }
                }
            };

            uiResizer.prototype._onMouseDown = function (e) {
                this._hoveredColumn = this._getFieldByPos({ x: e.pageX, y: e.pageY });

                if (this._hoveredColumn && this._hoveredColumn._canSize() && this._wijgrid._canInteract()) {
                    try  {
                        var wijCSS = this._wijgrid.options.wijCSS, defCSS = wijmo.grid.wijgrid.CSS;

                        this._hoveredColumn.element.css("cursor", "");

                        this._docCursor = document.body.style.cursor;
                        document.body.style.cursor = "e-resize";
                        this._startLocation = this._lastLocation = wijmo.grid.bounds(this._hoveredColumn.element);

                        this._proxy = $("<div class=\"" + defCSS.resizingHandle + " " + wijCSS.wijgridResizingHandle + " " + wijCSS.stateHighlight + "\">&nbsp;</div>");

                        var visibleAreaBounds = this._wijgrid._view().getVisibleAreaBounds(true);

                        this._proxy.css({
                            "left": e.pageX, "top": this._startLocation.top,
                            "height": visibleAreaBounds.height + visibleAreaBounds.top - this._startLocation.top
                        });

                        $(document.body).append(this._proxy);
                    } finally {
                        this._attachDocEvents();
                        this._inProgress = true;

                        e.stopPropagation(); // prevent frozener from taking effect
                    }
                }
            };

            uiResizer.prototype._onDocumentMouseMove = function (e) {
                var deltaX = this._step * Math.round((e.pageX - this._lastLocation.left) / this._step);

                this._lastLocation = { left: this._lastLocation.left + deltaX, top: e.pageY, width: undefined, height: undefined };
                this._proxy.css("left", this._lastLocation.left);
            };

            uiResizer.prototype._onDocumentMouseUp = function (e) {
                try  {
                    document.body.style.cursor = this._docCursor;

                    // destroy proxy object
                    this._proxy.remove();

                    if (this._startLocation !== this._lastLocation) {
                        this._wijgrid._fieldResized(this._hoveredColumn, this._startLocation.width, Math.max(this._lastLocation.left - this._startLocation.left, this.MIN_WIDTH));
                    }
                } finally {
                    this._hoveredColumn = null;
                    this._proxy = null;
                    this._detachDocEvents();
                    this._inProgress = false;
                }
            };

            uiResizer.prototype._onSelectStart = function (e) {
                e.preventDefault();
            };

            uiResizer.prototype._attachDocEvents = function () {
                if (!this._inProgress) {
                    $(document).bind(this._eventKey("mousemove"), $.proxy(this._onDocumentMouseMove, this)).bind(this._eventKey("mouseup"), $.proxy(this._onDocumentMouseUp, this));

                    if ($.fn.disableSelection) {
                        $(document.body).disableSelection();
                    }

                    if ("onselectstart" in document) {
                        $(document.body).bind("selectstart", this._onSelectStart);
                    }
                }
            };

            uiResizer.prototype._detachDocEvents = function () {
                if (this._inProgress) {
                    $(document).unbind(this._eventKey("mousemove"), this._onDocumentMouseMove).unbind(this._eventKey("mouseup"), this._onDocumentMouseUp);

                    if ($.fn.enableSelection) {
                        $(document.body).enableSelection();
                    }

                    if ("onselectstart" in document) {
                        $(document.body).unbind("selectstart", this._onSelectStart);
                    }
                }
            };

            uiResizer.prototype._getFieldByPos = function (mouse) {
                for (var i = 0, len = this._elements.length; i < len; i++) {
                    var field = this._elements[i], bounds = wijmo.grid.bounds(field.element), isOver = wijmo.grid.isOver(mouse.y, mouse.x, bounds.top, bounds.left + bounds.width - this._gap, bounds.height, this._gap);

                    if (isOver) {
                        return field;
                    }
                }

                return null;
            };

            uiResizer.prototype._eventKey = function (eventType) {
                var prefix = (this._wijgrid._isTouchEnv()) ? "wij" : "";

                return prefix + wijmo.grid.stringFormat(this._evntFormat, eventType);
            };
            return uiResizer;
        })();
        grid.uiResizer = uiResizer;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="interfaces.ts"/>
/// <reference path="wijgrid.ts" />
/// <reference path="c1groupedfield.ts" />
var wijmo;
(function (wijmo) {
    (function (grid) {
        var $ = jQuery;

        /** @ignore */
        var uiDragndrop = (function () {
            function uiDragndrop(wijgrid) {
                this._scope_guid = "scope_" + wijmo.grid.getUID();
                this._dragEnd = false;
                this.mZIndex = 1000;
                var defCSS = wijmo.grid.wijgrid.CSS;

                this._wijgrid = wijgrid;
                this._wijCSS = this._wijgrid.options.wijCSS;
                this._wrapHtml = "<div class=\"" + this._wijCSS.widget + " " + defCSS.wijgrid + " " + this._wijCSS.wijgrid + " " + this._wijCSS.content + " " + this._wijCSS.cornerAll + "\">" + "<table class=\"" + defCSS.root + " " + defCSS.table + " " + this._wijCSS.wijgridTable + "\">" + "<tr class=\"" + defCSS.headerRow + " " + this._wijCSS.wijgridHeaderRow + "\">" + "</tr>" + "</table>" + "</div>";
            }
            uiDragndrop.prototype.attachGroupArea = function (element) {
                var draggedColumn, self = this;

                if (!$.ui || !$.ui.droppable || !$.ui.draggable) {
                    return;
                }

                element.droppable({
                    scope: this._scope_guid,
                    tolerance: "pointer",
                    greedy: true,
                    accept: function (draggable) {
                        if (self._wijgrid.options.allowColMoving) {
                            draggedColumn = self._getColumnInstance(draggable);

                            if (draggedColumn) {
                                return draggedColumn._canDropToGroupArea();
                            }
                        }
                        return false;
                    },
                    drop: function (e, ui) {
                        if (!self._isInElement(e, ui.draggable) && (draggedColumn = self._getColumnInstance(ui.draggable))) {
                            self._dragEnd = true;
                        }
                    },
                    over: function (e, ui) {
                        var cnt = self._wijgrid._groupAreaColumns().length;

                        self._dropTargetRedirected = (cnt > 0);
                        self._droppableColumn = (cnt > 0) ? self._wijgrid._groupAreaColumns()[cnt - 1] : element; // special case, the drop target is the group area itself

                        element.data("thisDroppableWijField", self._droppableColumn);
                    },
                    out: function (e, ui) {
                        if (self._droppableColumn === element.data("thisDroppableWijField")) {
                            self._droppableColumn = null;
                        }
                    }
                });
            };

            uiDragndrop.prototype.attach = function (column) {
                var element, draggedColumn, defCSS = wijmo.grid.wijgrid.CSS, self = this;

                if (!$.ui.droppable || !$.ui.draggable) {
                    return;
                }

                if (!column || !(element = column.element)) {
                    return;
                }

                element.draggable({
                    helper: function (e) {
                        var result;

                        if (column instanceof grid.c1groupedfield) {
                            result = element.clone();
                        } else {
                            result = element.clone().wrap(self._wrapHtml).width(element.width()).height(element.height()).closest("." + defCSS.wijgrid);
                        }

                        result.addClass(defCSS.dndHelper + " " + self._wijCSS.wijgridDndHelper).css("z-index", self.mZIndex = wijmo.grid.getZIndex(self._wijgrid.mOuterDiv, 1000)); // Update the z-index property. wijdialog increases its z-index property every time when the dialog position is changed.

                        return result;
                    },
                    appendTo: "body",
                    //cursor: "pointer",
                    scope: self._scope_guid,
                    drag: function (e, ui) {
                        self._hideArrows();

                        if (self._droppableColumn && !self._isInElement(e, element)) {
                            // indicate insertion position
                            var $arrowsTarget = self._droppableColumn.element;
                            if (!$arrowsTarget) {
                                $arrowsTarget = self._droppableColumn;
                            }

                            self._showArrows($arrowsTarget, self._getPosition(column, self._droppableColumn, e, ui));
                        }
                    },
                    start: function (e, ui) {
                        if (self._wijgrid._canInteract() && self._wijgrid.options.allowColMoving && (self._wijgrid._UIResizer() == null || !self._wijgrid._UIResizer().inProgress())) {
                            var dragColumn = column, dragInGroup = (column instanceof grid.c1groupedfield), dragSource = dragInGroup ? "groupArea" : "columns";

                            if (dragInGroup) {
                                dragColumn = self._wijgrid._findInstance(column.options);
                            }

                            var opt = dragColumn.options;

                            if (column._canDrag() && self._wijgrid._trigger("columnDragging", null, { drag: opt, dragSource: dragSource })) {
                                self._wijgrid._trigger("columnDragged", null, { drag: opt, dragSource: dragSource });
                                return true;
                            }
                        }

                        return false;
                    },
                    stop: function (e, ui) {
                        self._hideArrows();

                        try  {
                            if (self._dragEnd) {
                                if (!self._droppableColumn.element) {
                                    self._wijgrid._handleDragnDrop(column, null, "left", column instanceof grid.c1groupedfield, true);
                                } else {
                                    self._wijgrid._handleDragnDrop(column, self._droppableColumn, self._getPosition(column, self._droppableColumn, e, ui), column instanceof grid.c1groupedfield, self._droppableColumn instanceof grid.c1groupedfield);
                                }
                            }
                        } finally {
                            self._droppableColumn = null;
                            self._dragEnd = false;
                        }
                    }
                }).droppable({
                    hoverClass: self._wijCSS.stateHover,
                    scope: self._scope_guid,
                    tolerance: "pointer",
                    greedy: true,
                    accept: function (draggable) {
                        if (self._wijgrid.options.allowColMoving) {
                            if (element[0] !== draggable[0]) {
                                draggedColumn = self._getColumnInstance(draggable); // dragged column

                                if (draggedColumn) {
                                    return draggedColumn._canDropTo(column);
                                }
                            }
                        }
                        return false;
                    },
                    drop: function (e, ui) {
                        if (draggedColumn = self._getColumnInstance(ui.draggable)) {
                            // As droppable.drop fires before draggable.stop, let draggable to finish the action.
                            // Otherwise exception is thrown as during re-rendering element bound to draggable will be already deleted.
                            self._dragEnd = true;
                            // an alternative:
                            //window.setTimeout(function () {
                            //wijgrid._handleDragnDrop(draggedWijField, wijField, _getPosition(draggedWijField, wijField, e, ui));
                            //}, 100);
                        }
                    },
                    over: function (e, ui) {
                        self._dropTargetRedirected = false;
                        self._droppableColumn = column;

                        // to track when droppable.over event of other element fires before droppable.out of that element.
                        element.data("thisDroppableWijField", self._droppableColumn);
                    },
                    out: function (e, ui) {
                        if (self._droppableColumn === column.element.data("thisDroppableWijField")) {
                            self._droppableColumn = null;
                        }
                    }
                }); // ~droppable
            };

            uiDragndrop.prototype.detach = function (column) {
                var element;

                if (column && (element = column.element)) {
                    if (element.data("ui-draggable")) {
                        element.draggable("destroy");
                    }

                    if (element.data("ui-droppable")) {
                        element.droppable("destroy");
                    }
                }
            };

            uiDragndrop.prototype.dispose = function () {
                if (this._$topArrow) {
                    this._$topArrow.remove();
                    this._$topArrow = null;
                }

                if (this._$bottomArrow) {
                    this._$bottomArrow.remove();
                    this._$bottomArrow = null;
                }
            };

            // private
            uiDragndrop.prototype._getColumnInstance = function (draggable) {
                var instance = draggable.data(grid.widgetEmulator.DATA_INSTANCE_PROP);

                if (!instance) {
                    throw "Unable to get a column instance";
                }

                return instance;
            };

            // position: "left", "right", "center"
            uiDragndrop.prototype._showArrows = function (element, position) {
                this._topArrow().css("z-index", this.mZIndex).show().position({
                    my: "center",
                    at: position + " top",
                    of: element,
                    collision: "none"
                });

                this._bottomArrow().css("z-index", this.mZIndex).show().position({
                    my: "center",
                    at: position + " bottom",
                    of: element,
                    collision: "none"
                });
            };

            uiDragndrop.prototype._hideArrows = function () {
                this._topArrow().hide();
                this._bottomArrow().hide();
            };

            uiDragndrop.prototype._topArrow = function () {
                if (!this._$topArrow) {
                    this._$topArrow = $("<div />").addClass(wijmo.grid.wijgrid.CSS.dndArrowTopContainer + " " + this._wijCSS.wijgridDndArrowTopContainer).append($("<span />").addClass(this._wijCSS.icon + " " + this._wijCSS.iconArrowThickDown)).hide().appendTo(document.body);
                }

                return this._$topArrow;
            };

            uiDragndrop.prototype._bottomArrow = function () {
                if (!this._$bottomArrow) {
                    this._$bottomArrow = $("<div />").addClass(wijmo.grid.wijgrid.CSS.dndArrowBottomContainer + " " + this._wijCSS.wijgridDndArrowBottomContainer).append($("<span />").addClass(this._wijCSS.icon + " " + this._wijCSS.iconArrowThickUp)).hide().appendTo(document.body);
                }

                return this._$bottomArrow;
            };

            uiDragndrop.prototype._isInElement = function (e, element) {
                var bounds = wijmo.grid.bounds(element, false);
                return ((e.pageX > bounds.left && e.pageX < bounds.left + bounds.width) && (e.pageY > bounds.top && e.pageY < bounds.top + bounds.height));
            };

            uiDragndrop.prototype._getPosition = function (drag, drop, e, ui) {
                if (!drop.element) {
                    return "left";
                }

                if (this._dropTargetRedirected) {
                    return "right";
                }

                var bounds = wijmo.grid.bounds(drop.element, false), sixth = bounds.width / 6, centerX = bounds.left + (bounds.width / 2), result = "right", distance;

                if (e.pageX < centerX) {
                    result = "left";
                }

                if (drop instanceof grid.c1groupedfield) {
                    if (drag instanceof grid.c1groupedfield) {
                        distance = drop.options.groupedIndex - drag.options.groupedIndex;

                        if (Math.abs(distance) === 1) {
                            result = (distance < 0) ? "left" : "right";
                        }
                    }

                    return result;
                }

                // both drag and drop are non-grouped columns
                distance = drop.options._linearIdx - drag.options._linearIdx;

                if (grid.c1bandfield.test(drop.options) && (drag.options._parentIdx !== drop.options._travIdx) && (Math.abs(e.pageX - centerX) < sixth)) {
                    return "center";
                }

                // drag and drop are contiguous items of the same level
                if (drag.options._parentIdx === drop.options._parentIdx && Math.abs(distance) === 1) {
                    result = (distance < 0) ? "left" : "right";
                }

                return result;
            };
            return uiDragndrop;
        })();
        grid.uiDragndrop = uiDragndrop;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="interfaces.ts" />
/// <reference path="wijgrid.ts" />
/// <reference path="misc.ts" />
var wijmo;
(function (wijmo) {
    (function (grid) {
        var $ = jQuery;

        /** @ignore */
        var cellStyleFormatterHelper = (function () {
            function cellStyleFormatterHelper(wijgrid) {
                if (!wijgrid) {
                    throw "invalid arguments";
                }

                this._wijgrid = wijgrid;
            }
            cellStyleFormatterHelper.prototype.format = function ($cell, cellIndex, column, rowInfo, state, cellAttr, cellStyle) {
                var $rs = wijmo.grid.renderState, $rt = wijmo.grid.rowType, rowType = rowInfo.type, groupRowCellInfo = null;

                if (cellIndex < this._wijgrid._virtualLeaves().length) {
                    column = null; //TODO: check
                }

                if (rowType === 16 /* groupHeader */ || rowType === 32 /* groupFooter */) {
                    column = null;

                    if (cellAttr && (groupRowCellInfo = cellAttr.groupInfo)) {
                        column = this._wijgrid._leaves()[groupRowCellInfo.leafIndex]; // replace "column" with the one associated with the $cell's content
                        //delete cellAttr.groupInfo;
                    }
                }

                var args = {
                    $cell: $cell,
                    state: state,
                    row: rowInfo,
                    column: column && column.options,
                    _cellIndex: cellIndex,
                    _purpose: groupRowCellInfo ? groupRowCellInfo.purpose : undefined
                };

                if (state & 1 /* rendering */) {
                    this._renderingStateFormatter(args, cellAttr, cellStyle);
                } else {
                    this._currentStateFormatter(args, state & 2 /* current */);

                    //hoveredStateFormatter(args, state & $rs.hovered);
                    this._selectedStateFormatter(args, state & 8 /* selected */);

                    if (rowType !== 1 /* header */) {
                        if ((state & 2 /* current */) || (state & 8 /* selected */)) {
                            args.$cell.addClass(this._wijgrid.options.wijCSS.stateDefault); // make bootstrap happy
                        } else {
                            args.$cell.removeClass(this._wijgrid.options.wijCSS.stateDefault);
                        }
                    }
                }

                if ($.isFunction(this._wijgrid.options.cellStyleFormatter)) {
                    this._wijgrid.options.cellStyleFormatter(args);
                }
            };

            // private ---
            cellStyleFormatterHelper.prototype._renderingStateFormatter = function (args, cellAttr, cellStyles) {
                var $rt = wijmo.grid.rowType, key, value, leaf = args.column, rowType = args.row.type, defCSS = wijmo.grid.wijgrid.CSS, wijCSS = this._wijgrid.options.wijCSS;

                switch (rowType) {
                    case 1 /* header */:
                        args.$cell.addClass(defCSS.TH + " " + wijCSS.wijgridTH);
                        break;

                    default:
                        args.$cell.addClass(defCSS.TD + " " + wijCSS.wijgridTD);
                }

                if ((rowType & 2 /* data */) && leaf && leaf.textAlignment) {
                    switch (leaf.textAlignment.toLowerCase()) {
                        case "left":
                            args.$cell.addClass(defCSS.cellAlignLeft + " " + wijCSS.wijgridCellAlignLeft);
                            break;

                        case "right":
                            args.$cell.addClass(defCSS.cellAlignRight + " " + wijCSS.wijgridCellAlignRight);
                            break;

                        case "center":
                            args.$cell.addClass(defCSS.cellAlignCenter + " " + wijCSS.wijgridCellAlignCenter);
                            break;
                    }
                }

                // copy attributes
                if (cellAttr) {
                    for (key in cellAttr) {
                        if (cellAttr.hasOwnProperty(key)) {
                            value = cellAttr[key];

                            if ((key === "groupInfo" || key === "colSpan" || key === "rowSpan") && !(value > 1)) {
                                continue;
                            }

                            if (key === "class") {
                                args.$cell.addClass(value);
                            } else {
                                args.$cell.attr(key, value);
                            }
                        }
                    }
                }

                // copy inline css
                if (cellStyles) {
                    for (key in cellStyles) {
                        if (cellStyles.hasOwnProperty(key)) {
                            if (key === "paddingLeft") {
                                args.$cell.children("." + defCSS.cellContainer).css(key, cellStyles[key]);
                                continue;
                            }
                            args.$cell.css(key, cellStyles[key]);
                        }
                    }
                }

                if (args._cellIndex < this._wijgrid._virtualLeaves().length) {
                    args.$cell.attr({ "role": "rowheader", "scope": "row" }).addClass(wijCSS.stateDefault + " " + wijCSS.content + " " + defCSS.rowHeader + " " + wijCSS.wijgridRowHeader);
                } else {
                    switch (rowType) {
                        case (1 /* header */):
                            args.$cell.attr({ "role": "columnheader", "scope": "col" });
                            break;
                        case (64 /* footer */):
                            args.$cell.attr({ "role": "gridcell", "scope": "col" });
                            break;
                        default:
                            args.$cell.attr("role", "gridcell");
                    }
                }

                if (rowType & 2 /* data */) {
                    if (args._cellIndex >= 0 && leaf) {
                        args.$cell.attr("headers", window.escape(leaf.headerText));

                        if (leaf.readOnly) {
                            args.$cell.attribute("aria-readonly", true);
                        }

                        if (leaf.dataIndex >= 0) {
                            args.$cell.addClass("wijdata-type-" + wijmo.grid.getDataType(leaf));
                        }
                    }
                }

                if (rowType === 16 /* groupHeader */ || rowType === 32 /* groupFooter */) {
                    // append wijdata-type class only to the aggregate cells of the group row, not grouped cells.
                    if (leaf && args._purpose === 1 /* aggregateCell */) {
                        args.$cell.addClass("wijdata-type-" + wijmo.grid.getDataType(leaf));
                    }
                }
            };

            cellStyleFormatterHelper.prototype._currentStateFormatter = function (args, add) {
                var $rt = wijmo.grid.rowType, defCSS = wijmo.grid.wijgrid.CSS, wijCSS = this._wijgrid.options.wijCSS;

                if (add) {
                    args.$cell.addClass(wijCSS.stateActive);

                    if (args.row.type === 1 /* header */) {
                        args.$cell.addClass(defCSS.currentHeaderCell + " " + wijCSS.wijgridCurrentHeaderCell);
                    } else {
                        args.$cell.addClass(defCSS.currentCell + " " + wijCSS.wijgridCurrentCell);
                    }
                } else {
                    args.$cell.removeClass(wijCSS.stateActive);

                    if (args.row.type === 1 /* header */) {
                        args.$cell.removeClass(defCSS.currentHeaderCell + " " + wijCSS.wijgridCurrentHeaderCell);
                    } else {
                        args.$cell.removeClass(defCSS.currentCell + " " + wijCSS.wijgridCurrentCell);
                    }
                }
            };

            cellStyleFormatterHelper.prototype._hoveredStateFormatter = function (args, add) {
                if (add) {
                } else {
                }
            };

            cellStyleFormatterHelper.prototype._selectedStateFormatter = function (args, add) {
                var wijCSS = this._wijgrid.options.wijCSS;

                if (add) {
                    args.$cell.addClass(wijCSS.stateHighlight).attribute("aria-selected", "true");
                } else {
                    args.$cell.removeClass(wijCSS.stateHighlight).removeAttribute("aria-selected");
                }
            };
            return cellStyleFormatterHelper;
        })();
        grid.cellStyleFormatterHelper = cellStyleFormatterHelper;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="interfaces.ts" />
/// <reference path="wijgrid.ts" />
/// <reference path="misc.ts" />
var wijmo;
(function (wijmo) {
    (function (grid) {
        var $ = jQuery;

        /** @ignore */
        var rowStyleFormatterHelper = (function () {
            function rowStyleFormatterHelper(wijgrid) {
                if (!wijgrid) {
                    throw "invalid arguments";
                }

                this._wijgrid = wijgrid;
            }
            rowStyleFormatterHelper.prototype.format = function (rowInfo, rowAttr, rowStyle) {
                var $rs = wijmo.grid.renderState, $rt = wijmo.grid.rowType, state = rowInfo.state, args = rowInfo;

                if (state & 1 /* rendering */) {
                    this._renderingStateFormatter(args, rowAttr, rowStyle);
                } else {
                    this._currentStateFormatter(args, (state & 2 /* current */) !== 0);
                    this._hoveredStateFormatter(args, (state & 4 /* hovered */) !== 0);
                    this._selectedStateFormatter(args, (state & 8 /* selected */) !== 0);
                }

                if ($.isFunction(this._wijgrid.options.rowStyleFormatter)) {
                    this._wijgrid.options.rowStyleFormatter(args);
                }

                //Due to the row height may be changed via rowStyleFormatter, we should store the height after rowStyleFormatter applied.
                if ((state & 1 /* rendering */) && args.$rows[0].style.height) {
                    args.$rows.each(function () {
                        $.data(this, "customHeight", this.style.height);
                    });
                }
            };

            rowStyleFormatterHelper.prototype._groupFormatter = function (rowInfo) {
                var rse = wijmo.grid.renderStateEx, extInfo = rowInfo._extInfo, defCSS = wijmo.grid.wijgrid.CSS, wijCSS = this._wijgrid.options.wijCSS;

                if (extInfo.state & 1 /* hidden */) {
                    rowInfo.$rows.css("display", "none");
                    //rowInfo.$rows.attr("aria-hidden", true);
                } else {
                    rowInfo.$rows.css("display", "");
                    //rowInfo.$rows.removeAttr("aria-hidden");
                }

                if (rowInfo.type & 16 /* groupHeader */) {
                    var gi = this._wijgrid._groupedLeaves()[rowInfo._extInfo.groupLevel - 1].options.groupInfo, expandedIcon = gi.expandedImageClass || wijCSS.iconArrowRightDown, collapsedIcon = gi.collapsedImageClass || wijCSS.iconArrowRight, toggleBtn = wijmo.grid.rowAccessor.getCell$(rowInfo.$rows, this._wijgrid._showRowHeader() ? 1 : 0).find("." + defCSS.groupToggleVisibilityButton);

                    if (extInfo.state & 2 /* collapsed */) {
                        rowInfo.$rows.attribute("aria-expanded", false);

                        rowInfo.$rows.removeClass(defCSS.groupHeaderRowExpanded + " " + wijCSS.wijgridGroupHeaderRowExpanded).addClass(defCSS.groupHeaderRowCollapsed + " " + wijCSS.wijgridGroupHeaderRowCollapsed);

                        toggleBtn.removeClass(expandedIcon).addClass(collapsedIcon);
                    } else {
                        rowInfo.$rows.attribute("aria-expanded", true);

                        rowInfo.$rows.removeClass(defCSS.groupHeaderRowCollapsed + " " + wijCSS.wijgridGroupHeaderRowCollapsed).addClass(defCSS.groupHeaderRowExpanded + " " + wijCSS.wijgridGroupHeaderRowExpanded);

                        toggleBtn.removeClass(collapsedIcon).addClass(expandedIcon);
                    }
                }
            };

            rowStyleFormatterHelper.prototype._masterFormatter = function (rowInfo) {
                var defCSS = wijmo.grid.wijgrid.CSS, wijCSS = this._wijgrid.options.wijCSS, toggleBtn = rowInfo.$rows.find("." + defCSS.groupToggleVisibilityButton), expandedIcon = wijCSS.iconArrowRightDown, collapsedIcon = wijCSS.iconArrowRight;

                if (rowInfo._extInfo.state & 2 /* collapsed */) {
                    rowInfo.$rows.attribute("aria-expanded", false);

                    toggleBtn.removeClass(expandedIcon).addClass(collapsedIcon);
                } else {
                    rowInfo.$rows.attribute("aria-expanded", true);

                    toggleBtn.removeClass(collapsedIcon).addClass(expandedIcon);
                }
            };

            // * private
            rowStyleFormatterHelper.prototype._renderingStateFormatter = function (args, rowAttr, rowStyle) {
                var defCSS = wijmo.grid.wijgrid.CSS, wijCSS = this._wijgrid.options.wijCSS, className, contentClass = defCSS.row + " " + wijCSS.wijgridRow + " " + wijCSS.content, $rt = wijmo.grid.rowType, rse = wijmo.grid.renderStateEx, key;

                $.each(args.$rows, function (index, value) {
                    if ($(value).children().length > 0) {
                        $(value).attr("role", "row");
                    }
                });

                // copy attributes
                if (rowAttr) {
                    for (key in rowAttr) {
                        if (rowAttr.hasOwnProperty(key)) {
                            if (key === "class") {
                                args.$rows.addClass(rowAttr[key]);
                            } else {
                                args.$rows.attr(key, rowAttr[key]);
                            }
                        }
                    }
                }

                // copy inline css
                if (rowStyle) {
                    for (key in rowStyle) {
                        if (rowStyle.hasOwnProperty(key)) {
                            args.$rows.css(key, rowStyle[key]);
                        }
                    }
                }

                if (args._extInfo.groupLevel) {
                    args.$rows.attribute("aria-level", args._extInfo.groupLevel);
                }

                // hide collapsed row
                if (args._extInfo.state & 1 /* hidden */) {
                    args.$rows.css("display", "none");
                    // args.$rows.attr("aria-hidden", true);
                }

                switch (args.type & ~(4 /* dataAlt */ | 512 /* dataDetail */ | 256 /* dataHeader */)) {
                    case (1 /* header */):
                        className = defCSS.headerRow + " " + wijCSS.wijgridHeaderRow;
                        break;

                    case (2 /* data */):
                        className = contentClass + " " + defCSS.dataRow + " " + wijCSS.wijgridDataRow;

                        if (args.type & 4 /* dataAlt */) {
                            className += " " + defCSS.altRow + " " + wijCSS.wijgridAltRow;
                        }

                        break;

                    case (128 /* emptyDataRow */):
                        className = contentClass + " " + defCSS.emptyDataRow + " " + wijCSS.wijgridEmptyDataRow;
                        break;

                    case (8 /* filter */):
                        className = defCSS.filterRow + " " + wijCSS.wijgridFilterRow;
                        break;

                    case (16 /* groupHeader */):
                        $(args.$rows.last()).attribute({
                            "id": "GH" + args._extInfo.groupIndex + "-" + args._extInfo.groupLevel,
                            "aria-expanded": ((args._extInfo.state & 2 /* collapsed */) === 0)
                        });

                        className = contentClass + " " + defCSS.groupHeaderRow + " " + wijCSS.wijgridGroupHeaderRow + " ";

                        className += (args._extInfo.state & 2 /* collapsed */) ? defCSS.groupHeaderRowCollapsed + " " + wijCSS.wijgridGroupHeaderRowCollapsed : defCSS.groupHeaderRowExpanded + " " + wijCSS.wijgridGroupHeaderRowExpanded;

                        break;

                    case (32 /* groupFooter */):
                        $(args.$rows.last()).attr("id", "GF" + args._extInfo.groupIndex + "-" + args._extInfo.groupLevel);

                        className = contentClass + " " + defCSS.groupFooterRow + " " + wijCSS.wijgridGroupFooterRow;
                        break;

                    case (1024 /* detail */):
                        className = contentClass + " " + defCSS.detailRow + " " + wijCSS.wijgridDetailRow;
                        break;

                    case (64 /* footer */):
                        className = defCSS.footerRow + " " + wijCSS.wijgridFooterRow + " " + wijCSS.stateDefault + " " + wijCSS.stateHighlight;
                        break;

                    default:
                        throw wijmo.grid.stringFormat("unknown rowType: {0}", args.type);
                }

                args.$rows.addClass(className);
            };

            rowStyleFormatterHelper.prototype._currentStateFormatter = function (args, flag) {
                if (this._wijgrid._showRowHeader()) {
                    var wijCSS = this._wijgrid.options.wijCSS, defCSS = wijmo.grid.wijgrid.CSS;

                    // make deal with the row header cell
                    if (flag) {
                        $(args.$rows[0].cells[0]).addClass(wijCSS.stateActive + " " + defCSS.currentRowHeaderCell + " " + wijCSS.wijgridCurrentRowHeaderCell);
                    } else {
                        $(args.$rows[0].cells[0]).removeClass(wijCSS.stateActive + " " + defCSS.currentRowHeaderCell + " " + wijCSS.wijgridCurrentRowHeaderCell);
                    }
                }
            };

            rowStyleFormatterHelper.prototype._hoveredStateFormatter = function (args, flag) {
                var wijCSS = this._wijgrid.options.wijCSS;

                if (flag) {
                    args.$rows.addClass(wijCSS.stateDefault + " " + wijCSS.stateHover);
                } else {
                    args.$rows.removeClass(wijCSS.stateDefault + " " + wijCSS.stateHover);

                    if (args.type & 2 /* data */) {
                        args.$rows.addClass(wijCSS.wijgridDataRow); // bootsrap issue, both stateDefault and wijgridDataRow contains the same class "btn", restore it.
                    }
                }
            };

            rowStyleFormatterHelper.prototype._selectedStateFormatter = function (args, flag) {
                if (flag) {
                } else {
                }
            };
            return rowStyleFormatterHelper;
        })();
        grid.rowStyleFormatterHelper = rowStyleFormatterHelper;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="interfaces.ts"/>
var wijmo;
(function (wijmo) {
    (function (grid) {
        var $ = jQuery;

        /** @ignore */
        var tally = (function () {
            function tally(parser) {
                this._sum = 0;
                this._sum2 = 0;
                this._cntNumbers = 0;
                this._cntStrings = 0;
                this._cntDates = 0;
                this._max = 0;
                this._min = 0;
                this._minDate = 0;
                this._maxDate = 0;
                this._parser = parser;
            }
            tally.getValueString = function (value, column, strConverter) {
                var opt = column.options;

                if (typeof (value) !== "string") {
                    if ((opt.aggregate === "count") && (opt.dataType !== "number")) {
                        opt = {
                            dataType: "number",
                            dataFormatString: "n0"
                        };
                    }

                    value = strConverter.toStr(opt, value);
                }

                return value;
            };

            tally.prototype.add = function (value) {
                if (value === null) {
                    return;
                }

                var typeOf = (value instanceof Date) ? "datetime" : typeof (value);

                // * count strings *
                var foo = value.toString();

                if (this._cntStrings++ === 0) {
                    this._minString = this._maxString = foo;
                }

                if (foo < this._minString) {
                    this._minString = foo;
                }

                if (foo > this._maxString) {
                    this._maxString = foo;
                }

                // * count numbers *
                var numberValue = this._parseValue(value);
                if ((typeof (numberValue) === "number") && !wijmo.grid.isNaN(numberValue)) {
                    value = numberValue;

                    if (this._cntNumbers++ === 0) {
                        this._min = this._max = value;
                    }

                    this._sum += value;
                    this._sum2 += value * value;

                    if (value < this._min) {
                        this._min = value;
                    }

                    if (value > this._max) {
                        this._max = value;
                    }
                } else {
                    // * count dates *
                    if (typeOf === "datetime") {
                        foo = value.getTime();

                        if (this._cntDates++ === 0) {
                            this._minDate = this._maxDate = foo;
                        }

                        if (foo < this._minDate) {
                            this._minDate = foo;
                        }

                        if (foo > this._maxDate) {
                            this._maxDate = foo;
                        }
                    }
                }
            };

            tally.prototype.getValue = function (column) {
                var opt = column.options;

                if (this._cntNumbers && ((opt.dataType === "number" || opt.dataType === "currency") || (this._cntNumbers == this._cntStrings))) {
                    return this._getValue(opt.aggregate);
                }

                // we only support max/min and count for dates
                if (this._cntDates && (opt.dataType === "datetime")) {
                    switch (opt.aggregate) {
                        case "max":
                            return new Date(this._maxDate);

                        case "min":
                            return new Date(this._minDate);

                        case "count":
                            return this._cntStrings;
                    }
                }

                // we only support max/min and count for strings
                if (this._cntStrings) {
                    switch (opt.aggregate) {
                        case "max":
                            return this._maxString;

                        case "min":
                            return this._minString;

                        case "count":
                            return this._cntStrings;
                    }
                }

                return "";
            };

            tally.prototype._parseValue = function (value) {
                var typeOf = typeof (value);

                if (typeOf === "number") {
                    return value;
                }

                if (typeOf === "string" && $.trim(value) === "") {
                    return 0;
                }

                if (this._parser) {
                    var testValue;

                    try  {
                        testValue = this._parser.parse({ dataType: "currency" }, value);
                    } catch (e) {
                        testValue = NaN;
                    }

                    if (grid.isNaN(testValue)) {
                        testValue = parseFloat(value);
                    }

                    if (!grid.isNaN(testValue)) {
                        return testValue;
                    }
                }

                return value;
            };

            tally.prototype._getValue = function (aggregate) {
                switch (aggregate) {
                    case "average":
                        return (this._cntNumbers === 0) ? 0 : this._sum / this._cntNumbers;

                    case "count":
                        return this._cntStrings;

                    case "max":
                        return this._max;

                    case "min":
                        return this._min;

                    case "sum":
                        return this._sum;

                    case "std":
                        if (this._cntNumbers <= 1) {
                            return 0;
                        }

                        return Math.sqrt(this._getValue("var"));

                    case "stdPop":
                        if (this._cntNumbers <= 1) {
                            return 0;
                        }

                        return Math.sqrt(this._getValue("varPop"));

                    case "var":
                        if (this._cntNumbers <= 1) {
                            return 0;
                        }

                        return this._getValue("varPop") * this._cntNumbers / (this._cntNumbers - 1);

                    case "vapPop":
                        if (this._cntNumbers <= 1) {
                            return 0;
                        }

                        var tmp = this._sum / this._cntNumbers;
                        return this._sum2 / this._cntNumbers - tmp * tmp;
                }

                return 0;
            };
            return tally;
        })();
        grid.tally = tally;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="interfaces.ts"/>
/// <reference path="wijgrid.ts"/>
var wijmo;
(function (wijmo) {
    (function (grid) {
        var $ = jQuery;

        /** @ignore */
        var uiFrozener = (function () {
            function uiFrozener(wijgrid) {
                this._docEventsUID = "wijgridfrozener" + wijmo.grid.getUID();
                this._docEventsAttached = false;
                this._newStaticIndex = -1;
                this._staticColumnIndex = -1;
                this._staticRowIndex = -1;
                this._staticOffsetH = 0;
                this._staticOffsetV = 0;
                this._inProgress = false;
                this._wijgrid = wijgrid;

                this.refresh();
            }
            uiFrozener.prototype.inProgress = function () {
                return this._inProgress;
            };

            uiFrozener.prototype.refresh = function () {
                this.dispose();

                var freezingMode = this._wijgrid._lgGetFreezingMode();

                if (freezingMode !== "none" && (this._wijgrid._lgGetScrollMode() !== "none")) {
                    this._$outerDiv = this._wijgrid.mOuterDiv.find("." + wijmo.grid.wijgrid.CSS.fixedView);
                    this._superPanel = this._wijgrid._view()._getSuperPanel();
                    this._staticOffsetH = this._wijgrid._getStaticOffsetIndex(false);
                    this._staticOffsetV = this._wijgrid._getStaticOffsetIndex(true);
                    this._staticColumnIndex = this._wijgrid._getStaticIndex(false);
                    this._staticRowIndex = this._wijgrid._getStaticIndex(true);
                    this._visibleBounds = this._wijgrid._view().getVisibleContentAreaBounds(); //.getVisibleAreaBounds();

                    var allFixedAreaBounds = wijmo.grid.bounds(this._$outerDiv.find(".wijmo-wijgrid-split-area-nw")), containerBounds = wijmo.grid.bounds(this._$outerDiv);

                    // if staticColumnsAlignment is "right" then create vbar only when staticColumnIndex is set (vbar dragging ability is disabled in this case)
                    if ((freezingMode === "both" || freezingMode === "columns") && (this._wijgrid._lgGetStaticColumnsAlignment() !== "right" || this._staticColumnIndex >= 0)) {
                        this._createVBar(this._visibleBounds, allFixedAreaBounds, containerBounds);
                    }

                    if ((freezingMode === "both" || freezingMode === "rows") && !this._wijgrid._serverSideVirtualScrolling()) {
                        this._createHBar(this._visibleBounds, allFixedAreaBounds, containerBounds);
                    }
                }
            };

            uiFrozener.prototype.ensureVBarHeight = function () {
                if (this._$vBar) {
                    var allFixedAreaBounds = wijmo.grid.bounds(this._$outerDiv.find(".wijmo-wijgrid-split-area-nw"));

                    this._visibleBounds = this._wijgrid._view().getVisibleContentAreaBounds(); //.getVisibleAreaBounds();

                    this._$vBar.height(this._visibleBounds.height + this._visibleBounds.top - allFixedAreaBounds.top);
                }
            };

            uiFrozener.prototype.dispose = function () {
                if (this._$hBar) {
                    this._$hBar.remove();
                    this._$hBar = null;
                }

                if (this._$vBar) {
                    this._$vBar.remove();
                    this._$vBar = null;
                }

                if (this._$proxy) {
                    this._$proxy.remove();
                    this._$proxy = null;
                }

                this._$outerDiv = null;
                this._superPanel = null;

                this._detachDocEvents();
            };

            uiFrozener.prototype._createVBar = function (visibleBounds, allFixedAreaBounds, containerBounds) {
                var lAlign = (this._wijgrid._lgGetStaticColumnsAlignment() !== "right"), leftPos = lAlign ? allFixedAreaBounds.width + allFixedAreaBounds.left : allFixedAreaBounds.left - 2, self = this, defCSS = wijmo.grid.wijgrid.CSS, wijCSS = this._wijgrid.options.wijCSS;

                if (leftPos <= visibleBounds.left + visibleBounds.width) {
                    this._$vBar = $("<div><div></div></div>").addClass(defCSS.freezingHandleV + " " + wijCSS.wijgridFreezingHandleV).addClass(lAlign ? "" : "not-allowed").css({
                        left: leftPos - containerBounds.left,
                        top: allFixedAreaBounds.top - containerBounds.top,
                        height: visibleBounds.height + visibleBounds.top - allFixedAreaBounds.top
                    }).bind("mousedown", function (e) {
                        e.data = true; // vertical bar
                        self._onBarMouseDown.apply(self, arguments);
                    }).appendTo(this._$outerDiv);

                    // content
                    this._$vBar.find("div").addClass(defCSS.freezingHandleContent + " " + wijCSS.header);
                }
            };

            uiFrozener.prototype._createHBar = function (visibleBounds, allFixedAreaBounds, containerBounds) {
                var topPos = allFixedAreaBounds.top + allFixedAreaBounds.height, lAlign = (this._wijgrid._lgGetStaticColumnsAlignment() !== "right"), self = this, defCSS = wijmo.grid.wijgrid.CSS, wijCSS = this._wijgrid.options.wijCSS;

                if (topPos <= visibleBounds.top + visibleBounds.height) {
                    this._$hBar = $("<div><div></div></div>").addClass(defCSS.freezingHandleH + " " + wijCSS.wijgridFreezingHandleH).css({
                        left: lAlign ? allFixedAreaBounds.left - containerBounds.left : 0,
                        top: topPos - containerBounds.top,
                        width: lAlign ? visibleBounds.width + visibleBounds.left - allFixedAreaBounds.left : visibleBounds.width
                    }).bind("mousedown", function (e) {
                        e.data = false; // horizontal bar
                        self._onBarMouseDown.apply(self, arguments);
                    }).appendTo(this._$outerDiv);

                    // content
                    this._$hBar.find("div").addClass(defCSS.freezingHandleContent + " " + wijCSS.header);
                }
            };

            // e.data: true = vertical, false = horizontal
            uiFrozener.prototype._onBarMouseDown = function (e) {
                if (this._wijgrid.options.disabled || (this._wijgrid._lgGetStaticColumnsAlignment() === "right" && e.data)) {
                    return false;
                }

                var defCSS = wijmo.grid.wijgrid.CSS, wijCSS = this._wijgrid.options.wijCSS;

                this._visibleBounds = this._wijgrid._view().getVisibleContentAreaBounds(); //.getVisibleAreaBounds();

                this._newStaticIndex = e.data ? this._staticColumnIndex : this._staticRowIndex;

                this._$proxy = $("<div class=\"" + defCSS.resizingHandle + " " + wijCSS.wijgridResizingHandle + " " + wijCSS.header + "\"></div>").appendTo(document.body);

                this._attachDocEvents(e.data);

                this._inProgress = true;

                // prevent selectionUI from taking effect
                e.stopPropagation();
            };

            uiFrozener.prototype._onDocumentMouseMove = function (e) {
                if (e.data && this._superPanel.options.hScroller.scrollValue) {
                    this._superPanel.hScrollTo(0);
                } else if (!e.data && this._superPanel.options.vScroller.scrollValue) {
                    this._superPanel.vScrollTo(0);
                }

                this._showPosition(e);
            };

            uiFrozener.prototype._onDocumentMouseUp = function (e) {
                try  {
                    if (this._$proxy) {
                        this._$proxy.remove();
                    }

                    this._detachDocEvents();

                    if (e.data) {
                        if (this._newStaticIndex !== this._staticColumnIndex) {
                            this._wijgrid.option("staticColumnIndex", this._newStaticIndex);
                        }
                    } else {
                        if (this._newStaticIndex !== this._staticRowIndex) {
                            this._wijgrid.option("staticRowIndex", this._newStaticIndex);
                        }
                    }
                } finally {
                    this._$proxy = null;
                    this._inProgress = false;
                }
            };

            uiFrozener.prototype._attachDocEvents = function (verticalBarTouched) {
                if (!this._docEventsAttached) {
                    try  {
                        if ($.fn.disableSelection) {
                            $(document.body).disableSelection();
                        }

                        this._wijgrid._view().toggleDOMSelection(false);

                        $(document).bind(this._docEventKey("mousemove"), verticalBarTouched, $.proxy(this._onDocumentMouseMove, this)).bind(this._docEventKey("mouseup"), verticalBarTouched, $.proxy(this._onDocumentMouseUp, this));
                    } finally {
                        this._docEventsAttached = true;
                    }
                }
            };

            uiFrozener.prototype._detachDocEvents = function () {
                if (this._docEventsAttached) {
                    try  {
                        if ($.fn.enableSelection) {
                            $(document.body).enableSelection();
                        }

                        this._wijgrid._view().toggleDOMSelection(true);

                        $(document).unbind("." + this._docEventsUID);
                    } finally {
                        this._docEventsAttached = false;
                    }
                }
            };

            uiFrozener.prototype._docEventKey = function (eventName) {
                return wijmo.grid.stringFormat("{0}.{1}", eventName, this._docEventsUID);
            };

            uiFrozener.prototype._showPosition = function (e) {
                var colPosInfo, elementBounds, centerXOrY, currentIdx, prevIdx, leftOrTop, position, barBounds, lAlign = (this._wijgrid._lgGetStaticColumnsAlignment() !== "right");

                if (e.data) {
                    barBounds = wijmo.grid.bounds(this._$vBar);

                    if (Math.abs(e.pageX - (barBounds.left + barBounds.width / 2)) < barBounds.width) {
                        this._$proxy.hide();
                        return;
                    }

                    if ((colPosInfo = this._getFieldByPos({ x: e.pageX, y: e.pageY }))) {
                        elementBounds = wijmo.grid.bounds(colPosInfo.element);
                        centerXOrY = elementBounds.left + elementBounds.width / 2;
                        currentIdx = colPosInfo.column.options._visLeavesIdx - this._staticOffsetV;
                        prevIdx = Math.max(currentIdx - 1, -1);
                        leftOrTop = e.pageX < centerXOrY ? (prevIdx !== this._staticColumnIndex) : (currentIdx === this._staticColumnIndex);
                        position = leftOrTop ? elementBounds.left : elementBounds.left + elementBounds.width;

                        if (!wijmo.grid.isOverAxis(position, this._visibleBounds.left - 1, this._visibleBounds.width + 3)) {
                            return;
                        }

                        this._newStaticIndex = leftOrTop ? prevIdx : currentIdx;

                        this._$proxy.show().css({
                            left: position,
                            top: elementBounds.top,
                            width: 3,
                            height: this._visibleBounds.height + this._visibleBounds.top - elementBounds.top
                        });
                    }
                } else {
                    barBounds = wijmo.grid.bounds(this._$hBar);

                    if (Math.abs(e.pageY - (barBounds.top + barBounds.height / 2)) < barBounds.height) {
                        this._$proxy.hide();
                        return;
                    }

                    var row;

                    if ((row = this._getRowByPos({ x: e.pageX, y: e.pageY }))) {
                        elementBounds = wijmo.grid.bounds(row);
                        centerXOrY = elementBounds.top + elementBounds.height / 2;
                        currentIdx = this._wijgrid._view().getAbsoluteRowIndex(row) - this._staticOffsetH;

                        prevIdx = Math.max(currentIdx - 1, -1);
                        leftOrTop = e.pageY < centerXOrY ? (prevIdx !== this._staticRowIndex) : (currentIdx === this._staticRowIndex);
                        position = leftOrTop ? elementBounds.top : elementBounds.top + elementBounds.height;

                        if (!wijmo.grid.isOverAxis(position, this._visibleBounds.top - 1, this._visibleBounds.height + 3)) {
                            return;
                        }

                        this._newStaticIndex = leftOrTop ? prevIdx : currentIdx;

                        this._$proxy.show().css({
                            left: lAlign ? elementBounds.left : this._visibleBounds.left,
                            top: position,
                            width: lAlign ? this._visibleBounds.width + this._visibleBounds.left - elementBounds.left : this._visibleBounds.width,
                            height: 3
                        });
                    }
                }
            };

            uiFrozener.prototype._getFieldByPos = function (pos) {
                var columns = this._wijgrid.columns(), dataRow = undefined;

                for (var i = 0, len = columns.length; i < len; i++) {
                    var instance = columns[i], opt = instance.options;

                    if (opt._isLeaf) {
                        var bounds = null, element;

                        if (instance.element) {
                            bounds = wijmo.grid.bounds(element = instance.element);
                        } else {
                            if (dataRow == undefined) {
                                dataRow = this._wijgrid._rows().find(0, function (row) {
                                    return (row.type & 2 /* data */) !== 0;
                                });
                            }

                            if (dataRow) {
                                var cell = grid.rowAccessor.getCell(dataRow.$rows, opt._visLeavesIdx);
                                if (cell) {
                                    bounds = wijmo.grid.bounds(element = $(cell));
                                }
                            }
                        }

                        if (bounds && wijmo.grid.isOverAxis(pos.x, bounds.left, bounds.width)) {
                            return {
                                column: instance,
                                element: element
                            };
                        }
                    }
                }

                return null;
            };

            uiFrozener.prototype._getRowByPos = function (pos) {
                var rows = this._wijgrid._rows();

                for (var i = 0, len = rows.length(); i < len; i++) {
                    var row = rows.item(i)[0], bounds = wijmo.grid.bounds($(row));

                    if (wijmo.grid.isOverAxis(pos.y, bounds.top, bounds.height)) {
                        return row;
                    }
                }

                return null;
            };
            return uiFrozener;
        })();
        grid.uiFrozener = uiFrozener;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="interfaces.ts"/>
/// <reference path="bands_traversing.ts"/>
/// <reference path="misc.ts"/>
var wijmo;
(function (wijmo) {
    (function (grid) {
        var $ = jQuery;

        /** @ignore */
        var columnsGenerator = (function () {
            function columnsGenerator() {
            }
            columnsGenerator.generate = function (mode, fieldsInfo, columns) {
                mode = (mode || "").toLowerCase();

                switch (mode) {
                    case "append":
                        columnsGenerator._processAppendMode(fieldsInfo, columns);
                        break;

                    case "merge":
                        columnsGenerator._processMergeMode(fieldsInfo, columns);
                        break;

                    case "none":
                        break;

                    default:
                        throw wijmo.grid.stringFormat("Unsupported value: \"{0}\"", mode);
                }
            };

            columnsGenerator._processAppendMode = function (fieldsInfo, columns) {
                var autoColumns = {};

                wijmo.grid.traverse(columns, function (column) {
                    if (column._dynamic && wijmo.grid.validDataKey(column.dataKey)) {
                        autoColumns[column.dataKey] = true;
                    }
                });

                $.each(fieldsInfo, function (key, fieldInfo) {
                    if (("name" in fieldInfo) && !autoColumns[fieldInfo.name]) {
                        columns.push(columnsGenerator._createAutoField(fieldInfo));
                    }
                });
            };

            columnsGenerator._processMergeMode = function (fieldsInfo, columns) {
                var columnsHasNoDataKey = [];

                wijmo.grid.traverse(columns, function (column) {
                    if (column._isLeaf && columnsGenerator._isBindableColumn(column)) {
                        var dataKey = column.dataKey;

                        if (wijmo.grid.validDataKey(dataKey)) {
                            if (fieldsInfo[dataKey] !== undefined) {
                                delete fieldsInfo[dataKey];
                            }
                        } else {
                            if (dataKey !== null) {
                                columnsHasNoDataKey.push(column);
                            }
                        }
                    }
                });

                if (columnsHasNoDataKey.length) {
                    var i = 0;

                    $.each(fieldsInfo, function (key, info) {
                        var leaf = columnsHasNoDataKey[i++];
                        if (leaf) {
                            leaf.dataKey = info.name;
                            delete fieldsInfo[key];
                        }
                    });
                }

                $.each(fieldsInfo, function (key, info) {
                    columns.push(columnsGenerator._createAutoField(info));
                });
            };

            columnsGenerator._createAutoField = function (fieldInfo) {
                return wijmo.grid.createDynamicField({ dataKey: fieldInfo.name });
            };

            columnsGenerator._isBindableColumn = function (column) {
                return !grid.c1bandfield.test(column) && !grid.c1rowheaderfield.test(column) && !grid.c1buttonbasefield.test(column) && !grid.c1buttonfield.test(column) && !grid.c1commandbuttonfield.test(column);
            };
            return columnsGenerator;
        })();
        grid.columnsGenerator = columnsGenerator;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="interfaces.ts"/>
var wijmo;
(function (wijmo) {
    (function (grid) {
        var $ = jQuery;

        /** @ignore */
        var uiVirtualScroller = (function () {
            function uiVirtualScroller(wijgrid, $content, fixedAreaHeight, rowOuterHeight) {
                //private _fixedAreaHeight: number;
                this._timer = 0;
                this._timeout = 50;
                this._ignoreScrollEvents = false;
                this._debounceScrolledEvent = true;
                this.mScrollLeftPos = undefined;
                this.mScrollTopPos = undefined;
                this.mVertical = false;
                this.mHorizontal = false;
                this._wijgrid = wijgrid;

                this.mVertical = wijgrid._allowVVirtualScrolling();
                this.mHorizontal = wijgrid._allowHVirtualScrolling();

                //this._fixedAreaHeight = fixedAreaHeight;
                this._$content = $content;

                this._view = this._wijgrid._view();

                if (this.mVertical) {
                    this._N = this._wijgrid._renderableRowsCount();

                    this._rowOuterHeight = rowOuterHeight;

                    this._updateContentHeight();

                    var height = this._wijgrid.mOuterDiv.height() + this._N * this._rowOuterHeight;
                    this._view._splitAreas.sw.height(height);
                }
            }
            uiVirtualScroller.prototype.scrollToColumn = function (column, left, callback) {
                this._debounceScrolledEvent = false; // otherwise sequential method calls will be blocked by timer
                this._completeListener = callback;
                this._panelInst.hScrollTo(left, false);
            };

            uiVirtualScroller.prototype.scrollToRow = function (rowIndex, callback) {
                this._debounceScrolledEvent = false; // otherwise sequential method calls will be blocked by timer
                this._completeListener = callback;
                this._panelInst.vScrollTo(rowIndex * this._panelInst.options.vScroller.scrollSmallChange, true);
            };

            /** calculate content height from row number, row height and fixed area */
            uiVirtualScroller.prototype._updateContentHeight = function () {
                // subtract _fixedAreaHeight, otherwise dummy rows will be hanging "under" the grid
                this._$content.height(this._rowOuterHeight * this._N);
            };

            uiVirtualScroller.prototype.attach = function ($scroller) {
                this._$scroller = $scroller;
                this._panelInst = $scroller.data("wijmo-wijsuperpanel");

                if (this.mVertical) {
                    this._updateContentHeight();
                    this._updateVerticalScroller();
                }

                $scroller.bind("wijsuperpanelscrolled.wijgrid", $.proxy(this._onSuperpanelScrolled, this));
                $scroller.bind("wijsuperpanelscrolling.wijgrid", $.proxy(this._onSuperpanelScrolling, this));
                $scroller.bind("wijsuperpanelscrolled.wijgrid", $.proxy(this._onSuperpanelPostScrolled, this)); // manipulate with the _ignoreScrollEvents property.
            };

            uiVirtualScroller.prototype._updateVerticalScroller = function () {
                // if vScroll.scrollValue was an y-offset of the content, rather than a percentage of the offset,
                // smallChange and max would be in pixels
                var max = Math.max(0, this._N - this._view.getVirtualPageSize(false));

                // scrollValue is the index of the first row to show
                this._setVerticalScrollerOptions(1, max);
            };

            uiVirtualScroller.prototype._setVerticalScrollerOptions = function (smallChange, max) {
                var vScroller = this._panelInst.options.vScroller;
                vScroller.scrollSmallChange = smallChange;
                vScroller.scrollLargeChange = smallChange * 4;

                if (max <= vScroller.scrollLargeChange) {
                    vScroller.scrollLargeChange = max;
                } else {
                    max += vScroller.scrollLargeChange - 1;
                }

                vScroller.scrollMax = max;

                this._panelInst.option("vScroller", vScroller);

                // TODO: rewrite!!
                if (!this._view._isNativeSuperPanel() && (this._panelInst._scrollDrag != undefined)) {
                    var f = this._panelInst._fields(), vbarContainer = f.vbarContainer, vbarDrag = f.vbarDrag;

                    this._panelInst._scrollDrag("v", vbarContainer, vbarDrag, false);
                }
            };

            uiVirtualScroller.prototype._changeVisibleRowsCount = function (visibleRowsCount) {
                this._N = visibleRowsCount;
                this._updateContentHeight();
                this._updateVerticalScroller();
            };

            uiVirtualScroller.prototype.dispose = function () {
                this._$scroller.unbind(".wijgrid");
                this._clearTimer();
            };

            uiVirtualScroller.prototype._clearTimer = function () {
                window.clearTimeout(this._timer);
                this._timer = 0;
            };

            uiVirtualScroller.prototype._onSuperpanelScrolling = function (e, args) {
                if (this._ignoreScrollEvents || (args.dir === "v" && !this.mVertical) || (args.dir === "h" && !this.mHorizontal)) {
                    //if (this._ignoreScrollEvents || (args.dir !== "v")) {
                    return;
                }

                if (this._timer === -1) {
                    return false;
                }
            };

            uiVirtualScroller.prototype._onSuperpanelScrolled = function (e, args) {
                var self = this;

                if (this._ignoreScrollEvents || (args.dir === "v" && !this.mVertical) || (args.dir === "h" && !this.mHorizontal)) {
                    //if (this._ignoreScrollEvents || (args.dir !== "v")) {
                    return;
                }

                if (this._timer > 0) {
                    this._clearTimer();
                }

                if (this._timer !== -1) {
                    this._timer = window.setTimeout(function () {
                        self._timer = -1; // lock

                        var doHScroll = false, leftPos = -args.afterPosition.left, newRange;

                        if (args.dir === "h") {
                            var newRange = new grid.renderableColumnsCollection();

                            self._view._getRenderableColumnsBounds(newRange, leftPos);
                            doHScroll = !self._wijgrid._renderableColumnsRange().equals(newRange);
                        } else {
                            var scrollToIndex = Math.floor(args.newValue / self._panelInst.options.vScroller.scrollSmallChange), oldScrollIndex = self._view._bounds.start;

                            if (scrollToIndex < 0) {
                                scrollToIndex = 0;
                            }

                            if (scrollToIndex >= self._N) {
                                scrollToIndex = self._N - 1;
                            }
                        }

                        if ((scrollToIndex !== oldScrollIndex) || doHScroll) {
                            self._debounceScrolledEvent = true;

                            if (args.dir === "v" && self.mVertical) {
                                self._wijgrid._handleVerticalVirtualScrolling(scrollToIndex, null, $.proxy(self._verticalScrollingCompleted, self));
                            } else {
                                self._wijgrid._handleHorizontalVirtualScrolling(newRange, $.proxy(self._horizontalScrollingCompleted, self));
                            }
                        } else {
                            self._debounceScrolledEvent = true;
                            self._log();
                            self._clearTimer(); // unlock
                        }
                    }, this._debounceScrolledEvent ? this._timeout : 0);
                }
            };

            uiVirtualScroller.prototype._verticalScrollingCompleted = function (scrollIndex) {
                this._wijgrid._trackScrollingIndex(scrollIndex);

                this._log();

                if (this._completeListener) {
                    this._completeListener();
                    this._completeListener = null;
                }

                this._clearTimer(); // unlock
            };

            uiVirtualScroller.prototype._horizontalScrollingCompleted = function () {
                this._log();

                if (this._completeListener) {
                    this._completeListener();
                    this._completeListener = null;
                }

                this._clearTimer(); // unlock
            };

            uiVirtualScroller.prototype._onSuperpanelPostScrolled = function () {
                if ($.isFunction(this._postScrolled)) {
                    this._postScrolled.apply(this, arguments);
                }
            };

            uiVirtualScroller.prototype._log = function () {
                //if (window.console) {
                //	var bounds = this._wijgrid._view()._bounds;
                //	window.console.log("bounds: [" + bounds.start + ", " + bounds.end + "], scrollTo: " + bounds.start);
                //}
            };
            return uiVirtualScroller;
        })();
        grid.uiVirtualScroller = uiVirtualScroller;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="interfaces.ts" />
var wijmo;
(function (wijmo) {
    (function (grid) {
        /** @ignore */
        var renderableColumnsCollection = (function () {
            function renderableColumnsCollection() {
                this.mItems = [];
            }
            renderableColumnsCollection.prototype.add = function (a, b) {
                var start, end;

                if (arguments.length === 1) {
                    this.mItems.push(a);
                } else {
                    this.mItems.push({
                        start: a,
                        end: b
                    });
                }
            };

            renderableColumnsCollection.prototype.item = function (index) {
                return this.mItems[index];
            };

            renderableColumnsCollection.prototype.clear = function () {
                this.mItems = [];
            };

            renderableColumnsCollection.prototype.contains = function (value) {
                if (value && value.options) {
                    value = value.options._leavesIdx;
                }

                if (value || (value === 0)) {
                    for (var i = 0; i < this.mItems.length; i++) {
                        var item = this.mItems[i];

                        if ((item.start >= 0) && (value >= item.start) && (value <= item.end)) {
                            return true;
                        }
                    }
                }

                return false;
            };

            renderableColumnsCollection.prototype.equals = function (value) {
                if (this === value) {
                    return true;
                }

                var len = this.length();
                if (!value || (len !== value.length())) {
                    return false;
                }

                var result = true;
                for (var i = 0; i < len && result; i++) {
                    var a = this.item(i), b = value.item(i);

                    result = (a.start === b.start) && (a.end === b.end);
                }

                return result;
            };

            renderableColumnsCollection.prototype.length = function () {
                return this.mItems.length;
            };

            renderableColumnsCollection.prototype.forEachIndex = function (callback) {
                for (var i = 0; i < this.mItems.length; i++) {
                    var item = this.mItems[i];

                    if (item && (item.start >= 0)) {
                        for (var j = item.start; j <= item.end; j++) {
                            if (callback(j) === false) {
                                return;
                            }
                        }
                    }
                }
            };
            return renderableColumnsCollection;
        })();
        grid.renderableColumnsCollection = renderableColumnsCollection;

        /** @ignore */
        //export class fixedRenderColumnsRange extends renderableColumnsRange {
        //	private mFix: IRenderBounds;
        //	private mScroll: IRenderBounds;
        //	constructor() {
        //		super();
        //		this.mFix = { start: -1, end: -1 };
        //		this.mScroll = { start: -1, end: -1 };
        //		this.add(this.mFix);
        //		this.add(this.mScroll);
        //	}
        //	public Fix(): IRenderBounds {
        //		return this.mFix;
        //	}
        //	public Scroll(): IRenderBounds {
        //		return this.mScroll;
        //	}
        //}
        /** @ignore */
        var renderableRowsCollection = (function () {
            function renderableRowsCollection(maxRowIndex) {
                this._items = [];
                this._capacity = null;
                this._maxRowIndex = maxRowIndex;
            }
            renderableRowsCollection.prototype.add = function (bounds) {
                this._capacity = null;

                var len = this._items.length, last;

                if (!len || (last = this._items[len - 1]).end < bounds.start) {
                    if (len && (bounds.start - last.end === 1)) {
                        last.end = bounds.end;
                    } else {
                        this._items.push(bounds);
                    }
                } else {
                    // todo: merge adjacent bounds
                    var idxS = this._binSearchByStartVal(bounds.start), idxE = this._binSearchByEndVal(bounds.end), idxSn = idxS < 0 ? ~idxS : idxS, idxEn = idxE < 0 ? ~idxE : idxE, pinL = (idxS >= 0) || (idxSn > 0 && bounds.start <= this._items[idxSn - 1].end), pinR = (idxE >= 0) || (idxEn < len && bounds.end <= this._items[idxEn].end && bounds.end >= this._items[idxEn].start), cnt;

                    if (pinL) {
                        if (pinR) {
                            // 1 1
                            if (idxS >= 0) {
                                this._items[idxEn].start = this._items[idxSn].start;

                                if (cnt = (idxEn - idxSn)) {
                                    this._items.splice(idxSn, cnt);
                                }
                            } else {
                                this._items[idxEn].start = this._items[idxSn - 1].start;

                                if (cnt = idxEn - idxSn + 1) {
                                    this._items.splice(idxSn - 1, cnt);
                                }
                            }
                        } else {
                            // 1 0
                            if (idxS >= 0) {
                                this._items[idxSn].end = bounds.end;

                                if (cnt = (idxEn - idxSn - 1)) {
                                    this._items.splice(idxSn, cnt);
                                }
                            } else {
                                this._items[idxSn - 1].end = bounds.end;

                                if (cnt = (idxEn - idxSn)) {
                                    this._items.splice(idxSn, cnt);
                                }
                            }
                        }
                    } else {
                        if (pinR) {
                            // 0 1
                            this._items[idxEn].start = bounds.start;

                            if (cnt = (idxEn - idxSn)) {
                                this._items.splice(idxSn, cnt);
                            }
                        } else {
                            // 0 0
                            this._items.splice(idxSn, idxEn - idxSn, bounds);
                        }
                    }
                }
            };

            //public remove(bounds: IRenderBounds) {
            //	this._capacity = null;
            //	var len = this._items.length;
            //	if (len) {
            //		var idxS = this._binSearchByStartVal(bounds.start),
            //			idxE = this._binSearchByEndVal(bounds.end),
            //			idxSn = idxS < 0 ? ~idxS : idxS,
            //			idxEn = idxE < 0 ? ~idxE : idxE,
            //			pinL = (idxS >= 0) || (idxSn > 0 && bounds.start <= this._items[idxSn - 1].end),
            //			pinR = (idxE >= 0) || (idxEn < len && bounds.end <= this._items[idxEn].end && bounds.end >= this._items[idxEn].start);
            //		if (pinL) {
            //			if (pinR) {
            //				var boundIdxL = (idxS >= 0) ? idxS : idxSn - 1,
            //					boundIdxR = (idxE >= 0) ? idxE : idxEn;
            //				if (idxS >= 0 && idxE >= 0) {
            //					this._items.splice(idxSn, idxEn - idxSn + 1);
            //				} else {
            //					if (idxS >= 0) {
            //						this._items[idxEn].start = bounds.end + 1;
            //						this._items.splice(idxSn, idxEn - idxSn);
            //					} else {
            //						if (idxE >= 0) {
            //							if (boundIdxL === boundIdxR) { // same bound
            //								this._items[idxSn - 1].end = bounds.start - 1;
            //							} else {
            //								this._items[idxSn].end = bounds.start - 1;
            //								this._items.splice(idxSn, idxEn - idxSn + 1);
            //							}
            //						}
            //						else {
            //							if (boundIdxL === boundIdxR) { // same bound, split single bound.
            //								var tEnd = this._items[idxSn - 1].end;
            //								this._items[idxSn - 1].end = bounds.start - 1;
            //								this._items.splice(idxSn, 0, { start: bounds.end + 1, end: tEnd });
            //							} else {
            //								this._items[idxSn - 1].end = bounds.start - 1;
            //								this._items[idxEn].start = bounds.end + 1;
            //								this._items.splice(idxSn, idxEn - idxSn);
            //							}
            //						}
            //					}
            //				}
            //			} else {
            //				if (idxS >= 0) {
            //					this._items.splice(idxSn, idxEn - idxSn);
            //				} else {
            //					this._items[idxSn].end = bounds.start - 1;
            //					this._items.splice(idxSn, idxEn - idxSn - 1);
            //				}
            //			}
            //		} else {
            //			if (pinR) {
            //				if (idxE >= 0) {
            //					this._items.splice(idxSn, idxEn - idxSn + 1);
            //				} else {
            //					// !!
            //					this._items[idxEn].start = bounds.end + 1;
            //					this._items.splice(idxSn, idxEn - idxSn);
            //				}
            //			} else {
            //				this._items.splice(idxSn, idxEn - idxSn);
            //			}
            //		}
            //	}
            //}
            //public clear() {
            //	this._capacity = 0;
            //	this._items = [];
            //}
            renderableRowsCollection.prototype.item = function (index) {
                return this._items[index];
            };

            //public forEachIndex(callback: (idx: number) => void ) {
            //	if (callback) {
            //		for (var i = 0, len = this._items.length; i < len; i++) {
            //			var bound = this._items[i];
            //			for (var start = bound.start, end = bound.end; start <= end; start++) {
            //				callback(start);
            //			}
            //		}
            //	}
            //}
            renderableRowsCollection.prototype.forEachIndex = function (start, count, callback) {
                if (start < 0) {
                    return;
                }

                var len = this._items.length, state = this._getIteratorStateFor(start), cnt = 0, flag = true, abort = false;

                if (state) {
                    var j = state.j;

                    for (var i = state.i; i < len && !abort; i++) {
                        var item = this._items[i];

                        if (!flag) {
                            j = item.start;
                        }

                        for (j; j <= item.end && !abort; j++) {
                            if ((++cnt > count) && (count !== -1)) {
                                return;
                            }

                            abort = (callback(j) === false);
                        }

                        flag = false;
                    }
                }
            };

            renderableRowsCollection.prototype.forEachIndexBackward = function (start, count, callback) {
                if (start < 0) {
                    return;
                }

                var len = this._items.length, state = this._getIteratorStateFor(start), cnt = 0, flag = true, abort = false;

                if (state) {
                    var j = state.j;

                    for (var i = state.i; i >= 0 && !abort; i--) {
                        var item = this._items[i];

                        if (!flag) {
                            j = item.end;
                        }

                        for (j; j >= item.start && !abort; j--) {
                            if ((++cnt > count) && (count !== -1)) {
                                return;
                            }

                            abort = (callback(j) === false);
                        }

                        flag = false;
                    }
                }
            };

            renderableRowsCollection.prototype._getIteratorStateFor = function (visIndex) {
                var len = this._items.length, cap = 0;

                for (var i = 0; i < len; i++) {
                    var item = this._items[i];

                    cap += item.end - item.start + 1;

                    var delta = cap - visIndex;

                    if (delta >= 0) {
                        return {
                            i: i,
                            j: item.end - delta + 1
                        };
                    }
                }

                return null;
            };

            // [0-5],[10-15]
            // f(6) -> 10
            // Maps visible row index to absolute row (sketch)  index
            renderableRowsCollection.prototype.getAbsIndex = function (renderedIndex) {
                for (var i = 0, len = this._items.length; i < len; i++) {
                    var bound = this._items[i], relEndIdx = bound.end - bound.start;

                    if (renderedIndex <= relEndIdx) {
                        return bound.start + renderedIndex;
                    } else {
                        renderedIndex -= relEndIdx + 1; // -= bound length
                    }
                }

                return -1;
            };

            // Maps absolute row (sketch) index to rendered row index
            renderableRowsCollection.prototype.getRenderedIndex = function (absIndex) {
                var boundIndex = this.hasAbsIndex(absIndex);

                if (boundIndex >= 0) {
                    var capacity = 0;

                    for (var i = 0; i < boundIndex; i++) {
                        var bound = this._items[i];
                        capacity += bound.end - bound.start + 1;
                    }

                    return capacity + (absIndex - this._items[boundIndex].start);
                }

                return -1;
            };

            // returns index of the IRenderBound item in the _items array or -1.
            renderableRowsCollection.prototype.hasAbsIndex = function (absIndex) {
                if (this._items.length) {
                    var idx = this._binSearchByStartVal(absIndex);

                    if (idx >= 0) {
                        return idx;
                    } else {
                        idx = ~idx;

                        if (idx > 0 && absIndex <= this._items[idx - 1].end) {
                            return idx - 1;
                        }
                    }
                }

                return -1;
            };

            renderableRowsCollection.prototype.length = function () {
                return this._items.length;
            };

            renderableRowsCollection.prototype.capacity = function () {
                if (this._capacity === null) {
                    var result = 0;

                    for (var i = 0, len = this._items.length; i < len; i++) {
                        var bound = this._items[i];

                        result += (bound.end - bound.start) + 1;
                    }

                    this._capacity = result;
                }

                return this._capacity;
            };

            //public truncate(start: number, end: number) {
            //	this.truncateByStart(start);
            //	this.truncateByStart(end);
            //}
            //public truncateByCount(value: number) {
            //	var count = 0;
            //	if (value === 0) {
            //		this._items = [];
            //	} else {
            //		for (var i = 0, len = this._items.length; i < len; i++) {
            //			var bound = this._items[i];
            //			count += (bound.end - bound.start) + 1;
            //			if (count >= value) {
            //				if (count > value) {
            //					bound.end -= count - value;
            //				}
            //				this._items.splice(i + 1, this._items.length - (i + 1));
            //				break;
            //			}
            //		}
            //	}
            //}
            renderableRowsCollection.prototype.truncateByStart = function (value, pinFirstRemainingBoundToValue) {
                var idx = this._binSearchByStartVal(value), len = this._items.length;

                if (idx < 0) {
                    idx = ~idx;

                    if (idx < len) {
                        if (idx > 0 && this._items[idx - 1].end >= value) {
                            this._items[idx - 1].start = value;
                            this._items.splice(0, idx - 1);
                        } else {
                            if (pinFirstRemainingBoundToValue) {
                                this._items[idx].start = value;
                            }

                            this._items.splice(0, idx);
                        }
                    } else {
                        this._items = [];
                    }
                } else {
                    this._items.splice(0, idx);
                }
            };

            //public truncateByEnd(value: number, pinLastRemainingBoundToValue?: boolean) {
            //	// todo
            //	var idx = this._binSearchByEndVal(value),
            //		len = this._items.length;
            //	if (idx < 0) {
            //		idx = ~idx;
            //		if (idx < len) {
            //			this._items[idx].end = value;
            //			this._items.splice(idx + 1, this._items.length - idx + 1);
            //		} else {
            //			this._items = [];
            //		}
            //	} else {
            //		this._items.splice(idx + 1, this._items.length - idx + 1);
            //	}
            //}
            //public deleteFromTop(count: number) {
            //	var i = 0,
            //		cap = 0;
            //	for (i = 0; i < this._items.length; i++) {
            //		var item = this._items[i];
            //		cap += item.end - item.start + 1;
            //		if (cap >= count) {
            //			break;
            //		}
            //	}
            //	if (cap >= count) {
            //		this._items[i].start = cap - count + 1;
            //	}
            //	this._items.splice(0, i);
            //}
            //public deleteFromBottom(count: number) {
            //	var i = 0,
            //		cap = 0;
            //	for (i = this._items.length - 1; i >= 0; i--) {
            //		var item = this._items[i];
            //		cap += item.end - item.start + 1;
            //		if (cap >= count) {
            //			break;
            //		}
            //	}
            //	if (cap >= count) {
            //		this._items[i].start = cap - count + 1;
            //	}
            //	this._items.splice(i, this._items.length - i);
            //}
            renderableRowsCollection.prototype._binSearchByStartVal = function (value) {
                var l = 0, u = this._items.length - 1;

                while (l <= u) {
                    var m = (u + l) >> 1, cmp = this._items[m].start - value;

                    if (cmp === 0) {
                        return m;
                    }

                    if (cmp < 0) {
                        l = m + 1;
                    } else {
                        u = m - 1;
                    }
                }

                return ~l;
            };

            renderableRowsCollection.prototype._binSearchByEndVal = function (value) {
                var l = 0, u = this._items.length - 1;

                while (l <= u) {
                    var m = (u + l) >> 1, cmp = this._items[m].end - value;

                    if (cmp < 0) {
                        l = m + 1;
                    } else {
                        if (cmp) {
                            u = m - 1;
                        } else {
                            return m;
                        }
                    }
                }

                return ~l;
            };
            return renderableRowsCollection;
        })();
        grid.renderableRowsCollection = renderableRowsCollection;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="../../../data/src/dataView.ts"/>
/// <reference path="interfaces.ts"/>
/// <reference path="wijgrid.ts"/>
/// <reference path="sketchTable.ts"/>
/// <reference path="misc.ts"/>
var wijmo;
(function (wijmo) {
    (function (_grid) {
        var $ = jQuery;

        /** @ignore */
        var hierarchyBuilder = (function () {
            function hierarchyBuilder() {
            }
            hierarchyBuilder.build = function (grid) {
                if (grid._hasDetail()) {
                    var sketch = grid.mSketchTable;

                    sketch.ensureNotLazy(); // make sure all rows are created

                    grid._clearDetails();

                    if (!grid._isRoot()) {
                        var mi = grid._masterInfo(), mdi = mi.master.details()[mi.dataRowIndex];

                        mdi._setDetails(grid.details());
                    }

                    for (var i = 0; i < sketch.count(); i++) {
                        var dataRow = sketch.row(i), detailRow = this.buildDetailRow(grid), detail = new hierarchyNode(grid, dataRow.originalRowIndex);

                        grid.details().push(detail);

                        dataRow.rowType |= 256 /* dataHeader */;

                        if (!detail.isExpanded()) {
                            dataRow.extInfo.state |= 2 /* collapsed */;
                            detailRow.extInfo.state |= 1 /* hidden */;
                        }

                        sketch.insert(i + 1, detailRow);
                        i++;
                    }
                }
            };

            hierarchyBuilder.buildDetailRow = function (wijgrid) {
                var row = new _grid.SketchDetailRow(null);

                // Add row header cells first
                $.each(wijgrid._virtualLeaves(), function () {
                    row.add(_grid.HtmlCell.nbsp());
                });

                // A detail grid will be placed here
                row.add(new _grid.HtmlCell("", {
                    colSpan: wijgrid._visibleLeaves().length - wijgrid._virtualLeaves().length
                }));

                return row;
            };
            return hierarchyBuilder;
        })();
        _grid.hierarchyBuilder = hierarchyBuilder;

        /** @ignore */
        var detailInstantiator = (function () {
            function detailInstantiator() {
            }
            detailInstantiator.instantiateIn = function (container, master, masterKey, dataRowIndex) {
                var table = $("<table></table>");

                container.empty().append(table);

                var detailOptions = detailInstantiator._populateDetail(master), masterInfo = {
                    master: master,
                    dataRowIndex: dataRowIndex
                }, args = {
                    options: detailOptions,
                    masterKey: masterKey
                };

                master._onDetailCreating(args);

                table.data(_grid.wijgrid.JQDATA_MASTER_INFO_KEY, masterInfo).wijgrid(args.options);

                return table.wijgrid("instance");
            };

            detailInstantiator._populateDetail = function (master) {
                var result, source = master.options.detail;

                // clone original object except the .data option
                var st = wijmo.grid.DataOptionPersister.persistAndClear(source);
                result = $.extend(true, {}, source);
                wijmo.grid.DataOptionPersister.restore(source, st);
                wijmo.grid.DataOptionPersister.restore(result, st); // share same .data options

                result._isDetail = true;
                result.disabled = master.options.disabled;

                // handle the .data option
                if (!result.data || $.isArray(result.data)) {
                    // result.data points to the source.data
                } else {
                    if (typeof (result.data.clone) === "function") {
                        result.data = result.data.clone(); // clone wijdataview
                    } else {
                        throw "Unsupported data source.";
                    }
                }

                return result;
            };
            return detailInstantiator;
        })();
        _grid.detailInstantiator = detailInstantiator;

        /** Provides an access to hierarchy nodes in form of tree. */
        var hierarchyNode = (function () {
            /** @ignore */
            function hierarchyNode(owner, dataRowIndex) {
                this.mIsExpanded = undefined;
                this.mDetail = null;
                this.mOwner = owner;
                this.mDataRowIndex = dataRowIndex;
            }
            /**
            * Returns children nodes.
            * @returns {wijmo.grid.hierarchyNode[]} An array of children nodes if node is expanded, otherwise an empty array.
            */
            hierarchyNode.prototype.details = function () {
                if (!this.mDetails) {
                    this.mDetails = [];
                }

                return this.mDetails;
            };

            /** Collapses the node. */
            hierarchyNode.prototype.collapse = function () {
                var view = this.mOwner._view(), dataRow = this._masterDataRow(), detailRow = view.bodyRows().item(view._getRowInfo(dataRow).sectionRowIndex + 1);

                this._toggleDataRow(dataRow, false);
                this._toggleDetailRow(detailRow, false);

                var defCSS = wijmo.grid.wijgrid.CSS, container = _grid.rowObjToJQuery(detailRow).find("." + defCSS.detailContainerCell + ":first > ." + defCSS.cellContainer);

                container.empty();

                this._setGrid(null);
                if (this.mDetails) {
                    this.mDetails.splice(0, this.mDetails.length); // clear subtree
                }

                // 1. go upstairs from the current detail to a topmost one, reset width of each traversed grid, build a path.
                var current = this.mOwner, path = [];

                do {
                    path.unshift(current);
                } while(current = current._master());

                while (current = path.shift()) {
                    current._setSizeWithoutDetails();
                }

                this.mIsExpanded = false;
            };

            /** Expands the node. */
            hierarchyNode.prototype.expand = function () {
                var view = this.mOwner._view(), dataRow = this._masterDataRow(), detailRow = view.bodyRows().item(view._getRowInfo(dataRow).sectionRowIndex + 1);

                this._toggleDataRow(dataRow, true);
                this._toggleDetailRow(detailRow, true);

                var defCSS = wijmo.grid.wijgrid.CSS, container = _grid.rowObjToJQuery(detailRow).find("." + defCSS.detailContainerCell + ":first > ." + defCSS.cellContainer);

                this.mOwner.mLoadingDetails++;
                detailInstantiator.instantiateIn(container, this.mOwner, this.masterKey(), this.mDataRowIndex);

                this.mIsExpanded = true;
            };

            /**
            * Determines whether node is expanded or not.
            * @returns {Boolean} True if node is collapsed, otherwise false.
            */
            hierarchyNode.prototype.isExpanded = function () {
                if (this.mIsExpanded === undefined) {
                    return this.mOwner.options.detail.startExpanded;
                }

                return this.mIsExpanded;
            };

            /**
            * Returns a wijgrid instance object which represents the detail grid related to node.
            * @returns {wijmo.grid.wijgrid} A wijgrid instance object which represents the detail grid related to node if node is expanded, otherwise null.
            */
            hierarchyNode.prototype.grid = function () {
                return this.mDetail;
            };

            /**
            * Returns master key related to node.
            * @returns {wijmo.grid.IDataKeyArray} Master key related to node.
            */
            hierarchyNode.prototype.masterKey = function () {
                var result = {}, dataItem = this.mOwner._getDataItem(this.mDataRowIndex), detail = this.mOwner.options.detail;

                for (var i = 0; i < detail.relation.length; i++) {
                    var r = detail.relation[i];
                    result[r.masterDataKey.toLowerCase()] = this.mOwner.mDataViewWrapper.getValue(dataItem, r.masterDataKey);
                }
                ;

                return result;
            };

            /** @ignore */
            hierarchyNode.prototype._setDetails = function (value) {
                this.mDetails = value;
            };

            /** @ignore */
            hierarchyNode.prototype._setGrid = function (value) {
                this.mDetail = value;
            };

            hierarchyNode.prototype._masterHierarchyNode = function () {
                if (this.mOwner) {
                    var mi = this.mOwner._masterInfo();
                    if (mi.master) {
                        return mi.master.details()[mi.dataRowIndex];
                    }
                }

                return null;
            };

            hierarchyNode.prototype._masterDataRowIndex = function () {
                return this.mDataRowIndex;
            };

            hierarchyNode.prototype._masterDataRow = function () {
                var self = this, dataRow = this.mOwner._rows().findRowObj(0, function (row) {
                    return row.dataRowIndex == self.mDataRowIndex;
                });

                return dataRow;
            };

            hierarchyNode.prototype._toggleDataRow = function (dataRow, expand) {
                var view = this.mOwner._view(), info = view._getRowInfo(dataRow), sketch = this.mOwner.mSketchTable.row(info.sketchRowIndex);

                if (expand) {
                    sketch.extInfo.state &= ~2 /* collapsed */;
                    info._extInfo.state &= ~2 /* collapsed */;
                } else {
                    info._extInfo.state |= 2 /* collapsed */;
                    sketch.extInfo.state |= 2 /* collapsed */;
                }

                view._setRowInfo(info.$rows, info);

                this.mOwner.mRowStyleFormatter._masterFormatter(info);
            };

            hierarchyNode.prototype._toggleDetailRow = function (detailRow, expand) {
                var view = this.mOwner._view(), info = view._getRowInfo(detailRow), sketch = this.mOwner.mSketchTable.row(info.sketchRowIndex);

                if (expand) {
                    sketch.extInfo.state &= ~1 /* hidden */;
                    info._extInfo.state &= ~1 /* hidden */;
                } else {
                    info._extInfo.state |= 1 /* hidden */;
                    sketch.extInfo.state |= 1 /* hidden */;
                }

                view._setRowInfo(info.$rows, info);

                if (expand) {
                    info.$rows.show();
                } else {
                    info.$rows.hide();
                }
            };
            return hierarchyNode;
        })();
        _grid.hierarchyNode = hierarchyNode;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="../../../Data/src/core.ts"/>
/// <reference path="../../../Data/src/util.ts"/>
/// <reference path="../../../Data/src/errors.ts"/>
/// <reference path="../../../external/declarations/globalize.d.ts"/>
var wijmo;
(function (wijmo) {
    (function (data) {
        var $ = jQuery, glob = Globalize;

        

        

        /** @ignore */
        function convert(val, fromType, toType, options) {
            var origValue = val;
            options = $.extend({
                nullString: "",
                format: ""
            }, options);

            function getParser(type) {
                options.parser = options.parser || data.defaultParsers[type];
                if (!options.parser && val != null)
                    data.errors.noParser(type);
                return options.parser;
            }

            fromType = fromType || val != null && typeof val;
            toType = toType || fromType;
            if (!toType)
                return val;

            if (toType == "string") {
                getParser(fromType);
                if (!options.parser)
                    return val;
                return options.parser.toStr(val, options.culture, options.format, options.nullString, true);
            }
            getParser(toType);
            if (!options.parser)
                return val;

            val = options.parser.parse(val, options.culture, options.format, options.nullString, true);

            if (isNaN(val) && val != null && data.util.isNumeric(val)) {
                if (options.ignoreError)
                    return origValue;
                data.errors.cantConvert(toType, origValue);
            }
            return val;
        }
        data.convert = convert;

        /** @ignore */
        data.defaultParsers = {
            string: {
                // string -> string
                parse: function (value, culture, format, nullString, convertEmptyStringToNull) {
                    switch (value) {
                        case null:
                            return null;

                        case nullString:
                            if (convertEmptyStringToNull) {
                                return null;
                            }

                        case undefined:
                        case "&nbsp":
                            return "";

                        default:
                            return "" + value;
                    }
                },
                // string -> string
                toStr: function (value, culture, format, nullString, convertEmptyStringToNull) {
                    if (value === null && convertEmptyStringToNull) {
                        return nullString;
                    }
                    return "" + value;
                }
            },
            number: {
                // string/number -> number
                parse: function (value, culture, format, nullString, convertEmptyStringToNull) {
                    var type = typeof (value);

                    if (type === "number") {
                        return isNaN(value) ? NaN : value;
                    }

                    if ((!value && value !== 0) || (value === "&nbsp;") || (value === nullString && convertEmptyStringToNull)) {
                        return null;
                    }

                    return glob.parseFloat(value, 10, culture);
                },
                // number -> string
                toStr: function (value, culture, format, nullString, convertEmptyStringToNull) {
                    if (value === null && convertEmptyStringToNull) {
                        return nullString;
                    }

                    return glob.format(value, format || "n", culture);
                }
            },
            currency: {
                // string/number -> number
                parse: function (value, culture, format, nullString, convertEmptyStringToNull) {
                    var type = typeof (value);

                    if (type === "number") {
                        return isNaN(value) ? NaN : value;
                    }

                    if ((!value && value !== 0) || (value === "&nbsp;") || (value === nullString && convertEmptyStringToNull)) {
                        return null;
                    }

                    if (type === "string") {
                        value = value.replace(culture.numberFormat.currency.symbol, "");
                    }

                    return glob.parseFloat(value, 10, culture);
                },
                // number -> string (currency)
                toStr: function (value, culture, format, nullString, convertEmptyStringToNull) {
                    if (value === null && convertEmptyStringToNull) {
                        return nullString;
                    }

                    return glob.format(value, format || "c", culture);
                }
            },
            datetime: {
                // string/datetime -> datetime
                parse: function (value, culture, format, nullString, convertEmptyStringToNull) {
                    var match;

                    if (value instanceof Date) {
                        return value;
                    }

                    if (!value || (value === "&nbsp;") || (value === nullString && convertEmptyStringToNull)) {
                        return null;
                    }

                    match = /^\/Date\((\d+)\)\/$/.exec(value);
                    if (match) {
                        return new Date(parseInt(match[1], 10));
                    }

                    var date = glob.parseDate(value, format || "d", culture);

                    if (date == null || isNaN(date)) {
                        date = Date.parse(value);
                        date = isNaN(date) ? NaN : new Date(date);
                    }

                    return date;
                },
                // datetime -> string
                toStr: function (value, culture, format, nullString, convertEmptyStringToNull) {
                    if (value === null && convertEmptyStringToNull) {
                        return nullString;
                    }

                    return glob.format(value, format || "d", culture);
                }
            },
            boolean: {
                // string/boolean -> boolean
                parse: function (value, culture, format, nullString, convertEmptyStringToNull) {
                    var valType = typeof (value);

                    if (valType === "number") {
                        return value != 0;
                    }

                    if (valType === "boolean") {
                        return value;
                    }

                    if (valType === "string") {
                        value = $.trim(value);
                    }

                    if (!value || (value === "&nbsp;") || (value === nullString && convertEmptyStringToNull)) {
                        return null;
                    }

                    switch (value.toLowerCase()) {
                        case "true":
                            return true;

                        case "false":
                            return false;
                    }

                    return NaN;
                },
                // boolean -> string
                toStr: function (value, culture, format, nullString, convertEmptyStringToNull) {
                    if (value === null && convertEmptyStringToNull) {
                        return nullString;
                    }

                    return (value) ? "true" : "false";
                }
            }
        };

        function checkGlob(func) {
            return function () {
                if (!glob) {
                    data.util.logError(data.errors.noGlobalize.create().message);
                }
                return func.apply(this, arguments);
            };
        }

        $.each(data.defaultParsers, function (_, parser) {
            parser.parse = parser.parse && checkGlob(parser.parse);
            parser.toStr = parser.toStr && checkGlob(parser.toStr);
        });
    })(wijmo.data || (wijmo.data = {}));
    var data = wijmo.data;
})(wijmo || (wijmo = {}));

/// <reference path="../../../Data/src/arrayDataView.ts"/>
var wijmo;
(function (wijmo) {
    (function (data) {
        (function (filtering) {
            /** Provides compilation of the Extended Filtering Format
            *
            * @remarks
            * Some examples of extended filter format:
            *   [{ property: "name", value: "John" }, { property: "age", operator: "<", value: 10 }]
            *   ["or", { property: "name", value: "John" }, { property: "age", operator: "<", value: 10 }]
            *   ["and",
            *      ["or", { property: "name", value: "John" }, { property: "name", operator: "BeginsWith", value: "A" } ],
            *      { property: "age", operator: "<", value: 10 }]
            *   ]
            */
            /** @ignore */
            (function (extended) {
                /** @ignore */
                extended.Connective = {
                    AND: "and",
                    OR: "or"
                };

                function normalizeFilter(filter) {
                    function norm(filter) {
                        var result = [];
                        if (filter.length === 0)
                            return result;

                        var connective = extended.Connective.AND;
                        data.util.each(filter, function (i, cond) {
                            if (i == 0 && data.util.isString(cond)) {
                                var lowerConnective = cond.toLowerCase();
                                if (lowerConnective == extended.Connective.AND || lowerConnective == extended.Connective.OR) {
                                    connective = lowerConnective;
                                    return;
                                }
                            }

                            if ($.isArray(cond)) {
                                cond = norm(cond);
                                if (!cond)
                                    return;
                                if (cond[0] === connective || cond.length == 2) {
                                    cond.shift();
                                    result = result.concat(cond);
                                    return;
                                }
                            } else {
                                var predicate = filtering.normalizeCondition(cond);
                                if (!predicate)
                                    return;
                                predicate.property = cond.property;
                                cond = predicate;
                            }

                            result.push(cond);
                        });

                        if (result.length == 0) {
                            return null;
                        } else {
                            result.unshift(connective);
                            return result;
                        }
                    }
                    return norm(filter);
                }
                function compilAsExtended(extendedFilter) {
                    if (!$.isArray(extendedFilter)) {
                        return null;
                    }

                    var result = {
                        isEmpty: true,
                        original: extendedFilter,
                        normalized: normalizeFilter(extendedFilter),
                        func: null
                    };
                    if (result.normalized == null) {
                        result.func = function (x) {
                            return true;
                        };
                    } else {
                        result.isEmpty = false;
                        result.func = function (x) {
                            function check(filter) {
                                var isAnd = filter[0] === extended.Connective.AND, checker = isAnd ? data.util.every : data.util.some;
                                return checker(filter, function (cond, i) {
                                    if (i === 0)
                                        return isAnd;
                                    if ($.isArray(cond)) {
                                        return check(cond);
                                    } else {
                                        var value = data.util.getProperty(x, cond.property);
                                        return cond.op.apply(value, cond.value);
                                    }
                                });
                            }
                            return check(result.normalized);
                        };
                    }
                    return result;
                }

                /** @ignore */
                function compile(filter) {
                    return compilAsExtended(filter) || filtering.compile(filter);
                }
                extended.compile = compile;
            })(filtering.extended || (filtering.extended = {}));
            var extended = filtering.extended;
        })(data.filtering || (data.filtering = {}));
        var filtering = data.filtering;
    })(wijmo.data || (wijmo.data = {}));
    var data = wijmo.data;
})(wijmo || (wijmo = {}));

/// <reference path="../../../Data/src/arrayDataView.ts"/>
/// <reference path="wijmo.data.filtering.extended.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    (function (grid) {
        var $ = jQuery;
        var wijdata = wijmo.data;
        var filterExt = wijmo.data.filtering.extended;

        // in fact implements IDataView in run-time, but not at compile-time
        /** @ignore */
        var GridDataView = (function () {
            function GridDataView(real) {
                this.real = real;
                this._updatingFilter = false;
                this._overrideFilter();
                this._makeMemberProxies();
            }
            GridDataView.prototype._overrideFilter = function () {
                var _this = this;
                this.filter = wijdata.observable(this.real.filter());

                this.filter.subscribe(function (newValue) {
                    if (_this.real.filter() !== newValue && !_this._updatingFilter) {
                        _this.refresh({ filter: newValue });
                    }
                });

                this.real.filter.subscribe(function (newValue) {
                    // Do not update this.filter if it is the same filter we've assigned to the underlying dataView.
                    // Otherwise we may end up replacing a property filter with a function
                    if (newValue !== _this._lastSetFilter) {
                        _this.filter(newValue);
                    }
                });
            };

            GridDataView.prototype.refresh = function (shape, local) {
                if (typeof local === "undefined") { local = false; }
                shape = $.extend({}, shape);
                var origFilter = shape.filter;
                shape.filter = this._coerceFilter(shape.filter);
                this._lastSetFilter = shape.filter;

                this._updatingFilter = true;
                try  {
                    if ($.isFunction(shape.filter) && !$.isFunction(origFilter)) {
                        // it became a function. It means that the filter was complex
                        this.filter(origFilter);
                    } else {
                        this.filter(shape.filter);
                    }
                } finally {
                    this._updatingFilter = false;
                }

                return this.real.refresh(shape, local);
            };

            GridDataView.prototype._makeMemberProxies = function () {
                var _this = this;
                // make proxy methods for those that are not defined manually
                wijdata.util.each(this.real, function (key, value) {
                    if (!$.isFunction(value) || _this[key] || key.charAt(0) === "_")
                        return;

                    _this[key] = $.isFunction(value.subscribe) ? value : function () {
                        return value.apply(_this.real, arguments);
                    };
                });
            };

            GridDataView.create = function (dataView) {
                return new GridDataView(dataView);
            };

            GridDataView.prototype._convertComplexPropertyFilterToExtendedFilterFormat = function (filter) {
                var result = [];
                $.each(filter, function (prop, condList) {
                    if (!$.isArray(condList)) {
                        condList = [condList];
                    } else {
                        var connective = wijdata.util.isString(condList[0]) && condList[0].toLowerCase();
                        if (connective === filterExt.Connective.AND || connective === filterExt.Connective.OR) {
                            result.push(condList);
                            return;
                        }
                    }

                    var normCondList = [];
                    $.each(condList, function (_, cond) {
                        var normCond = wijdata.filtering.normalizeCondition(cond);
                        if (normCond) {
                            normCond.property = prop;
                            normCondList.push(normCond);
                        }
                    });

                    if (normCondList.length > 0) {
                        result.push(normCondList);
                    }
                });

                return result.length > 0 ? result : null;
            };
            GridDataView.prototype._coerceFilter = function (filter) {
                if ($.isArray(filter)) {
                    // assume extended
                    return filterExt.compile(filter).func;
                } else if (!$.isPlainObject(filter)) {
                    return filter;
                }

                filter = $.extend(true, {}, filter);

                var simpleFilter = {};
                $.each(filter, function (prop, cond) {
                    if (!$.isArray(cond)) {
                        cond = [cond];
                    }

                    if (simpleFilter) {
                        var possibleConnective = wijdata.util.isString(cond[0]) && cond[0].toLowerCase();
                        if (cond.length == 1 || cond.length == 2 && (possibleConnective === "and" || possibleConnective === "or")) {
                            simpleFilter[prop] = cond[cond.length - 1];
                            return;
                        }
                    }

                    filter[prop] = cond;
                    simpleFilter = null;
                });

                if (simpleFilter) {
                    return simpleFilter;
                }

                var extendedFilter = this._convertComplexPropertyFilterToExtendedFilterFormat(filter);
                return filterExt.compile(extendedFilter).func;
            };
            return GridDataView;
        })();
        grid.GridDataView = GridDataView;

        /** @ignore */
        var GridLocalDataDataView = (function (_super) {
            __extends(GridLocalDataDataView, _super);
            function GridLocalDataDataView(real) {
                _super.call(this, real);
                this.real = real;
            }
            GridLocalDataDataView.create = function (dataView) {
                return new GridLocalDataDataView(dataView);
            };

            GridLocalDataDataView.prototype._unsafeReplace = function (index, newItem) {
                this.real.sourceArray[index] = newItem;
                this.real.local[index] = newItem;
            };

            GridLocalDataDataView.prototype._unsafeSplice = function (index, count, item) {
                if (arguments.length === 2) {
                    this.real.sourceArray.splice(index, count);
                    this.real.local.splice(index, count);
                } else {
                    this.real.sourceArray.splice(index, count, item);
                    this.real.local.splice(index, count, item);
                }
            };

            GridLocalDataDataView.prototype._unsafePush = function (item) {
                this.real.sourceArray.push(item);
                this.real.local.push(item);
            };
            return GridLocalDataDataView;
        })(GridDataView);
        grid.GridLocalDataDataView = GridLocalDataDataView;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));

/// <reference path="../../../data/src/dataView.ts"/>
/// <reference path="../../../data/src/arrayDataView.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};

var wijmo;
(function (wijmo) {
    (function (grid) {
        /** @ignore */
        var koDataView = (function (_super) {
            __extends(koDataView, _super);
            function koDataView(observableArray) {
                this.mObservableArray = observableArray;

                var sourceArray = ko.utils.unwrapObservable(this.mObservableArray);

                _super.call(this, sourceArray, null);
            }
            koDataView.validSource = function (source) {
                return !!(ko && ko.isObservable(source) && $.isFunction(source.slice));
            };

            koDataView.prototype.refresh = function (shape, local) {
                if (typeof local === "undefined") { local = false; }
                this.sourceArray = ko.utils.unwrapObservable(this.mObservableArray);
                this.mRefreshPlainValue = true;

                // ** #53562: ensure that pageIndex is within [0; pageCount) range
                var pageSize = shape && shape.pageSize !== undefined ? shape.pageSize : this.pageSize();

                var pageIndex = shape && shape.pageIndex !== undefined ? shape.pageIndex : this.pageIndex();

                if (pageSize > 0 && pageIndex > 0) {
                    var pageCount = wijmo.data.util.pageCount(this.sourceArray.length, pageSize);

                    if (pageIndex >= pageCount) {
                        pageIndex = Math.max(0, pageCount - 1);

                        if (!shape) {
                            shape = {};
                        }

                        shape.pageIndex = pageIndex;
                    }
                }

                // ** #53562: ensure that pageIndex is within[0; pageCount) range
                return _super.prototype.refresh.apply(this, [shape, local]);
            };

            koDataView.prototype.getPlainSource = function () {
                if (this.mRefreshPlainValue) {
                    this.mRefreshPlainValue = false;

                    this.mPlainArray = ko.toJS(this.sourceArray);
                }

                return this.mPlainArray;
            };

            koDataView.prototype.dispose = function () {
                this.mObservableArray = null;
                this.mPlainArray = null;

                _super.prototype.dispose.apply(this, arguments);
            };

            koDataView.prototype.remove = function (item) {
                var entry = this._resolve(item, false);

                if (entry) {
                    this.mObservableArray.remove(entry.item);
                    return true;
                }

                return false;
            };
            return koDataView;
        })(wijmo.data.ArrayDataView);
        grid.koDataView = koDataView;
    })(wijmo.grid || (wijmo.grid = {}));
    var grid = wijmo.grid;
})(wijmo || (wijmo = {}));
;
/// <reference path="../External/declarations/jquery.d.ts"/>
/// <reference path="../External/declarations/raphael.d.ts"/>
/// <reference path="../External/declarations/globalize.d.ts"/>
var wijmo;
(function (wijmo) {
    var $ = jQuery;

    var ExtendJQuery = (function () {
        function ExtendJQuery() {
        }
        ExtendJQuery.prototype.round = function (val, digits) {
            if (!val) {
                return 0;
            }

            // do not use the Globalize to round an number.
            var rate = Math.pow(10, digits || 2);
            return Math.round(val * rate) / rate;
            //var value = Globalize.format(val, "N" + digits);
            //return Globalize.parseFloat(value);
            //return Globalize.parseFloat(val.toFixed(digits), 10, Globalize.culture("en"));
        };
        ExtendJQuery.prototype.toOADate = function (time) {
            var day = 24 * 60 * 60 * 1000, oaDate = null;

            if (time && time.valueOf) {
                oaDate = time.valueOf() - new Date(1900, 0, 1).valueOf() + 2 * day;
            }
            return oaDate;
        };
        ExtendJQuery.prototype.fromOADate = function (oaDate) {
            var day = 24 * 60 * 60 * 1000, time = new Date(oaDate - 2 * day + new Date(1900, 0, 1).getTime());

            return time;
        };
        ExtendJQuery.prototype.arrayClone = function (arr) {
            var result = [];
            $.each(arr, function (i, n) {
                result.push($.extend(true, {}, n));
            });
            return result;
        };
        return ExtendJQuery;
    })();

    var WijRaphael = (function () {
        function WijRaphael() {
        }
        WijRaphael.prototype.isSVGElem = function (node) {
            var svgNS = "http://www.w3.org/2000/svg";
            return (node.nodeType === 1 && node.namespaceURI === svgNS);
        };
        WijRaphael.prototype.addClass = function (ele, classNames) {
            classNames = classNames || '';
            var self = this;

            $.each(ele, function () {
                if (self.isSVGElem(this)) {
                    var node = this;
                    $.each(classNames.split(/\s+/), function (i, className) {
                        var classes = (node.className ? node.className.baseVal : node.getAttribute('class'));
                        if ($.inArray(className, classes.split(/\s+/)) === -1) {
                            classes += (classes ? ' ' : '') + className;

                            if (node.className) {
                                node.className.baseVal = classes;
                            } else {
                                node.setAttribute('class', classes);
                            }
                        }
                    });
                } else {
                    $(this).addClass(classNames);
                }
            });
        };

        // to do this methods
        WijRaphael.prototype.clearRaphaelCache = function () {
            // the raphael.d.ts not support.
            //Raphael.path2curve.cache = null;
            //Raphael.path2curve.count = null;
            //Raphael.parseTransformString.cache = null;
            //Raphael.parseTransformString.count = null;
            //Raphael.parsePathString.cache = null;
            //Raphael.parsePathString.count = null;
            //Raphael._pathToAbsolute.cache = null;
            //Raphael._pathToAbsolute.count = null;
        };

        WijRaphael.prototype.getPositionByAngle = function (cx, cy, r, angle) {
            var point = { x: 0, y: 0 }, rad = Raphael.rad(angle);
            point.x = cx + r * Math.cos(-1 * rad);
            point.y = cy + r * Math.sin(-1 * rad);
            return point;
        };
        WijRaphael.prototype.hasClass = function (ele, className) {
            if (!className || className.length === 0) {
                return false;
            }
            if (this.isSVGElem(ele)) {
                var cName = ele.className ? ele.className.baseVal : ele.getAttribute('class'), hasClass = false;

                $.each(cName.split(/\s+/), function (i, c) {
                    if (c === className) {
                        hasClass = true;
                        return false;
                    }
                });
                return hasClass;
                //return !!cName.match(new RegExp(className));
            } else {
                return $(ele).hasClass(className);
            }
        };
        WijRaphael.prototype.sector = function (cx, cy, r, startAngle, endAngle) {
            var start = this.getPositionByAngle(cx, cy, r, startAngle), end = this.getPositionByAngle(cx, cy, r, endAngle);

            return [
                "M", cx, cy, "L", start.x, start.y, "A", r, r, 0,
                +(endAngle - startAngle > 180), 0, end.x, end.y, "z"];
        };
        return WijRaphael;
    })();

    $.extend(ExtendJQuery.prototype);
    $.extend({ wijraphael: WijRaphael.prototype });

    var whitespace = "[\\x20\\t\\r\\n\\f]";
    var jqueryFilterCLASS = $.expr.filter.CLASS;
    var compareVersion = function (version, versionToCompare) {
        var arrVer = version.split("."), arrVerTC = versionToCompare.split("."), len = Math.max(arrVer.length, arrVerTC.length), result = 0, i, v1, v2;

        for (i = 0; i < len; i++) {
            v1 = arrVer[i] ? parseInt(arrVer[i]) : 0;
            v2 = arrVerTC[i] ? parseInt(arrVerTC[i]) : 0;
            if (v1 > v2) {
                result = 1;
                break;
            } else if (v1 < v2) {
                result = -1;
                break;
            }
        }
        return result;
    };

    $.expr.filter.CLASS = function (elem, match) {
        if (compareVersion($.fn.jquery, "1.8") < 0) {
            var className = (!($.wijraphael && $.wijraphael.isSVGElem(elem)) ? elem.className : (elem.className ? elem.className.baseVal : elem.getAttribute('class')));
            return (' ' + className + ' ').indexOf(match) > -1;
        } else {
            //return jqueryFilterCLASS(elem);
            var pattern = new RegExp("(^|" + whitespace + ")" + elem + "(" + whitespace + "|$)");
            return function (ele) {
                var className = (!($.wijraphael && $.wijraphael.isSVGElem(ele)) ? ele.className : (ele.className ? ele.className.baseVal : ele.getAttribute('class')));
                return pattern.test(className);
            };
        }
    };

    if (compareVersion($.fn.jquery, "1.8") < 0) {
        $.expr.preFilter.CLASS = function (match, curLoop, inplace, result, not, isXML) {
            var i = 0, elem = null, className = null, condition;

            match = ' ' + match[1].replace(/\\/g, '') + ' ';
            if (isXML) {
                return match;
            }
            for (i = 0, elem = {}; elem; i++) {
                elem = curLoop[i];
                if (!elem) {
                    try  {
                        elem = curLoop.item(i);
                    } catch (e) {
                    }
                }
                if (elem) {
                    className = (!($.wijraphael && $.wijraphael.isSVGElem(elem)) ? elem.className : (elem.className ? elem.className.baseVal : '') || elem.getAttribute('class'));
                    condition = className && (' ' + className + ' ').indexOf(match) > -1;
                    if (not ^ condition) {
                        if (!inplace) {
                            result.push(elem);
                        }
                    } else if (inplace) {
                        curLoop[i] = false;
                    }
                }
            }
            return false;
        };
    }

    Raphael.fn.tri = function (x, y, length) {
        var x1 = x, y1 = y - length, offsetX = Math.cos(30 * Math.PI / 180) * length, offsetY = Math.tan(60 * Math.PI / 180) * offsetX, x2 = x + offsetX, y2 = y + offsetY, x3 = x - offsetX, y3 = y + offsetY, arrPath = ["M", x1.toString(), y1.toString(), "L", x2.toString(), y2.toString(), "L", x3.toString(), y3.toString(), "z"];
        return this.path(arrPath.join(" "));
    };
    Raphael.fn.invertedTri = function (x, y, length) {
        var x1 = x, y1 = y + length, offsetX = Math.cos(30 * Math.PI / 180) * length, offsetY = Math.tan(60 * Math.PI / 180) * offsetX, x2 = x + offsetX, y2 = y - offsetY, x3 = x - offsetX, y3 = y - offsetY, arrPath = ["M", x1.toString(), y1.toString(), "L", x2.toString(), y2.toString(), "L", x3.toString(), y3.toString(), "z"];
        return this.path(arrPath.join(" "));
    };
    Raphael.fn.box = function (x, y, length) {
        var offset = Math.cos(45 * Math.PI / 180) * length, arrPath = [
            "M", x - offset, y - offset, "L", x + offset, y - offset,
            "L", x + offset, y + offset, "L", x - offset, y + offset, "z"];
        return this.path(arrPath.join(" "));
    };
    Raphael.fn.diamond = function (x, y, length) {
        var arrPath = [
            "M", x, y - length, "L", x + length, y, "L", x, y + length,
            "L", x - length, y, "z"];
        return this.path(arrPath.join(" "));
    };
    Raphael.fn.cross = function (x, y, length) {
        var offset = Math.cos(45 * Math.PI / 180) * length, arrPath = [
            "M", x - offset, y - offset, "L", x + offset, y + offset,
            "M", x - offset, y + offset, "L", x + offset, y - offset];
        return this.path(arrPath.join(" "));
    };
    Raphael.fn.paintMarker = function (type, x, y, length) {
        var self = this, marker = null;
        if (!type) {
            type = "circle";
        }
        switch (type) {
            case "circle":
                marker = self.circle(x, y, length);
                break;
            case "tri":
                marker = self.tri(x, y, length);
                break;
            case "invertedTri":
                marker = self.invertedTri(x, y, length);
                break;
            case "box":
                marker = self.box(x, y, length);
                break;
            case "diamond":
                marker = self.diamond(x, y, length);
                break;
            case "cross":
                marker = self.cross(x, y, length);
                break;
        }
        return marker;
    };
    Raphael.fn.htmlText = function (x, y, text, attrs, wordSpace, lineSpace) {
        var applyStyle = function (txt, sp, attrs) {
            var strongRegx = /<(b|strong)>/, italicRegx = /<(i|em)>/, hrefRegex = /href=[\"\']([^\"\']+)[\"\']/, aRegex = /<a/;
            if (attrs) {
                txt.attr(attrs);
            }
            if (strongRegx.test(sp)) {
                txt.attr("font-weight", "bold");
            }
            if (italicRegx.test(sp)) {
                txt.attr("font-style", "italic");
            }
            if (aRegex.test(sp)) {
                if (sp.match(hrefRegex)[1]) {
                    txt.attr("href", sp.match(hrefRegex)[1]);
                }
            }
        };

        var texts = text.toString().split(/<br\s?\/>|\\r/i), self = this, st = self.set(), totalX = 0, totalY = 0;

        //set default value of word spacing and line spacing
        wordSpace = wordSpace || 3;
        lineSpace = lineSpace || 5;

        $.each(texts, function (ridx, item) {
            var maxHeight = 0, spans = item.split('|||');
            item = item.replace(/<([A-Za-z]+(.|\n)*?)>/g, '|||<$1>').replace(/<\/([A-Za-z]*)>/g, '</$1>|||');

            $.each(spans, function (cidx, span) {
                var temp = null, box = null, offsetX = 0, txtEl, offsetY = 0;
                if (span !== '') {
                    temp = span;
                    temp = $.trim(temp.replace(/<(.|\n)*?>/g, ''));
                    txtEl = self.text(0, 0, temp);
                    applyStyle(txtEl, span, attrs);

                    box = txtEl.wijGetBBox();
                    offsetX = box.width / 2 + totalX;
                    offsetY = -box.height / 2 + totalY;
                    totalX = totalX + box.width + wordSpace;
                    txtEl.translate(offsetX, offsetY);

                    st.push(txtEl);
                    if (maxHeight < box.height) {
                        maxHeight = box.height;
                    }
                }
            });
            totalY += maxHeight + lineSpace;
            totalX = maxHeight = 0;
        });
        totalY = 0;

        //st.translate(x - st.getBBox().x, y - st.getBBox().y);
        st.transform(Raphael.format("...t{0},{1}", x - st.getBBox().x, y - st.getBBox().y));

        return st;
    };
    Raphael.fn.line = function (startX, startY, endX, endY) {
        return this.path(["M", startX.toString(), startY.toString(), "L", endX.toString(), endY.toString()]);
    };
    Raphael.fn.roundRect = function (x, y, width, height, tlCorner, lbCorner, brCorner, rtCorner) {
        var rs = [], posFactors = [-1, 1, 1, 1, 1, -1, -1, -1], orientations = ["v", "h", "v", "h"], pathData = null, lens = null;
        $.each([tlCorner, lbCorner, brCorner, rtCorner], function (idx, corner) {
            if (typeof (corner) === "number") {
                rs = rs.concat([{ x: corner, y: corner }]);
            } else if (typeof (corner) === "object") {
                rs = rs.concat(corner);
            } else {
                rs = rs.concat([{ x: 0, y: 0 }]);
            }
        });

        pathData = ["M", x + rs[0].x, y];
        lens = [
            height - rs[0].y - rs[1].y, width - rs[1].x - rs[2].x,
            rs[2].y + rs[3].y - height, rs[3].x + rs[0].x - width];

        $.each(rs, function (idx, r) {
            if (r.x && r.y) {
                pathData = pathData.concat("a", r.x, r.y, 0, 0, 0, posFactors[2 * idx] * r.x, posFactors[2 * idx + 1] * r.y);
            }

            pathData = pathData.concat(orientations[idx], lens[idx]);
        });

        pathData.push("z");

        return this.path(pathData);
    };
    Raphael.fn.wrapText = function (x, y, text, width, textAlign, textStyle) {
        var self = this, rotation = textStyle.rotation, style = rotation ? $.extend(true, {}, textStyle, { rotation: 0 }) : textStyle, top = y, texts = self.set(), bounds = null, center = null, textBounds = [];

        if (typeof text === "undefined") {
            text = "";
        }

        function splitString(text, width, textStyle) {
            var tempText = null, bounds = null, words = text.toString().split(' '), lines = [], line = [], tempTxt = "";
            while (words.length) {
                tempTxt += ' ' + words[0];
                tempText = self.text(-1000, -1000, tempTxt);
                tempText.attr(textStyle);
                bounds = tempText.wijGetBBox();

                if (bounds.width > width) {
                    if (line.length) {
                        lines.push(line);
                        tempTxt = words[0];
                    }
                    line = [words.shift()];
                } else {
                    line.push(words.shift());
                }

                if (words.length === 0) {
                    lines.push(line);
                }

                tempText.wijRemove();
                tempText = null;
            }

            return lines;
        }

        $.each(splitString(text, width, style), function (idx, line) {
            var lineText = line.join(' '), align = textAlign || "near", txt = self.text(x, top, lineText), offsetX = 0, offsetY = 0;

            txt.wijAttr(style, null);

            bounds = txt.wijGetBBox();

            switch (align) {
                case "near":
                    offsetX = width - bounds.width / 2;

                    break;
                case "center":
                    offsetX += width / 2;

                    break;
                case "far":
                    offsetX += bounds.width / 2;

                    break;
            }

            //add comments to fix tfs issue 19384
            if (rotation) {
                offsetY += bounds.height / 2 / Math.abs(Math.sin(rotation));
                top += bounds.height / Math.abs(Math.sin(rotation));
            } else {
                offsetY += bounds.height / 2;
                top += bounds.height;
            }

            //end comments
            bounds.x += offsetX;
            bounds.y += offsetY;
            if (rotation) {
                txt.attr({
                    x: txt.attr("x") + offsetX,
                    y: txt.attr("y") + offsetY
                });
            } else {
                txt.transform(Raphael.format("...T{0},{1}", offsetX, offsetY));
            }
            texts.push(txt);
            textBounds.push(bounds);
        });

        if (rotation) {
            bounds = texts.wijGetBBox();
            if (texts.length > 1) {
                $.each(texts, function (idx, txt) {
                    txt.attr({ y: txt.attr("y") - bounds.height / 2 });
                    textBounds[idx].y -= bounds.height / 2;
                });
                center = {
                    x: bounds.x + bounds.width / 2,
                    y: bounds.y + bounds.height / 2
                };

                $.each(texts, function (idx, txt) {
                    var math = Math, tb = textBounds[idx], txtCenter = {
                        x: tb.x + tb.width / 2,
                        y: tb.y + tb.height / 2
                    }, len = math.sqrt(math.pow(txtCenter.x - center.x, 2) + math.pow(txtCenter.y - center.y, 2)), theta = 0, rotatedTB = null, newTxtCenter = null;

                    txt.attr({ rotation: rotation });

                    if (len === 0) {
                        return true;
                    }
                    rotatedTB = txt.wijGetBBox();

                    theta = Raphael.deg(math.asin(math.abs(txtCenter.y - center.y) / len));

                    if (txtCenter.y > center.y) {
                        if (txtCenter.x > center.x) {
                            theta -= 360;
                        } else {
                            theta = -1 * (theta + 180);
                        }
                    } else {
                        if (txtCenter.x > center.x) {
                            theta *= -1;
                        } else {
                            theta = -1 * (180 - theta);
                        }
                    }
                    newTxtCenter = $.wijraphael.getPositionByAngle(center.x, center.y, len, -1 * (rotation + theta));

                    txt.attr({
                        y: txt.attr("y") + newTxtCenter.y - rotatedTB.y - rotatedTB.height / 2
                    });
                });
            } else {
                texts[0].transform(Raphael.format("...R{0}", rotation));
            }
        }

        return texts;
    };
    Raphael.fn.getSVG = function () {
        function createSVGElement(type, options) {
            var element = '<' + type + ' ', val = null, styleExist = false;

            $.each(options, function (name, val) {
                if (name === "text" || name === "opacity" || name === "transform" || name === "path" || name === "w" || name === "h" || name === "translation") {
                    return true;
                }

                if (val) {
                    if (name === "stroke" && val === 0) {
                        val = "none";
                    }

                    element += name + "='" + val + "' ";
                }
            });

            /*
            for (name in options) {
            if (name === "text" || name === "opacity" ||
            name === "transform" || name === "path" ||
            name === "w" || name === "h" || name === "translation") {
            continue;
            }
            
            if ((val = options[name]) !== null) {
            if (name === "stroke" && val === 0) {
            val = "none";
            }
            
            element += name + "='" + val + "' ";
            }
            }
            */
            if (options.opacity) {
                val = options.opacity;
                element += "opacity='" + val + "' style='opacity:" + val + ";";
                styleExist = true;
            }

            if (options.transform && options.transform.length > 0) {
                val = options.transform;
                if (styleExist) {
                    element += "transform:" + val;
                } else {
                    element += "style='transform:" + val;
                    styleExist = true;
                }
            }

            if (styleExist) {
                element += "'";
            }

            if (options.text) {
                val = options.text;
                element += "><tspan>" + val + "</tspan>";
            } else {
                element += ">";
            }

            element += "</" + type + ">";

            return element;
        }

        var paper = this, svg = '<svg xmlns="http://www.w3.org/2000/svg" ' + 'xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="' + paper.canvas.offsetWidth + '" height="' + paper.canvas.offsetHeight + '"><desc>Created with Raphael</desc><defs></defs>', node, path = "", trans, group, value, idx = 0, len1 = 0, index = 0, len2 = 0;

        for (node = paper.bottom; node; node = node.next) {
            if (node && node.type) {
                switch (node.type) {
                    case "path":
                        for (idx = 0, len1 = node.attrs.path.length; idx < len1; idx++) {
                            group = node.attrs.path[idx];

                            for (index = 0, len2 = group.length; index < len2; index++) {
                                value = group[index];

                                if (index < 1) {
                                    path += value;
                                } else {
                                    if (index === (len2 - 1)) {
                                        path += value;
                                    } else {
                                        path += value + ',';
                                    }
                                }
                            }
                        }

                        if (path && path.length > 0) {
                            node.attrs.d = path.replace(/,/g, ' ');
                        }
                        break;
                    case "text":
                        if (!node.attrs["text-anchor"]) {
                            node.attrs["text-anchor"] = "middle";
                        }
                        break;
                    case "image":
                        trans = node.transformations;
                        node.attrs.transform = trans ? trans.join(' ') : '';
                        break;
                    case "ellipse":
                    case "rect":
                        svg += createSVGElement(node.type, node.attrs);
                        break;
                }
            }
        }

        svg += '</svg>';

        return svg;
    };

    Raphael.fn.group = function () {
        var r = this;
        function Group() {
            var inst, set = r.set(), group = r.raphael.vml ? document.createElement("group") : document.createElementNS("http://www.w3.org/2000/svg", "g");

            r.canvas.appendChild(group);
            inst = {
                type: 'group',
                node: group,
                // In raphael attr method, it need paper, attrs, _, so here define it.
                paper: r,
                attrs: {},
                _: {},
                id: Raphael.createUUID(),
                push: function (item) {
                    function pushOneRaphaelVector(it) {
                        var i;
                        if (it.type === 'set') {
                            for (i = 0; i < it.length; i++) {
                                pushOneRaphaelVector(it[i]);
                            }
                        } else {
                            group.appendChild(it.node);
                            set.push(it);
                        }
                    }
                    if (arguments.length > 1) {
                        $.each(arguments, function (i, arg) {
                            pushOneRaphaelVector(arg);
                        });
                    } else {
                        pushOneRaphaelVector(item);
                    }
                    return this;
                },
                getBBox: function () {
                    return set.getBBox();
                },
                transform: function (matrix) {
                    var baseMatrix = this.matrix || Raphael.matrix(1, 0, 0, 1, 0, 0);
                    var mts = Raphael.format("{0},{1},{2},{3},{4},{5}", matrix.a, matrix.b, matrix.c, matrix.d, matrix.e, matrix.f);

                    if (Raphael.svg) {
                        mts = Raphael.format("matrix({0})", mts);
                        group.setAttribute("transform", mts);
                    } else {
                        var mstr = "DXImageTransform.Microsoft.Matrix", hasMatrix;
                        try  {
                            hasMatrix = !!group["filters"].item(mstr);
                        } catch (e) {
                            hasMatrix = false;
                        }

                        var m11 = matrix.a, m12 = matrix.c, m21 = matrix.b, m22 = matrix.d;

                        if (hasMatrix) {
                            group["filters"].item(mstr).M11 = m11;
                            group["filters"].item(mstr).M12 = m12;
                            group["filters"].item(mstr).M21 = m21;
                            group["filters"].item(mstr).M22 = m22;

                            // use 'nearest' for a faster transform
                            group["filters"].item(mstr).filterType = 'bilinear';
                            group["filters"].item(mstr).Dx = 0;
                            group["filters"].item(mstr).Dy = 0;
                            group["filters"].item(mstr).sizingMethod = 'auto expand';
                        } else {
                            group["style"].filter += " progid:" + mstr + "(M11=" + m11 + ",M12=" + m12 + ",M21=" + m21 + ",M22=" + m22 + ",FilterType='bilinear',Dx=0,Dy=0,sizingMethod='auto expand')";
                        }
                    }
                    return this;
                }
            };

            // create methods which is extend from Raphael.
            $.each(["attr", "stop", "animate", "wijAnimate", "remove", "wijRemove"], function (i, name) {
                inst[name] = function () {
                    if (Raphael.el[name]) {
                        return Raphael.el[name].apply(this, arguments);
                    }
                };
            });

            return inst;
        }
        return Group();
    };

    Raphael.el.wijRemove = function () {
        var self = this, jqobj;
        if (self.removed) {
            return;
        }
        if (self.node.parentNode) {
            jqobj = $(self.node);
            self.stop().remove();
            jqobj.remove();
        }
    };
    Raphael.el.wijGetBBox = function () {
        return this.getBBox();
    };
    Raphael.el.wijAnimate = function (params, ms, easing, callback) {
        if (!params || $.isEmptyObject(params)) {
            return;
        }

        if ($.isPlainObject(params)) {
            $.each(params, function (key, val) {
                parseOption(key, val, params);
            });
        }

        var shadow = this.shadow, offset = 0, jQEasing = {
            easeInCubic: ">",
            easeOutCubic: "<",
            easeInOutCubic: "<>",
            easeInBack: "backIn",
            easeOutBack: "backOut",
            easeOutElastic: "elastic",
            easeOutBounce: "bounce"
        };

        if (jQEasing[easing]) {
            easing = jQEasing[easing];
        }
        this.animate(params, ms, easing, callback);
        jQEasing = null;
        if (shadow && shadow.offset) {
            offset = shadow.offset;
            if (params.x) {
                params.x += offset;
            }
            if (params.y) {
                params.y += offset;
            }
            this.shadow.animate(params, ms, easing, callback);
        }
    }, Raphael.el.wijAttr = function (name, value) {
        if ($.isPlainObject(name)) {
            $.each(name, function (key, val) {
                parseOption(key, val, name);
            });
        } else if (typeof (name) === "string") {
            name = parseOption(name, value);
        }

        this.attr(name, value);

        if (this.shadow) {
            if (typeof (name) === "object") {
                var newName = $.extend(true, {}, name);
                if (newName.fill) {
                    delete newName.fill;
                }
                if (newName.stroke) {
                    delete newName.stroke;
                }
                if (newName["stroke-width"]) {
                    delete newName["stroke-width"];
                }
                this.shadow.attr(newName, value);
            } else if (typeof (name) === "string") {
                switch (name) {
                    case "clip-rect":
                    case "cx":
                    case "cy":
                    case "fill-opacity":
                    case "font":
                    case "font-family":
                    case "font-size":
                    case "font-weight":
                    case "height":
                    case "opacity":
                    case "path":
                    case "r":
                    case "rotation":
                    case "rx":
                    case "ry":
                    case "scale":
                    case "stroke-dasharray":
                    case "stroke-linecap":
                    case "stroke-linejoin":
                    case "stroke-miterlimit":
                    case "stroke-opacity":
                    case "stroke-width":
                    case "translation":
                    case "width":
                        this.shadow.attr(name, value);
                        break;
                    case "x":
                        this.shadow.attr(name, value);

                        //this.shadow.attr("translation", "1 0");
                        this.shadow.attr("transform", "...t1,0");
                        break;
                    case "y":
                        this.shadow.attr(name, value);

                        //this.shadow.attr("translation", "0 1");
                        this.shadow.attr("transform", "...t0,1");
                        break;
                    default:
                        break;
                }
            }
        }
    };

    Raphael.st.wijRemove = function () {
        $.each(this, function (idx, obj) {
            if (obj.wijRemove && !obj.removed) {
                obj.wijRemove();
            }
        });
    };
    Raphael.st.wijAttr = function (name, value) {
        $.each(this.items, function (idx, item) {
            item.wijAttr(name, value);
        });
        return this;
    };
    Raphael.st.wijAnimate = function (params, ms, easing, callback) {
        var i = 0, ii = 0, item = null;
        for (i = 0, ii = this.items.length; i < ii; i++) {
            item = this.items[i];
            if (!item.removed) {
                item.wijAnimate(params, ms, easing, callback);
            }
        }
        return this;
    };
    Raphael.st.wijGetBBox = function () {
        var x = [], y = [], w = [], h = [], bx, by, mmax = Math.max, mmin = Math.min, push = "push", apply = "apply", box = null, i = 0;
        for (i = this.items.length - 1; i >= 0; i--) {
            box = this.items[i].wijGetBBox();
            x[push](box.x);
            y[push](box.y);
            w[push](box.x + box.width);
            h[push](box.y + box.height);
        }
        bx = mmin[apply](0, x);
        by = mmin[apply](0, y);
        return {
            x: bx,
            y: by,
            x2: undefined,
            y2: undefined,
            width: mmax[apply](0, w) - bx,
            height: mmax[apply](0, h) - by
        };
    };

    // fixed an issue that when set to width/height/r to negative value,
    // the browser will throw exception in console.  This issue is found in
    // bar chart seriesTransition animation when the easing is backIn.
    var raphaelAttr = Raphael.el.attr, handleValue = function (key, val) {
        if (key === "width" || key === "height" || key === "r") {
            if (!isNaN(val) && val < 0) {
                return 0;
            }
        } else if (key === "clip-rect") {
            if ($.isArray(val)) {
                $.each(val, function (i, v) {
                    if (!isNaN(v) && v < 0) {
                        val[i] = 0;
                    }
                });
            }
        }
        return val;
    }, parseOption = function (optName, optValue, attr) {
        // for some attr parameters for svg element, they should obey the patter like 'xxxx-xxxx'
        // They are 'arrow-end', 'clip-rect', 'fill' related attribute, 'font' related attribute,
        // 'stroke' related attribute and 'text' related attribute.
        var newOptName = optName.toLowerCase().replace(/^(font|stroke|clip|arrow|text|fill)(\w+)$/, "$1-$2");
        if (attr && newOptName !== optName) {
            delete attr[optName];
            attr[newOptName] = optValue;
        }

        return newOptName;
    };
    Raphael.el.attr = function (name, value) {
        if ($.isPlainObject(name)) {
            $.each(name, function (key, val) {
                name[key] = handleValue(key, val);
            });
        } else {
            value = handleValue(name, value);
        }

        return raphaelAttr.apply(this, arguments);
    };
})(wijmo || (wijmo = {}));
;
/// <reference path="../Base/jquery.wijmo.widget.ts" />
/// <reference path="../wijutil/jquery.wijmo.raphael.ts"/>
/// <reference path="../wijtooltip/jquery.wijmo.wijtooltip.ts"/>
/// <reference path="../external/declarations/globalize.d.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*globals $, Raphael, jQuery, document, window, Globalize, wijmoASPNetParseOptions*/
    /*
    * Depends:
    *  raphael.js
    *  globalize.js
    *  jquery.svgdom.js
    *  jquery.ui.widget.js
    *
    */
    (function (chart) {
        var $ = jQuery, disabledCss = ".35";

        /** @ignore */
        var TrendlineFitType = (function () {
            function TrendlineFitType() {
            }
            TrendlineFitType.strPolynom = "polynom";

            TrendlineFitType.strExponent = "exponent";

            TrendlineFitType.strLogarithmic = "logarithmic";

            TrendlineFitType.strPower = "power";

            TrendlineFitType.strFourier = "fourier";

            TrendlineFitType.strMinX = "minX";

            TrendlineFitType.strMinY = "minY";

            TrendlineFitType.strMaxX = "maxX";

            TrendlineFitType.strMaxY = "maxY";

            TrendlineFitType.strAverageX = "averageX";

            TrendlineFitType.strAverageY = "averageY";
            return TrendlineFitType;
        })();
        chart.TrendlineFitType = TrendlineFitType;

        /** @ignore */
        var ChartConsts = (function () {
            function ChartConsts() {
            }
            ChartConsts.strTrendline = "trendLine";
            return ChartConsts;
        })();
        chart.ChartConsts = ChartConsts;

        /** @ignore */
        var ChartUtil = (function () {
            function ChartUtil() {
            }
            ChartUtil.getDiffAttrs = function (attrs, newAttrs) {
                var result = {};

                $.each(newAttrs, function (key, attr) {
                    if (typeof (attrs) === "undefined") {
                        return true;
                    } else if (typeof (attrs[key]) === "undefined") {
                        result[key] = newAttrs[key];
                    } else if (attrs[key] !== newAttrs[key]) {
                        result[key] = newAttrs[key];
                    }
                });

                return result;
            };

            //To do: make sure what is the type of the element.
            ChartUtil.paintShadow = function (element, offset, stroke) {
                if (element.removed || $(element.node).parent().length === 0) {
                    return;
                }
                var shadow = element.clone(), newOffset = offset || 1, newStroke = stroke || "#cccccc";

                shadow.insertBefore(element);
                shadow.attr({
                    // translation: newOffset + " " + newOffset,
                    transform: Raphael.format("...T{0},{1}", newOffset, newOffset),
                    stroke: newStroke,
                    // the shadow should not fill an color.
                    fill: "none",
                    "stroke-width": newOffset
                });
                shadow.toBack();
                shadow.offset = newOffset;
                element.shadow = shadow;
            };
            ChartUtil.getScaling = function (isVertical, max, min, length) {
                var dx = max - min;

                if (dx === 0) {
                    dx = 1;
                }

                if (isVertical) {
                    dx = -dx;
                }

                return length / dx;
            };
            ChartUtil.getTranslation = function (isVertical, location, max, min, scaling) {
                var translation = 0;

                if (isVertical) {
                    translation = location.y;
                    translation -= scaling * max;
                } else {
                    translation = location.x;
                    translation -= scaling * min;
                }

                return translation;
            };
            ChartUtil.getXSortedPoints = function (series) {
                var seriesX = series.data.x, tempX = [].concat(seriesX), tempY = [].concat(series.data.y), points = [], sortedX = seriesX;

                if (seriesX === undefined || seriesX.length === 0) {
                    return;
                }

                function sortNumber(a, b) {
                    return a - b;
                }

                if (typeof (seriesX[0]) === "number") {
                    sortedX = [].concat(seriesX).sort(sortNumber);
                }

                $.each(sortedX, function (i, nSortedX) {
                    $.each(tempX, function (j, nx) {
                        if (nSortedX === nx) {
                            if (typeof (nx) !== "number") {
                                nx = i;
                            }
                            points.push({ x: nx, y: tempY[j] });
                            tempX.splice(j, 1);
                            tempY.splice(j, 1);
                            return false;
                        }
                    });
                });

                return points;
            };
            ChartUtil.sector = function (cx, cy, r, startAngle, endAngle) {
                var start = $.wijraphael.getPositionByAngle(cx, cy, r, startAngle), end = $.wijraphael.getPositionByAngle(cx, cy, r, endAngle);

                var largeArcFlag, sweepFlag, angleDiff, isConvex;

                if (endAngle > startAngle) {
                    angleDiff = endAngle - startAngle;
                    isConvex = angleDiff > 180;
                    if (isConvex) {
                        largeArcFlag = 1;
                        sweepFlag = 0;
                    } else {
                        largeArcFlag = +isConvex;
                        sweepFlag = +isConvex;
                    }
                } else {
                    angleDiff = startAngle - endAngle;
                    isConvex = angleDiff > 180;

                    if (isConvex) {
                        largeArcFlag = 1;
                        sweepFlag = 1;
                    } else {
                        largeArcFlag = +isConvex;
                        sweepFlag = +!isConvex;
                    }
                }

                return [
                    "M", cx, cy, "L", start.x, start.y, "A", r, r, 0,
                    largeArcFlag, sweepFlag, end.x, end.y, "z"];
            };
            ChartUtil.donut = function (cx, cy, outerR, innerR, startAngle, endAngle) {
                var outerS = $.wijraphael.getPositionByAngle(cx, cy, outerR, startAngle), outerE = $.wijraphael.getPositionByAngle(cx, cy, outerR, endAngle), innerS = $.wijraphael.getPositionByAngle(cx, cy, innerR, startAngle), innerE = $.wijraphael.getPositionByAngle(cx, cy, innerR, endAngle), largeAngle = endAngle - startAngle > 180;

                var largeArcFlagStart, sweepFlagStart, largeArcFlagEnd, sweepFlagEnd, angleDiff, isConvex;

                // if direction is counter clockwise
                if (endAngle > startAngle) {
                    angleDiff = endAngle - startAngle;
                    isConvex = angleDiff > 180;
                    if (isConvex) {
                        largeArcFlagStart = 1;
                        sweepFlagStart = 0;
                        largeArcFlagEnd = 1;
                        sweepFlagEnd = 1;
                    } else {
                        largeArcFlagStart = 0;
                        sweepFlagStart = 0;
                        largeArcFlagEnd = 0;
                        sweepFlagEnd = 1;
                    }
                } else {
                    angleDiff = startAngle - endAngle;
                    isConvex = angleDiff > 180;

                    if (isConvex) {
                        largeArcFlagStart = 1;
                        sweepFlagStart = 1;
                        largeArcFlagEnd = 1;
                        sweepFlagEnd = 0;
                    } else {
                        largeArcFlagStart = 0;
                        sweepFlagStart = 1;
                        largeArcFlagEnd = 0;
                        sweepFlagEnd = 0;
                    }
                }

                return [
                    "M", outerS.x, outerS.y,
                    "A", outerR, outerR, 0, largeArcFlagStart, sweepFlagStart, outerE.x, outerE.y,
                    "L", innerE.x, innerE.y,
                    "A", innerR, innerR, 0, largeArcFlagEnd, sweepFlagEnd, innerS.x, innerS.y,
                    "L", outerS.x, outerS.y, "z"];
            };
            ChartUtil.isDate = function (obj) {
                if (!obj) {
                    return false;
                }
                return (typeof obj === 'object') && obj.constructor === Date;
            };

            ChartUtil.getNumberValues = function (values) {
                var numberValues = [], isDate, validValue = ChartUtil.getFirstValidListValue(values);

                if (typeof validValue === "number") {
                    return values;
                }
                isDate = ChartUtil.isDate(validValue);
                for (var i = 0; i < values.length; i++) {
                    if (isDate) {
                        numberValues.push($.toOADate(values[i]));
                    } else {
                        numberValues.push(i);
                    }
                }
                return numberValues;
            };
            ChartUtil.getFirstValidListValue = function (values) {
                var val;
                $.each(values, function (idx, value) {
                    if (value === null) {
                        return true;
                    } else if (typeof value === "undefined") {
                        return true;
                    } else if (typeof value === "number" && isNaN(value)) {
                        return true;
                    }
                    val = value;
                    return false;
                });
                return val;
            };

            ChartUtil.getLastValidListValue = function (values) {
                var vals = [].concat(values).reverse();
                return ChartUtil.getFirstValidListValue(vals);
            };

            ChartUtil.isHolefunction = function (val, hole) {
                if (val === null) {
                    return true;
                } else if (typeof val === "undefined") {
                    return true;
                } else if (typeof val === "number" && isNaN(val)) {
                    return true;
                }
                if (hole === null) {
                    return false;
                }
                if (typeof val !== "undefined") {
                    // for datetime, if use val === hole it returns false.
                    if (val - hole === 0) {
                        return true;
                    }
                    return false;
                }
                return false;
            };

            ChartUtil.toHexColor = function (color) {
                if ({ hs: 1, rg: 1 }.hasOwnProperty(color.toLowerCase().substring(0, 2)) || color.substring(0, 1) === "#") {
                    return color;
                } else {
                    try  {
                        var document = new ActiveXObject("htmlfile"), body, range, value;
                        document.write("<body>");
                        document.close();
                        body = document.body;
                        range = body.createTextRange();
                        body.style.color = color;
                        value = range.queryCommandValue("ForeColor");
                        value = ((value & 0x0000ff) << 16) | (value & 0x00ff00) | ((value & 0xff0000) >>> 16);
                        value = value.toString(16);
                        return "#000000".slice(0, 7 - value.length) + value;
                    } catch (e) {
                        return color;
                    }
                }
            };

            ChartUtil.getChartLabel = function (chartLabelFormatString, text, culture, opts) {
                var chartLabel = text, processed = false, args;
                if (chartLabelFormatString && chartLabelFormatString.length) {
                    processed = true;
                    chartLabel = Globalize.format(text, chartLabelFormatString, culture);
                }
                if (opts.chartLabelFormatter && $.isFunction(opts.chartLabelFormatter)) {
                    processed = true;
                    args = $.extend(true, {}, opts, { chartLabel: chartLabel });
                    chartLabel = $.proxy(opts.chartLabelFormatter, args)();
                }

                return { text: chartLabel, processed: processed };
            };
            return ChartUtil;
        })();
        chart.ChartUtil = ChartUtil;

        /** @ignore */
        var ChartDataUtil = (function () {
            function ChartDataUtil() {
            }
            ChartDataUtil.roundTime = function (timevalue, unit, roundup) {
                var self = this, tunit = unit, tv = $.fromOADate(timevalue), th, td, tx, tz;

                if (tunit > 0) {
                    th = {
                        year: tv.getFullYear(),
                        month: tv.getMonth(),
                        day: tv.getDate(),
                        hour: tv.getHours(),
                        minute: tv.getMinutes(),
                        second: tv.getSeconds()
                    };
                    if (tunit < self.tmInc.minute) {
                        th.second = self.tround(th.second, tunit, roundup);
                        return self.getTimeAsDouble(th);
                    }

                    th.second = 0;
                    if (tunit < self.tmInc.hour) {
                        tunit /= self.tmInc.minute;
                        th.minute = self.tround(th.minute, tunit, roundup);
                        return self.getTimeAsDouble(th);
                    }

                    th.minute = 0;
                    if (tunit < self.tmInc.day) {
                        tunit /= self.tmInc.hour;
                        th.hour = self.tround(th.hour, tunit, roundup);
                        return self.getTimeAsDouble(th);
                    }

                    th.hour = 0;
                    if (tunit < self.tmInc.month) {
                        tunit /= self.tmInc.day;
                        th.day = self.tround(th.day, tunit, roundup);
                        return self.getTimeAsDouble(th);
                    }

                    th.day = 1;
                    if (tunit < self.tmInc.year) {
                        tunit /= self.tmInc.month;
                        th.month = self.tround(th.month, tunit, roundup);
                        return self.getTimeAsDouble(th);
                    }

                    // th.month = 1;
                    th.month = 0; // the month start from 0 in javascript.
                    tunit /= self.tmInc.year;
                    th.year = self.tround(th.year, tunit, roundup);
                    return self.getTimeAsDouble(th);
                } else {
                    td = tv;
                    tx = td - tunit;
                    tz = parseInt((tx / unit).toString(), 10) * unit;
                    if (roundup && tz !== tx) {
                        tz += unit;
                    }
                    td = tunit + tz;
                    return td;
                }
            };

            ChartDataUtil.tround = function (tval, tunit, roundup) {
                var test = parseInt(((tval / tunit) * tunit).toString(), 10);
                if (roundup && test !== tval) {
                    test += parseInt(tunit, 10);
                }
                return test;
            };

            ChartDataUtil.getTimeAsDouble = function (th) {
                var smon = 0, sday = 0, newDate = null;
                if (th.day < 1) {
                    sday = -1 - th.day;
                    th.day = 1;
                } else if (th.day > 28) {
                    sday = th.day - 28;
                    th.day = 28;
                }

                /*
                * if (th.month < 1) { smon = -1 - th.day; th.month = 1; } else if
                * (th.month > 12) { smon = th.month - 12; th.month = 12; }
                */
                // the month start from 0 & end with 11 in javascript.
                if (th.month < 0) {
                    smon = -1 - th.day;
                    th.month = 0;
                } else if (th.month > 11) {
                    smon = th.month - 11;
                    th.month = 11;
                }
                newDate = new Date(th.year, th.month, th.day, th.hour, th.minute, th.second);
                newDate.setDate(newDate.getDate() + sday);
                newDate.setMonth(newDate.getMonth() + smon);
                return $.toOADate(newDate);
            };

            ChartDataUtil.getTimeDefaultFormat = function (max, min) {
                var self = this, range = max - min, format = "d";

                // format = "s";
                if (range > 2 * self.tmInc.year) {
                    format = "yyyy";
                } else if (range > self.tmInc.year) {
                    format = "MMM yy";
                } else if (range > 3 * self.tmInc.month) {
                    format = "MMM";
                } else if (range > 2 * self.tmInc.week) {
                    format = "MMM d";
                } else if (range > 2 * self.tmInc.day) {
                    format = "ddd d";
                } else if (range > self.tmInc.day) {
                    format = "ddd H:mm";
                } else if (range > self.tmInc.hour) {
                    format = "H:mm";
                } else if (range >= 1000) {
                    format = "H:mm:ss";
                }

                /*
                * else if (range > 0) { //TODO: return millisecond }
                */
                return format;
            };

            ChartDataUtil.niceTimeUnit = function (timeinc, manualFormat) {
                var self = this, tsRange = timeinc;

                tsRange = self.niceTimeSpan(tsRange, manualFormat);

                // return tsRange / self._tmInc.day;
                return tsRange;
            };

            ChartDataUtil.niceTimeSpan = function (range, manualFormat) {
                var self = this, minSpan = self.manualTimeInc(manualFormat), tsinc = 0, tinc = 0;

                /*
                * if (minSpan < this._tmInc.second) { //TODO: calculate when
                * millisecond }
                */
                tsinc = Math.ceil(range);
                if (tsinc === 0) {
                    return self.timeSpanFromTmInc(minSpan);
                }
                tinc = 1;
                if (minSpan < self.tmInc.minute) {
                    if (tsinc < self.tmInc.minute) {
                        tinc = self.getNiceInc([1, 2, 5, 10, 15, 30], tsinc, minSpan);
                        if (tinc !== 0) {
                            return tinc;
                        }
                    }
                    minSpan = self.tmInc.minute;
                }
                if (minSpan < self.tmInc.hour) {
                    if (tsinc < self.tmInc.hour) {
                        tinc = self.getNiceInc([1, 2, 5, 10, 15, 30], tsinc, minSpan);
                        if (tinc !== 0) {
                            return tinc;
                        }
                    }
                    minSpan = self.tmInc.hour;
                }
                if (minSpan < self.tmInc.day) {
                    if (tsinc < self.tmInc.day) {
                        tinc = self.getNiceInc([1, 3, 6, 12], tsinc, minSpan);
                        if (tinc !== 0) {
                            return tinc;
                        }
                    }
                    minSpan = self.tmInc.day;
                }
                if (minSpan < self.tmInc.month) {
                    if (tsinc < self.tmInc.month) {
                        tinc = self.getNiceInc([1, 2, 7, 14], tsinc, minSpan);
                        if (tinc !== 0) {
                            return tinc;
                        }
                    }
                    minSpan = self.tmInc.month;
                }
                if (minSpan < self.tmInc.year) {
                    if (tsinc < self.tmInc.year) {
                        tinc = self.getNiceInc([1, 2, 3, 4, 6], tsinc, minSpan);
                        if (tinc !== 0) {
                            return tinc;
                        }
                    }
                    minSpan = self.tmInc.year;
                }
                tinc = 100 * self.tmInc.year;
                if (tsinc < tinc) {
                    tinc = self.getNiceInc([1, 2, 5, 10, 20, 50], tsinc, minSpan);
                    if (tinc === 0) {
                        tinc = 100 * self.tmInc.year;
                    }
                }
                return tinc;
            };

            ChartDataUtil.getNiceInc = function (tik, ts, mult) {
                var i = 0, tikm = 0, ii = tik.length;

                for (i = 0; i < ii; i++) {
                    tikm = tik[i] * mult;
                    if (ts <= tikm) {
                        return tikm;
                    }
                }

                return 0;
            };

            ChartDataUtil.timeSpanFromTmInc = function (ti) {
                var rv = 1000, rti = ti, ticks = 1;

                if (ti !== this.tmInc.maxtime) {
                    if (ti > this.tmInc.tickf1) {
                        rv = ti;
                    } else {
                        ti += 7;
                        while (rti > 0) {
                            ticks *= 10;
                            rti--;
                        }
                        rv = ticks;
                    }
                }
                return rv;
            };

            ChartDataUtil.manualTimeInc = function (manualFormat) {
                var self = this, minSpan = self.tmInc.second;
                if (!manualFormat || manualFormat.length === 0) {
                    return minSpan;
                }

                // var f = manualFormat.indexOf("f");
                // if (f > 0) {
                // //TODO: when _getTimeDefaultFormat return millisecond
                // }
                // else if (manualFormat.indexOf("s") >= 0) {
                if (manualFormat.indexOf("s") >= 0) {
                    minSpan = self.tmInc.second;
                } else if (manualFormat.indexOf("m") >= 0) {
                    minSpan = self.tmInc.minute;
                } else if (manualFormat.indexOf("h") >= 0 || manualFormat.indexOf("H") >= 0) {
                    minSpan = self.tmInc.hour;
                } else if (manualFormat.indexOf("d") >= 0) {
                    minSpan = self.tmInc.day;
                } else if (manualFormat.indexOf("M") >= 0) {
                    minSpan = self.tmInc.month;
                } else if (manualFormat.indexOf("y") >= 0) {
                    minSpan = self.tmInc.year;
                }
                return minSpan;
            };

            ChartDataUtil.niceTickNumber = function (x) {
                if (parseFloat(x) === 0.0) {
                    return x;
                } else if (x < 0) {
                    x = -x;
                }
                var log10 = Math.log(x) / Math.log(10), exp = parseInt(this.signedFloor(log10).toString(), 10), f = x / Math.pow(10.0, exp), nf = 10.0;
                if (f <= 1.0) {
                    nf = 1.0;
                } else if (f <= 2.0) {
                    nf = 2.0;
                } else if (f <= 5.0) {
                    nf = 5.0;
                }
                return (nf * Math.pow(10.0, exp));
            };

            ChartDataUtil.niceNumber = function (x, exp, round) {
                if (parseFloat(x) === 0.0) {
                    return x;
                } else if (x < 0) {
                    x = -x;
                }

                var f = x / Math.pow(10.0, exp), nf = 10.0;

                if (round) {
                    if (f < 1.5) {
                        nf = 1.0;
                    } else if (f < 3.0) {
                        nf = 2.0;
                    } else if (f < 7.0) {
                        nf = 5.0;
                    }
                } else {
                    if (f <= 1.0) {
                        nf = 1.0;
                    } else if (f <= 2.0) {
                        nf = 2.0;
                    } else if (f <= 5.0) {
                        nf = 5.0;
                    }
                }

                return (nf * Math.pow(10.0, exp));
            };

            ChartDataUtil.nicePrecision = function (range) {
                if (range <= 0 || typeof (range) !== "number") {
                    return 0;
                }

                var log10 = Math.log(range) / Math.log(10), exp = parseInt(this.signedFloor(log10).toString(), 10), f = range / Math.pow(10.0, exp);

                if (f < 3.0) {
                    exp = -exp + 1;
                }

                return exp;
            };

            ChartDataUtil.precCeil = function (prec, value) {
                var f = Math.pow(10.0, prec), x = value / f;

                x = Math.ceil(x);

                return x * f;
            };

            ChartDataUtil.precFloor = function (prec, value) {
                var f = Math.pow(10.0, prec), x = value / f;

                x = Math.floor(x);

                return x * f;
            };

            ChartDataUtil.signedCeiling = function (val) {
                if (val < 0.0) {
                    return Math.floor(val);
                }

                return Math.ceil(val);
            };

            ChartDataUtil.signedFloor = function (val) {
                if (val < 0.0) {
                    return Math.ceil(val);
                }

                return Math.floor(val);
            };

            // f(x) = A * x**B => ln(f(x) = ln( A) + B * ln(x)
            ChartDataUtil.powerTransform = function (np, x, y, xt, yt) {
                var fy, factor = y[0] < 0 ? -1 : 1;

                for (var i = 0; i < np; i++) {
                    if (x[i] <= 0) {
                        throw "Incompatible data: x values should be positive.";
                    } else {
                        fy = factor * y[i];
                        if (fy <= 0) {
                            throw "Incompatible data: y values must all have the same sign.";
                        } else {
                            xt[i] = Math.log(x[i]);
                            yt[i] = Math.log(fy);
                        }
                    }
                }

                return factor;
            };

            // f(X) = A * exp(B*x) => ln(f(x)) = B*x + ln(A)
            ChartDataUtil.expoTransform = function (np, x, y, xt, yt) {
                var fy, factor = y[0] < 0 ? -1 : 1;

                for (var i = 0; i < np; i++)
                    xt[i] = x[i];

                for (var i = 0; i < np; i++) {
                    fy = factor * y[i];

                    if (fy <= 0) {
                        throw "Incompatible data: for expo fit all Y values must have the same sign";
                    } else {
                        yt[i] = Math.log(fy);
                    }
                }

                return factor;
            };

            // f(X) = A * Ln(B*x) => f(X) = A * Ln(X) + A * Ln(B)
            ChartDataUtil.logTransform = function (np, x, y, xt, yt) {
                var fx, factor = x[0] < 0 ? -1 : 1;

                for (var i = 0; i < np; i++)
                    yt[i] = y[i];

                for (var i = 0; i < np; i++) {
                    fx = factor * x[i];
                    if (fx <= 0) {
                        throw "Incompatible data: for log fit all Y values must have the same sign";
                    } else {
                        xt[i] = Math.log(fx);
                    }
                }

                return factor;
            };

            // f0 = 1, f1 = x, f2 = x**2 ...
            ChartDataUtil.polyCreateBasisFunctions = function (np, nt, x, basis, zero) {
                for (var row = 0; row < np; row++) {
                    if (zero) {
                        basis[row][0] = x[row]; // start from x, x*x ...
                        if (nt > 1)
                            basis[row][1] = x[row] * x[row];
                    } else {
                        basis[row][0] = 1;
                        basis[row][1] = x[row];
                    }
                    for (var col = 2; col < nt; col++)
                        basis[row][col] = x[row] * basis[row][col - 1];
                }
            };

            // f0 = 1, f1 = x
            ChartDataUtil.powerCreateBasisFunctions = function (np, x, basis) {
                for (var row = 0; row < np; row++) {
                    basis[row][0] = 1;
                    basis[row][1] = x[row];
                }
            };

            // f0 = 1, f1 = x
            ChartDataUtil.expoCreateBasisFunctions = function (np, x, basis) {
                for (var row = 0; row < np; row++) {
                    basis[row][0] = 1;
                    basis[row][1] = x[row];
                }
                ;
            };

            // f0 = x, f1 = 1
            ChartDataUtil.logCreateBasisFunctions = function (np, x, basis) {
                for (var row = 0; row < np; row++) {
                    basis[row][0] = x[row];
                    basis[row][1] = 1;
                }
            };

            // f0 = 1, f1 = cos(x), f2 = sin(x), f3 = cos(2x), f4 = sin(2x) ...
            ChartDataUtil.fourierCreateBasisFunctions = function (np, nt, x, basis) {
                for (var row = 0; row < np; row++) {
                    if (basis[row] === null || basis[row] === undefined) {
                        basis[row] = new Array();
                    }
                    basis[row][0] = 1;

                    if (nt > 1)
                        basis[row][1] = Math.cos(x[row]);

                    if (nt > 2)
                        basis[row][2] = Math.sin(x[row]);

                    for (var col = 3; col < nt; col++) {
                        var n = Math.ceil((col + 1) / 2);
                        if ((col % 2) == 1)
                            basis[row][col] = Math.cos(n * x[row]);
                        else
                            basis[row][col] = Math.sin(n * x[row]);
                    }
                }
            };

            ChartDataUtil.createBasis = function (np, x, y, nt, solution, basis, fit, zero) {
                if (np < 2)
                    throw "Incompatible data: Less than 2 data points.";
                if (nt < 1)
                    throw "Incompatible data: Less than 1 coefficient in the fit";
                if (nt > np)
                    throw "Incompatible data: Number of data points less than number of terms";

                for (var i = 0; i < nt; i++) {
                    solution[i] = 0;
                }

                switch (fit) {
                    case TrendlineFitType.strPolynom:
                        ChartDataUtil.polyCreateBasisFunctions(np, nt, x, basis, zero);
                        break;
                    case TrendlineFitType.strPower:
                        ChartDataUtil.powerCreateBasisFunctions(np, x, basis);
                        break;
                    case TrendlineFitType.strExponent:
                        ChartDataUtil.expoCreateBasisFunctions(np, x, basis);
                        break;
                    case TrendlineFitType.strLogarithmic:
                        ChartDataUtil.logCreateBasisFunctions(np, x, basis);
                        break;
                    case TrendlineFitType.strFourier:
                        ChartDataUtil.fourierCreateBasisFunctions(np, nt, x, basis);
                        break;
                }
            };

            // A[n][n]*x = A[n+1]
            ChartDataUtil.solveGauss = function (a, x, epsilon) {
                var n = a.length, i, j, k, m, t, result = true;

                if (x.length < n || a[0].length < n + 1)
                    throw "Dimension of matrix is not correct.";

                for (i = 0; i < n; i++) {
                    k = i;
                    m = Math.abs(a[i][i]);

                    for (j = i + 1; j < n; j++) {
                        if (m < Math.abs(a[j][i])) {
                            m = Math.abs(a[j][i]);
                            k = j;
                        }
                    }

                    if (Math.abs(m) > epsilon) {
                        for (j = i; j <= n; j++) {
                            t = a[i][j];
                            a[i][j] = a[k][j];
                            a[k][j] = t;
                        }

                        for (k = i + 1; k < n; k++) {
                            t = a[k][i] / a[i][i];

                            a[k][i] = 0;

                            for (j = i + 1; j <= n; j++)
                                a[k][j] -= t * a[i][j];
                        }
                    } else {
                        result = false;
                        break;
                    }
                }

                if (result) {
                    for (i = n - 1; i >= 0; i--) {
                        x[i] = a[i][n];

                        for (j = i + 1; j < n; j++)
                            x[i] -= a[i][j] * x[j];

                        x[i] = x[i] / a[i][i];
                    }
                }
                return result;
            };

            ChartDataUtil.normalizeAndSolveGauss = function (np, nt, basis, y, solution) {
                var a = new Array(nt);

                for (var i = 0; i < nt; i++) {
                    a[i] = ChartDataUtil.createArray(nt + 1, 0);
                }
                ChartDataUtil.computeNormalEquations(np, nt, basis, y, a);

                if (!ChartDataUtil.solveGauss(a, solution, 0))
                    throw "Incompatible data: No solution";
            };

            // transform the least square task to the normal equation
            //  a * solution = c
            // where
            //   a = basis_transposed * basis
            //   c = basis_transposed * y
            //
            // here right part
            //   a[i][nt] = c[i]
            //
            ChartDataUtil.computeNormalEquations = function (np, nt, basis, y, a) {
                var sum;

                for (var col = 0; col < nt; col++) {
                    sum = 0;
                    for (var i = 0; i < np; i++)
                        sum += y[i] * basis[i][col];

                    a[col][nt] = sum;

                    for (var row = col; row < nt; row++) {
                        sum = 0;

                        for (var i = 0; i < np; i++)
                            sum = sum + basis[i][row] * basis[i][col];

                        a[row][col] = sum;
                        a[col][row] = sum;
                    }
                }
            };

            ChartDataUtil.solveLeastSquares = function (np, x, y, nt, solution, fit, zero) {
                var factor = 0, xt, yt, basis = new Array(np);
                if (fit == TrendlineFitType.strExponent || fit == TrendlineFitType.strLogarithmic || fit == TrendlineFitType.strPower) {
                    nt = 2;
                    xt = ChartDataUtil.createArray(np, 0);
                    yt = ChartDataUtil.createArray(np, 0);
                    switch (fit) {
                        case TrendlineFitType.strPower:
                            factor = ChartDataUtil.powerTransform(np, x, y, xt, yt);
                            break;
                        case TrendlineFitType.strExponent:
                            factor = ChartDataUtil.expoTransform(np, x, y, xt, yt);
                            break;
                        case TrendlineFitType.strLogarithmic:
                            factor = ChartDataUtil.logTransform(np, x, y, xt, yt);
                            break;
                    }
                } else {
                    xt = x;
                    yt = y;
                }
                if (zero && fit == TrendlineFitType.strPolynom) {
                    factor = solution[0];
                    nt--; // decrease term number
                }
                for (var i = 0; i < np; i++) {
                    basis[i] = ChartDataUtil.createArray(nt, 0);
                }
                ChartDataUtil.createBasis(np, xt, yt, nt, solution, basis, fit, zero);
                ChartDataUtil.normalizeAndSolveGauss(np, nt, basis, yt, solution);
                switch (fit) {
                    case TrendlineFitType.strPower:
                        solution[0] = factor * Math.exp(solution[0]);
                        break;
                    case TrendlineFitType.strExponent:
                        solution[0] = factor * Math.exp(solution[0]);
                        break;
                    case TrendlineFitType.strLogarithmic:
                        solution[1] = factor * Math.exp(solution[1] / solution[0]);
                        break;
                    case TrendlineFitType.strPolynom:
                        if (zero) {
                            for (var i = solution.length - 1; i > 0; i--)
                                solution[i] = solution[i - 1];
                            solution[0] = factor;
                        }
                        break;
                }
            };

            ChartDataUtil.aproximate = function (fit, coeffs, xvalue) {
                var yvalue = 0;

                switch (fit) {
                    case TrendlineFitType.strPolynom:
                        var pow = 1;
                        for (var k = 0; k < coeffs.length; k++) {
                            if (k > 0) {
                                pow *= xvalue;
                            }
                            yvalue += coeffs[k] * pow;
                        }
                        break;

                    case TrendlineFitType.strPower:
                        yvalue = coeffs[0] * Math.pow(xvalue, coeffs[1]);
                        break;

                    case TrendlineFitType.strExponent:
                        yvalue = coeffs[0] * Math.exp(xvalue * coeffs[1]);
                        break;

                    case TrendlineFitType.strLogarithmic:
                        yvalue = coeffs[0] * Math.log(xvalue * coeffs[1]);
                        break;

                    case TrendlineFitType.strFourier:
                        yvalue = coeffs[0];
                        for (var k = 1; k < coeffs.length; k++) {
                            var k1 = Math.ceil((k + 1) / 2);
                            if ((k % 2) == 1) {
                                yvalue += coeffs[k] * Math.cos(k1 * xvalue);
                            } else {
                                yvalue += coeffs[k] * Math.sin(k1 * xvalue);
                            }
                        }
                        break;
                }
                return yvalue;
            };

            ChartDataUtil.processSimpleValues = function (valuesX, valuesY, fitType) {
                var len = valuesX.length, xmin = valuesX[0], xmax = xmin, ymin = valuesY[0], ymax = ymin, xavg = 0, yavg = 0, valsX = [], valsY = [];

                for (var i = 0; i < len; i++) {
                    if (xmin > valuesX[i]) {
                        xmin = valuesX[i];
                    }
                    if (xmax < valuesX[i]) {
                        xmax = valuesX[i];
                    }
                    if (ymin > valuesY[i]) {
                        ymin = valuesY[i];
                    }
                    if (ymax < valuesY[i]) {
                        ymax = valuesY[i];
                    }
                    xavg += valuesX[i];
                    yavg += valuesY[i];
                }
                xavg = xavg * 1.0 / len;
                yavg = yavg * 1.0 / len;
                switch (fitType) {
                    case TrendlineFitType.strMinX:
                        valsX = [].concat([xmin, xmin]);
                        valsY = [].concat([ymin, ymax]);
                        break;
                    case TrendlineFitType.strMaxX:
                        valsX = [].concat([xmax, xmax]);
                        valsY = [].concat([ymin, ymax]);
                        break;
                    case TrendlineFitType.strMinY:
                        valsX = [].concat([xmin, xmax]);
                        valsY = [].concat([ymin, ymin]);
                        break;
                    case TrendlineFitType.strMaxY:
                        valsX = [].concat([xmin, xmax]);
                        valsY = [].concat([ymax, ymax]);
                        break;
                    case TrendlineFitType.strAverageX:
                        valsX = [].concat([xavg, xavg]);
                        valsY = [].concat([ymin, ymax]);
                        break;
                    case TrendlineFitType.strAverageY:
                        valsX = [].concat([xmin, xmax]);
                        valsY = [].concat([yavg, yavg]);
                        break;
                }
                return { x: valsX, y: valsY };
            };

            ChartDataUtil.getNumberSeriesData = function (valuesX, valuesY, display, hole) {
                var valsX = ChartUtil.getNumberValues(valuesX), valsY = ChartUtil.getNumberValues(valuesY), x = [], y = [];

                $.each(valuesY, function (i, value) {
                    if (i === valsX.length) {
                        return false;
                    }
                    if (ChartUtil.isHolefunction(value, hole)) {
                        if (display === "excludeHole") {
                            return true;
                        }
                        if (!ChartUtil.isHolefunction(hole, undefined) && value === hole) {
                            if (valsX[i] === undefined) {
                                return false;
                            }
                            x.push(valsX[i]);
                            y.push(valsY[i]);
                        } else {
                            return true;
                        }
                    } else {
                        x.push(valsX[i]);
                        y.push(valsY[i]);
                    }
                });
                return { x: x, y: y };
            };

            ChartDataUtil.createArray = function (count, defaultValue) {
                var result = [];
                for (var i = 0; i < count; i++) {
                    result.push(defaultValue);
                }
                return result;
            };

            ChartDataUtil.processValues = function (valuesX, valuesY, fitType, xAutoMin, xAutoMax, xMin, xMax, order, npts, display, hole) {
                var xmin, xmax, len, delta, valsX = [], valsY = [], coeffs, nValues;

                if (order === null || order === undefined) {
                    order = 2;
                } else if (typeof order === "number") {
                    if (order < 1) {
                        return;
                    }
                } else {
                    return;
                }
                if (npts === null || npts === undefined) {
                    npts = 100;
                } else if (typeof npts === "number") {
                    if (npts < 1) {
                        return;
                    }
                } else {
                    return;
                }
                if (fitType === null || fitType === undefined) {
                    fitType = TrendlineFitType.strPolynom;
                }
                if (!TrendlineRender.validateType(fitType)) {
                    return;
                }
                nValues = ChartDataUtil.getNumberSeriesData(valuesX, valuesY, display, hole);

                if (!nValues.x.length || !nValues.y.length) {
                    return;
                }

                if (fitType == TrendlineFitType.strMinX || fitType == TrendlineFitType.strMaxX || fitType == TrendlineFitType.strMinY || fitType == TrendlineFitType.strMaxY || fitType == TrendlineFitType.strAverageX || fitType == TrendlineFitType.strAverageY) {
                    return ChartDataUtil.processSimpleValues(nValues.x, nValues.y, fitType);
                }

                len = nValues.x.length;
                for (var i = 0; i < len; i++) {
                    if (i == 0) {
                        xmin = nValues.x[i];
                        xmax = xmin;
                    } else {
                        if (xmin > nValues.x[i]) {
                            xmin = nValues.x[i];
                        }
                        if (xmax < nValues.x[i]) {
                            xmax = nValues.x[i];
                        }
                    }
                }
                order = Math.min(order, len);
                coeffs = ChartDataUtil.createArray(order, 0);
                ChartDataUtil.solveLeastSquares(len, nValues.x, nValues.y, order, coeffs, fitType, false);
                if (!xAutoMin && (xmin < xMin)) {
                    xmin = xMin;
                }
                if (!xAutoMax && (xmax > xMax)) {
                    xmax = xMax;
                }
                delta = (xmax - xmin) / (npts - 1);
                for (var i = 0; i < npts; i++) {
                    var xv = xmin + delta * i;
                    valsX.push(xv);
                    valsY.push(ChartDataUtil.aproximate(fitType, coeffs, xv));
                }
                return { x: valsX, y: valsY };
            };
            ChartDataUtil.tmInc = {
                tickf7: -7000,
                tickf6: -6000,
                tickf5: -5000,
                tickf4: -4000,
                tickf3: -3000,
                tickf2: -2000,
                tickf1: -1,
                second: 1000,
                minute: 60 * 1000,
                hour: 60 * 60 * 1000,
                day: 24 * 60 * 60 * 1000,
                week: 7 * 24 * 60 * 60 * 1000,
                month28: 28 * 24 * 60 * 60 * 1000,
                month29: 29 * 24 * 60 * 60 * 1000,
                month30: 30 * 24 * 60 * 60 * 1000,
                month: 31 * 24 * 60 * 60 * 1000,
                year: 365 * 24 * 60 * 60 * 1000,
                maxtime: 2147483647
            };
            return ChartDataUtil;
        })();
        chart.ChartDataUtil = ChartDataUtil;

        var TrendlineRender = (function () {
            function TrendlineRender(element, options) {
                var bounds, self = this;
                self.options = options;
                self.element = element;
                if (options && options.bounds) {
                    bounds = options.bounds;
                    self.width = bounds.endX - bounds.startX;
                    self.height = bounds.endY - bounds.startY;
                }
            }
            TrendlineRender.prototype.render = function () {
                var element = this.element, options = this.options, wijCSS = options.wijCSS, cBounds = options.bounds, widgetName = options.widgetName, canvas = options.canvas, ani = options.animation, seTrans = options.seriesTransition, mouseDown = options.mouseDown, mouseUp = options.mouseUp, mouseOver = options.mouseOver, mouseOut = options.mouseOut, mouseMove = options.mouseMove, click = options.click, linesStyle = [], paths = [], shadowPaths = [], disabled = options.disabled, animationSet = canvas.set(), fieldsAniPathAttr = options.aniPathsAttr, aniPathsAttr = [], chartEles, fields = element.data("fields") || {}, seriesEles = [], widget = options.widget, exVal = options.extremeValue;

                this.widget = widget;
                this.renderTrendLineChart(options, aniPathsAttr, fieldsAniPathAttr, paths, shadowPaths, animationSet, linesStyle, seriesEles);

                TrendlineRender.playAnimation(ani.enabled, ani.duration, ani.easing, seTrans, cBounds, paths, fieldsAniPathAttr, options.axis, exVal);
                fieldsAniPathAttr.length = 0;
                $.each(aniPathsAttr, function (idx, aniPathAttr) {
                    fieldsAniPathAttr.push(aniPathAttr);
                });

                TrendlineRender.unbindLiveEvents(element, widgetName, wijCSS);
                TrendlineRender.bindLiveEvents(element, widgetName, mouseDown, mouseUp, mouseOver, mouseOut, mouseMove, click, disabled, wijCSS, false);
                chartEles = {
                    trendLines: paths,
                    trendLineShadows: shadowPaths,
                    trendLineAnimationSet: animationSet
                };
                if (!fields.chartElements) {
                    fields.chartElements = {};
                }

                fields.seriesEles = seriesEles;

                $.extend(true, fields.chartElements, chartEles);
                element.data("fields", fields);
            };

            TrendlineRender.setClipRect = function (clipRect, path, cBounds) {
                var width = cBounds.endX - cBounds.startX - clipRect.left + clipRect.right, height = cBounds.endY - cBounds.startY - clipRect.top + clipRect.bottom;
                path.wijAttr("clip-rect", Raphael.format("{0} {1} {2} {3}", (cBounds.startX + clipRect.left), (cBounds.startY + clipRect.top), width, height));
            };

            TrendlineRender.playAnimation = function (animationEnable, duration, easing, seTrans, cBounds, paths, fieldsAniPathAttr, axis, exVal) {
                $.each(paths, function (idx, path) {
                    var axisIndex = path.data("yAxis"), yAxis = $.isArray(axis.y) ? axis.y[axisIndex] : axis.y, ty = exVal.y[axisIndex], currentClipRect = {
                        enable: false,
                        left: -10,
                        top: -10,
                        right: 10,
                        bottom: 10
                    }, width, height;

                    if (!yAxis || !ty) {
                        return true;
                    }

                    if (!axis.x.autoMax && axis.x.max < exVal.txx) {
                        currentClipRect.enable = true;
                        currentClipRect.right = 0;
                    }
                    if (!axis.x.autoMin && axis.x.min > exVal.txn) {
                        currentClipRect.enable = true;
                        currentClipRect.left = 0;
                    }
                    if (!yAxis.autoMax && yAxis.max < ty.tyx) {
                        currentClipRect.enable = true;
                        currentClipRect.top = 0;
                    }
                    if (!yAxis.autoMin && yAxis.min > ty.tyn) {
                        currentClipRect.enable = true;
                        currentClipRect.bottom = 0;
                    }

                    if (fieldsAniPathAttr && fieldsAniPathAttr.length && seTrans.enabled) {
                        duration = seTrans.duration;
                        easing = seTrans.easing;
                    }

                    if (path.tracker) {
                        path.tracker.hide();
                    }

                    width = cBounds.endX - cBounds.startX - currentClipRect.left + currentClipRect.right, height = cBounds.endY - cBounds.startY - currentClipRect.top + currentClipRect.bottom;
                    if (animationEnable || seTrans.enabled) {
                        path.wijAttr("clip-rect", Raphael.format("{0} {1} 0 {2}", (cBounds.startX + currentClipRect.left), (cBounds.startY + currentClipRect.top), height));

                        TrendlineRender.playPathAnimation(duration, easing, cBounds, path, currentClipRect, width, height);
                    } else {
                        TrendlineRender.setClipRect(currentClipRect, path, cBounds);
                    }
                });
            };

            TrendlineRender.playPathAnimation = function (duration, easing, cBounds, path, clipRect, width, height) {
                var clipRectEnable = clipRect.enable;

                path.wijAnimate({
                    "clip-rect": Raphael.format("{0} {1} {2} {3}", (cBounds.startX + clipRect.left), (cBounds.startY + clipRect.top), width, height)
                }, duration, easing, function () {
                    if (this.tracker && this.visible !== false) {
                        this.tracker.show();
                    }

                    if (Raphael.vml && !clipRectEnable) {
                        var attrs = null, clipRect = null, node = this.node;
                        if (node && node.clipRect) {
                            attrs = this.attrs;
                            delete attrs["clip-rect"];
                            node.clipRect = null;
                            clipRect = $(node).parent();
                            clipRect.before(node);
                            clipRect.remove();
                            this.attr(attrs);
                            if (attrs.src && attrs.src.length) {
                                this.attr({ "src": attrs.src });
                            }
                            if (attrs.gradient && attrs.gradient.length && attrs.fill === "none") {
                                this.attr({ "fill": attrs.gradient });
                            }
                        }
                    }
                });
            };

            TrendlineRender.validateType = function (fitType) {
                var valid = false;
                if (!fitType) {
                    return true;
                }
                $.each(TrendlineFitType, function (key, value) {
                    if (value === fitType) {
                        valid = true;
                        return false;
                    }
                });
                return valid;
            };

            TrendlineRender.renderSingleTrendLine = function (series, seriesStyle, seriesHoverStyle, axis, hole, fieldsAniPathAttr, animation, seriesTransition, index, cBounds, canvas, paths, shadowPaths, animationSet, aniPathsAttr, wijCSS, seriesEles, inverted, shadow) {
                var xAxis = axis.x, firstYPoint, lastYPoint, needAnimated = false, lineSeries, lineStyle, path, valuesX, valuesY, seriesData, pathArr = [], initAniPath = [];

                if (!series.isValid || !series.innerData) {
                    return;
                }
                lineSeries = $.extend(true, {
                    display: "show",
                    fitType: TrendlineFitType.strPolynom,
                    order: 2,
                    sampleCount: 100,
                    visible: true
                }, series);
                lineStyle = $.extend(true, {
                    stroke: "black",
                    opacity: 1,
                    fill: "none",
                    "stroke-linejoin": "round",
                    "stroke-linecap": "round"
                }, seriesStyle);

                if (hole !== undefined) {
                    valuesX = [].concat(lineSeries.data.x);
                    valuesY = [].concat(lineSeries.data.y);
                    try  {
                        seriesData = ChartDataUtil.processValues(valuesX, valuesY, lineSeries.fitType, xAxis.autoMin, xAxis.autoMax, xAxis.min, xAxis.max, lineSeries.order, lineSeries.sampleCount, lineSeries.display, hole);
                    } catch (e) {
                        //todo:  Incompatible data
                        return;
                    }
                    valuesX = seriesData.x;
                    valuesY = seriesData.y;
                } else {
                    valuesX = [].concat(series.innerData.x);
                    valuesY = [].concat(series.innerData.y);
                }

                if (fieldsAniPathAttr.length <= index || (animation.enabled && !seriesTransition.enabled)) {
                    needAnimated = true;
                }
                if (needAnimated) {
                    if (valuesY.length > 0) {
                        firstYPoint = ChartUtil.getFirstValidListValue(inverted ? valuesX : valuesY);
                        lastYPoint = ChartUtil.getLastValidListValue(inverted ? valuesX : valuesY);
                    }
                }

                $.each(valuesY, function (m, valY) {
                    pathArr = TrendlineRender.renderPoint(cBounds, initAniPath, pathArr, needAnimated, firstYPoint, lastYPoint, valuesX[m], valY, axis, m, inverted);
                });

                TrendlineRender.renderPath(canvas, cBounds, lineSeries, paths, shadowPaths, seriesHoverStyle, animationSet, pathArr, aniPathsAttr, initAniPath, lineStyle, index, wijCSS, axis, null, shadow);
                path = paths[paths.length - 1];
                seriesEles.push({
                    path: path,
                    shadowPath: shadowPaths[shadowPaths.length - 1],
                    isTrendline: true
                });
                if (path.tracker) {
                    path.tracker.toFront();
                }
                path.data("yAxis", series.yAxis ? series.yAxis : 0);
                return path;
            };

            TrendlineRender.prototype.renderTrendLineChart = function (options, aniPathsAttr, fieldsAniPathAttr, paths, shadowPaths, animationSet, linesStyle, seriesEles) {
                var wijCSS = options.wijCSS, cBounds = options.bounds, canvas = options.canvas, axis = options.axis, ani = options.animation, hole = options.hole, seTrans = options.seriesTransition, needAnimated = false, linesSeries = options.seriesList, linesSeriesStyles = options.seriesStyles, linesHoverStyles = options.seriesHoverStyles, self = this;

                self.annoPoints = {};
                $.each(linesSeries, function (k, trendlineSeries) {
                    var trendLine = TrendlineRender.renderSingleTrendLine(trendlineSeries, linesSeriesStyles[k], linesHoverStyles[k], axis, hole, fieldsAniPathAttr, ani, seTrans, k, cBounds, canvas, paths, shadowPaths, animationSet, aniPathsAttr, wijCSS, seriesEles), valuesX, valuesY;

                    if (!trendLine) {
                        return true;
                    }
                    valuesX = ChartUtil.getNumberValues(trendlineSeries.data.x);
                    valuesY = ChartUtil.getNumberValues(trendlineSeries.data.y);
                    if (self.annoPoints[k] == null) {
                        self.annoPoints[k] = {};
                    }
                    $.each(valuesX, function (pIndex, x) {
                        self.annoPoints[k][pIndex] = BaseChartRender.calculateDataPosition(x, valuesY[pIndex], self);
                    });
                });
            };

            TrendlineRender.renderPath = function (canvas, bounds, lineSeries, paths, shadowPaths, lineHoverStyle, animationSet, pathArr, aniPathsAttr, initAniPath, lineStyle, pathIdx, wijCSS, axis, inverted, shadow) {
                var path, startX, endX, tracker, trackerWidth, idx, noFillStyle, endY, yOrigin = axis.y.origin;

                endY = bounds.endY;
                if (axis && axis.y && (yOrigin !== null && yOrigin !== undefined && !isNaN(yOrigin))) {
                    endY = TrendlineRender.calculatePoint(yOrigin, "y", axis, bounds, inverted);
                }

                path = canvas.path(pathArr.join(" "));
                path.straight = initAniPath.join(" ");
                if (shadow !== false) {
                    ChartUtil.paintShadow(path, 1, "#cccccc");
                }
                if (pathIdx === 0) {
                    if (pathArr.length > 1) {
                        startX = pathArr[1];
                        endX = pathArr[pathArr.length - 2];
                    } else {
                        startX = bounds.startX;
                        endX = bounds.endX;
                    }
                }

                tracker = canvas.path(pathArr.join(" "));
                path.tracker = tracker;
                if (lineStyle["stroke-width"]) {
                    trackerWidth = 10 + parseFloat(lineStyle["stroke-width"]);
                } else {
                    trackerWidth = 10;
                }
                tracker.attr({
                    "stroke-width": trackerWidth,
                    stroke: "#C0C0C0",
                    opacity: 0.01
                });
                $.wijraphael.addClass($(tracker.node), Raphael.format("{0} {1} {2}", wijCSS.canvasObject, wijCSS.trendlineElement, wijCSS.trendlineTracker));
                $(tracker.node).data("owner", $(path.node));

                noFillStyle = $.extend(true, {}, lineStyle);
                if (noFillStyle.fill) {
                    delete noFillStyle.fill;
                }
                path.wijAttr(noFillStyle);

                if (lineHoverStyle.fill) {
                    delete lineHoverStyle.fill;
                }

                aniPathsAttr.push({
                    path: $.extend(true, {}, path.attr())
                });

                if (!paths) {
                    paths = [];
                }
                paths.push(path);
                if (path.shadow) {
                    shadowPaths[pathIdx] = path.shadow;
                }

                animationSet.push(path);

                if (!lineSeries.visible || lineSeries.display === "hide") {
                    path.hide();
                    if (path.tracker) {
                        path.tracker.hide();
                    }
                    if (path.shadow) {
                        path.shadow.hide();
                    }
                    path.visible = false;
                }
                lineSeries.index = pathIdx;
                lineSeries.type = ChartConsts.strTrendline;
                lineSeries.path = path;
                lineSeries.lineStyle = lineStyle;
                lineSeries.lineHoverStyle = lineHoverStyle;
                $.wijraphael.addClass($(path.node), Raphael.format("{0} {1}", wijCSS.canvasObject, wijCSS.trendlineElement));
                $(path.node).data("wijchartDataObj", lineSeries);
            };

            TrendlineRender.calculatePoint = function (val, dir, axis, bounds, inverted) {
                var min = axis[dir].min, max = axis[dir].max, len, rate, boundStart, boundEnd;

                if (inverted) {
                    if (dir === "x") {
                        dir = "y";
                    } else {
                        dir = "x";
                    }
                }
                if (dir === "x") {
                    rate = (bounds.endX - bounds.startX) / (max - min);
                    return bounds.startX + (val - min) * rate;
                } else {
                    rate = (bounds.endY - bounds.startY) / (max - min);
                    return bounds.endY - (val - min) * rate;
                }
            };

            TrendlineRender.renderPoint = function (cBounds, initAniPath, pathArr, needAnimated, firstYPoint, lastYPoint, valX, valY, axis, pointIdx, inverted) {
                var height = (inverted ? cBounds.endX : cBounds.endY) - (inverted ? cBounds.startX : cBounds.startY), minX = inverted ? axis.y.min : axis.x.min, minY = inverted ? axis.x.min : axis.y.min, maxX = inverted ? axis.y.max : axis.x.max, maxY = inverted ? axis.x.max : axis.y.max, ky = height / (maxY - minY), X = 0, Y, temp, initAniY;

                X = TrendlineRender.calculatePoint(valX, "x", axis, cBounds, inverted);
                Y = TrendlineRender.calculatePoint(valY, "y", axis, cBounds, inverted);
                if (inverted) {
                    temp = X;
                    X = Y;
                    Y = temp;
                }

                if (needAnimated) {
                    initAniY = firstYPoint + (lastYPoint - firstYPoint) / (maxX - minX) * ((inverted ? valY : valX) - minX);
                    initAniY = (inverted ? cBounds.endX : cBounds.endY) - (initAniY - minY) * ky;
                    initAniPath.push(pointIdx ? "L" : "M");
                    initAniPath.push(X);
                    initAniPath.push(initAniY);
                }
                pathArr = pathArr.concat([pointIdx ? "L" : "M", X, Y]);
                return pathArr;
            };

            TrendlineRender.bindLiveEvents = function (element, widgetName, mouseDown, mouseUp, mouseOver, mouseOut, mouseMove, click, disabled, wijCSS, hasProcessed) {
                var touchEventPre = "", proxyObj = {
                    element: element,
                    mousedown: function (e) {
                        if (disabled) {
                            return;
                        }

                        var tar = $(e.target), data, lineSeries = null;
                        if (tar.data("owner")) {
                            tar = tar.data("owner");
                        }
                        data = tar.data("wijchartDataObj");

                        mouseDown.call(element, e, data);
                    },
                    mouseup: function (e) {
                        if (disabled) {
                            return;
                        }

                        var tar = $(e.target), data, lineSeries = null;
                        if (tar.data("owner")) {
                            tar = tar.data("owner");
                        }
                        data = tar.data("wijchartDataObj");

                        mouseUp.call(element, e, data);
                    },
                    mouseover: function (e) {
                        if (disabled) {
                            return;
                        }

                        var tar = $(e.target), data, lineSeries = null, trendlinePath;
                        if (tar.data("owner")) {
                            tar = tar.data("owner");
                        }
                        data = tar.data("wijchartDataObj");
                        if (!hasProcessed && data && data.type === ChartConsts.strTrendline) {
                            trendlinePath = data.path;
                            if (trendlinePath && !trendlinePath.removed) {
                                if (data.lineHoverStyle) {
                                    trendlinePath.wijAttr(data.lineHoverStyle);
                                }
                            }
                        }
                        mouseOver.call(element, e, data);
                    },
                    mouseout: function (e) {
                        if (disabled) {
                            return;
                        }

                        var tar = $(e.target), data, lineSeries = null, trendlinePath;
                        if (tar.data("owner")) {
                            tar = tar.data("owner");
                        }
                        data = tar.data("wijchartDataObj");
                        if (!hasProcessed && data && data.type === ChartConsts.strTrendline) {
                            trendlinePath = data.path;
                            if (trendlinePath && !trendlinePath.removed) {
                                if (data.lineStyle) {
                                    if (data.lineStyle.fill) {
                                        delete data.lineStyle.fill;
                                    }
                                    trendlinePath.wijAttr(data.lineStyle);
                                }
                            }
                        }
                        mouseOut.call(element, e, data);
                    },
                    mousemove: function (e) {
                        if (disabled) {
                            return;
                        }

                        var tar = $(e.target), data, lineSeries = null;
                        if (tar.data("owner")) {
                            tar = tar.data("owner");
                        }
                        data = tar.data("wijchartDataObj");

                        mouseMove.call(element, e, data);
                    },
                    click: function (e) {
                        if (disabled) {
                            return;
                        }

                        var tar = $(e.target), data, lineSeries = null;
                        if (tar.data("owner")) {
                            tar = tar.data("owner");
                        }
                        data = tar.data("wijchartDataObj");

                        click.call(element, e, data);
                    }
                };

                if ($.support.isTouchEnabled && $.support.isTouchEnabled()) {
                    touchEventPre = "wij";
                }
                element.on(touchEventPre + "mousedown." + widgetName, "." + wijCSS.trendlineElement, $.proxy(proxyObj.mousedown, proxyObj)).on(touchEventPre + "mouseup." + widgetName, "." + wijCSS.trendlineElement, $.proxy(proxyObj.mouseup, proxyObj)).on(touchEventPre + "mouseover." + widgetName, "." + wijCSS.trendlineElement, $.proxy(proxyObj.mouseover, proxyObj)).on(touchEventPre + "mouseout." + widgetName, "." + wijCSS.trendlineElement, $.proxy(proxyObj.mouseout, proxyObj)).on(touchEventPre + "mousemove." + widgetName, "." + wijCSS.trendlineElement, $.proxy(proxyObj.mousemove, proxyObj)).on(touchEventPre + "click." + widgetName, "." + wijCSS.trendlineElement, $.proxy(proxyObj.click, proxyObj));
            };

            TrendlineRender.unbindLiveEvents = function (element, widgetName, wijCSS) {
                element.off("." + widgetName, "." + wijCSS.trendlineElement);
            };

            TrendlineRender.paintLegendIcon = function (x, y, width, height, style, canvas, legendSize, legendIcons, legendIndex, seriesIndex, legendCss) {
                var legendHeight, icon;

                icon = canvas.path(Raphael.format("M{0},{1}L{2},{3}", x, y + height / 2, x + width, y + height / 2));

                $(icon.node).data("legendIndex", legendIndex).data("index", seriesIndex);
                legendIcons.push(icon);
                if (style) {
                    if (legendSize && legendSize.height) {
                        legendHeight = legendSize.height;
                    }
                    icon.attr($.extend(true, {}, style, {
                        "stroke-width": legendHeight
                    }));
                }
                $.wijraphael.addClass($(icon.node), legendCss);
                return icon;
            };

            TrendlineRender.showSerieEles = function (eles) {
                if (eles.path) {
                    eles.path.show();
                    if (eles.path.shadow) {
                        eles.path.shadow.show();
                    }
                    if (eles.path.tracker) {
                        eles.path.tracker.show();
                    }
                }
            };

            TrendlineRender.hideSerieEles = function (eles) {
                if (eles.path) {
                    eles.path.hide();
                    if (eles.path.shadow) {
                        eles.path.shadow.hide();
                    }
                    if (eles.path.tracker) {
                        eles.path.tracker.hide();
                    }
                }
            };

            TrendlineRender.getSeriesChartType = function (series) {
                if (!series) {
                    return;
                }
                if (series.isTrendline) {
                    return ChartConsts.strTrendline;
                }
                return series.type;
            };
            return TrendlineRender;
        })();
        chart.TrendlineRender = TrendlineRender;

        Raphael.fn.closeBtn = function (x, y, length) {
            var offset = Math.cos(45 * Math.PI / 180) * length, set = this.set(), arrPath = [
                "M", x - offset, y - offset, "L", x + offset, y + offset,
                "M", x - offset, y + offset, "L", x + offset, y - offset], path = this.path(arrPath.join(" ")), rect = null;
            path.attr({ cursor: "pointer" });
            set.push(path);

            rect = this.rect(x - length, y - length, length * 2, length * 2);
            rect.attr({
                fill: "white",
                "fill-opacity": 0,
                cursor: "pointer",
                stroke: "none"
            });
            set.push(rect);
            return set;
        };

        //export enum ToolTipCompass {
        //	east,
        //	eastnorth,
        //	eastsouth,
        //	west,
        //	westnorth,
        //	westsouth,
        //	north,
        //	northeast,
        //	northwest,
        //	south,
        //	southeast,
        //	southwest
        //}
        var ChartTooltip = (function () {
            function ChartTooltip(paper, targets, options) {
                this.options = {
                    content: "",
                    contentStyle: {},
                    title: "",
                    titleStyle: {},
                    style: {
                        fill: "white",
                        "fill-opacity": 0.5
                    },
                    closeBehavior: "auto",
                    mouseTrailing: true,
                    triggers: "hover",
                    animated: "fade",
                    showAnimated: null,
                    hideAnimated: null,
                    duration: 500,
                    showDuration: 500,
                    hideDuration: 500,
                    easing: null,
                    showEasing: null,
                    hideEasing: null,
                    showDelay: 150,
                    hideDelay: 150,
                    relativeTo: "mouse",
                    compass: "east",
                    offsetX: 0,
                    offsetY: 0,
                    showCallout: true,
                    calloutFilled: false,
                    calloutFilledStyle: {
                        fill: "black"
                    },
                    calloutLength: 12,
                    calloutOffset: 0,
                    calloutAnimation: {
                        easing: null,
                        duration: 500
                    },
                    windowCollisionDetection: "flip",
                    calloutSide: null,
                    width: null,
                    height: null,
                    beforeShowing: null
                };
                this.paper = paper;
                this.targets = targets;
                $.extend(this.options, options);
                this.init();
            }
            ChartTooltip.prototype.init = function () {
                var o = this.options;

                // If the document mode of IE is less than 9, it doesn't support svg.
                // The chart will be rendered as vml.  But when raphael try to access the toHex funtion from cache to convert color to hex mode.
                // It will throw 'Permission denied' error and then return 'none'.
                // We provide a workaround to avoid this issue.
                // We convert the color to hex before Rapheal convert it, then set the converted color to the container of tooltip.
                if ($.browser.msie && document.documentMode <= 8) {
                    if (o.style.fill) {
                        this.fillColorForIE8 = ChartUtil.toHexColor(o.style.fill);
                    }
                    if (o.style.stroke) {
                        this.strokeColorForIE8 = ChartUtil.toHexColor(o.style.stroke);
                    }
                }
                this.calloutOffset = o.calloutOffset;
                this.offsetLength = 0;
                this.gapLength = o.calloutLength / 2;
                this.width = o.width;
                this.height = o.height;
                this.offset = { x: 0, y: 0 };
                this.toolTipShown = false;

                if (this.targets) {
                    this._bindLiveEvent(this.targets);
                }
                if (this.selector) {
                    this._bindLiveEventBySelector(this.selector);
                }

                this.isContentHtml = false;
                if ($(this.paper.canvas).wijtooltip) {
                    this.isContentHtml = o.isContentHtml;
                }

                this._initializeHTMLToolTips();
            };

            ChartTooltip.prototype._initializeHTMLToolTips = function () {
                var _this = this;
                if (!this.isContentHtml) {
                    return;
                }

                var o = this.options, showAnimated, showDuration, showEasing, hideAnimated, hideDuration, hideEasing, closeBehavior, positionMY, op;

                this.toolTipTarget = $(this.paper.canvas);
                positionMY = this._getHTMLTooltipPositionMY(o.compass), closeBehavior = o.closeBehavior === "sticky" ? "sticky" : "none";
                showAnimated = o.showAnimated || o.animated;
                showDuration = o.showDuration || o.duration;
                showEasing = o.showEasing || o.easing;
                hideAnimated = o.hideAnimated || o.animated;
                hideDuration = o.hideDuration || o.duration;
                hideEasing = o.hideEasing || o.easing;
                op = {
                    "triggers": "custom",
                    "closeBehavior": closeBehavior,
                    "showCallout": o.showCallout,
                    "position": {
                        "my": positionMY,
                        "at": "center center"
                    },
                    "animation": null,
                    "showDelay": o.showDelay,
                    "hideDelay": o.hideDelay,
                    "showAnimation": { animated: showAnimated, duration: showDuration, easing: showEasing },
                    "hideAnimation": { animated: hideAnimated, duration: hideDuration, easing: hideEasing },
                    "shown": function (e, ui) {
                        _this._setHTMLToolTipMovingDuration();
                        _this.toolTipShown = true;
                    },
                    "hidden": function (e, ui) {
                        _this._revoverHTMLToolTipShowingDuration();
                        _this.toolTipShown = false;
                    }
                };
                this.toolTipTarget.wijtooltip(op);
            };

            ChartTooltip.prototype._setHTMLToolTipMovingDuration = function () {
                if (!this.isContentHtml) {
                    return;
                }

                var o = this.options, ttTarget = this.toolTipTarget, showAnimation;

                // Set the duration value for tooltip moving.
                // Only set it one time when tooltip shows first time.
                if (!this.toolTipShown) {
                    showAnimation = ttTarget.wijtooltip("option", "showAnimation");
                    showAnimation = $.extend(showAnimation, { "duration": 250 });
                    ttTarget.wijtooltip("option", "showAnimation", showAnimation);
                }
                // End comments.
            };

            ChartTooltip.prototype._revoverHTMLToolTipShowingDuration = function () {
                if (!this.isContentHtml) {
                    return;
                }

                var o = this.options, ttTarget = this.toolTipTarget, showAnimation;

                // ** Recover the duration value for tooltip showing.
                if (this.toolTipShown) {
                    showAnimation = ttTarget.wijtooltip("option", "showAnimation");
                    showAnimation = $.extend(showAnimation, { "duration": o.showDuration || o.duration });
                    ttTarget.wijtooltip("option", "showAnimation", showAnimation);
                }
                // ** End comment
            };

            ChartTooltip.prototype._getHTMLTooltipPositionMY = function (compass) {
                var my = "center bottom";
                switch (compass) {
                    case "north":
                        my = "center bottom";
                        break;
                    case "south":
                        my = "center top";
                        break;
                    case "east":
                        my = "left center";
                        break;
                    case "west":
                        my = "right center";
                        break;
                    case "eastnorth":
                        my = "bottom left";
                        break;
                    case "northeast":
                        my = "left bottom";
                        break;
                    case "westnorth":
                        my = "bottom right";
                        break;
                    case "northwest":
                        my = "right bottom";
                        break;
                    case "eastsouth":
                        my = "top left";
                        break;
                    case "southeast":
                        my = "left top";
                        break;
                    case "westsouth":
                        my = "top right";
                        break;
                    case "southwest":
                        my = "right top";
                        break;
                }
                return my;
            };

            ChartTooltip.prototype._getShowPoint = function (raphaelObj, compass) {
                var box = raphaelObj.getBBox(), point = {
                    x: 0,
                    y: 0
                };
                switch (compass.toLowerCase()) {
                    case "east":
                        point.x = box.x + box.width;
                        point.y = box.y + box.height / 2;
                        break;
                    case "eastnorth":
                        point.x = box.x + box.width;
                        point.y = box.y;
                        break;
                    case "eastsouth":
                        point.x = box.x + box.width;
                        point.y = box.y + box.height;
                        break;
                    case "west":
                        point.x = box.x;
                        point.y = box.y + box.height / 2;
                        break;
                    case "westnorth":
                        point.x = box.x;
                        point.y = box.y;
                        break;
                    case "westsouth":
                        point.x = box.x;
                        point.y = box.y + box.height;
                        break;
                    case "north":
                        point.x = box.x + box.width / 2;
                        point.y = box.y;
                        break;
                    case "northeast":
                        point.x = box.x + box.width;
                        point.y = box.y;
                        break;
                    case "northwest":
                        point.x = box.x;
                        point.y = box.y;
                        break;
                    case "south":
                        point.x = box.x + box.width / 2;
                        point.y = box.y + box.height;
                        break;
                    case "southeast":
                        point.x = box.x + box.width;
                        point.y = box.y + box.height;
                        break;
                    case "southwest":
                        point.x = box.x;
                        point.y = box.y + box.height;
                        break;
                }
                return point;
            };

            ChartTooltip.prototype._clearIntentTimer = function (timer) {
                if (timer) {
                    window.clearTimeout(timer);
                    timer = null;
                }
            };

            ChartTooltip.prototype._removeSVGTooltip = function (duration) {
                var _this = this;
                var self = this, elements = this.elements, o = self.options, animated, d, op;
                if (elements) {
                    if (o.hideAnimated || o.animated) {
                        animated = o.hideAnimated;
                        if (!animated) {
                            animated = o.animated;
                        }
                        if (animated && ChartTooltip.animations[animated]) {
                            op = {
                                animated: animated,
                                duration: o.hideDuration || o.duration,
                                easing: o.hideEasing || o.easing,
                                context: elements,
                                show: false
                            };
                            ChartTooltip.animations[animated](op);
                        }
                    }
                    d = o.hideDuration || o.duration;
                    if (duration) {
                        d = duration;
                    }
                    window.setTimeout(function () {
                        var i, ii;
                        if (_this.content) {
                            _this.content.wijRemove();
                            _this.content = null;
                        }
                        if (_this.title) {
                            _this.title.wijRemove();
                            _this.title = null;
                        }
                        if (_this.container) {
                            _this.container.wijRemove();
                            _this.container = null;
                        }
                        if (_this.closeBtn) {
                            for (i = 0, ii = _this.closeBtn.length; i < ii; i++) {
                                _this.closeBtn[i].unclick();
                            }
                            _this.closeBtn.wijRemove();
                            _this.closeBtn = null;
                        }
                        if (_this.callout) {
                            _this.callout.wijRemove();
                            _this.callout = null;
                        }
                        self.lastPoint = null;
                        elements = null;
                    }, d);
                }
            };

            ChartTooltip.prototype._removeHTMLTooltip = function () {
                var o = this.options;
                if (o.closeBehavior !== "sticky") {
                    this.toolTipTarget.wijtooltip("hide");
                }
            };

            ChartTooltip.prototype._removeTooltip = function (duration) {
                if (this.isContentHtml) {
                    this._removeHTMLTooltip();
                } else {
                    this._removeSVGTooltip(duration);
                }
            };

            ChartTooltip.prototype._clearTimers = function () {
                if (this.intentShowTimer) {
                    this._clearIntentTimer(this.intentShowTimer);
                }
                if (this.intentHideTimer) {
                    this._clearIntentTimer(this.intentHideTimer);
                }
            };

            ChartTooltip.prototype._hide = function (e) {
                var self = this;
                self._clearTimers();
                if (self.options.hideDelay) {
                    self.intentHideTimer = window.setTimeout(function () {
                        self._removeTooltip();
                    }, self.options.hideDelay);
                } else {
                    self._removeTooltip();
                }
            };

            ChartTooltip.prototype._convertCompassToPosition = function (compass) {
                var position = "", offset = { x: 0, y: 0 };
                switch (compass.toLowerCase()) {
                    case "east":
                        position = "right-middle";
                        offset.x = 2;
                        offset.y = 0;
                        break;
                    case "eastnorth":
                        position = "right-top";
                        offset.x = 2;
                        offset.y = -2;
                        break;
                    case "eastsouth":
                        position = "right-bottom";
                        offset.x = 2;
                        offset.y = 2;
                        break;
                    case "west":
                        position = "left-middle";
                        offset.x = -2;
                        offset.y = 0;
                        break;
                    case "westnorth":
                        position = "left-top";
                        offset.x = -2;
                        offset.y = -2;
                        break;
                    case "westsouth":
                        position = "left-bottom";
                        offset.x = -2;
                        offset.y = 2;
                        break;
                    case "north":
                        position = "top-middle";
                        offset.x = 0;
                        offset.y = -2;
                        break;
                    case "northeast":
                        position = "top-right";
                        offset.x = 2;
                        offset.y = -2;
                        break;
                    case "northwest":
                        position = "top-left";
                        offset.x = -2;
                        offset.y = -2;
                        break;
                    case "south":
                        position = "bottom-middle";
                        offset.x = 0;
                        offset.y = 2;
                        break;
                    case "southeast":
                        position = "bottom-right";
                        offset.x = 2;
                        offset.y = 2;
                        break;
                    case "southwest":
                        position = "bottom-left";
                        offset.x = -2;
                        offset.y = 2;
                        break;
                }
                this.offset = offset;
                return position;
            };

            ChartTooltip.prototype._getCalloutArr = function (p, offset) {
                var arr = [], o = this.options, compass = o.compass;
                if (o.calloutSide) {
                    compass = o.calloutSide;
                }
                switch (compass.toLowerCase()) {
                    case "east":
                    case "eastsouth":
                    case "eastnorth":
                        arr = [
                            "M", p.x + offset, p.y + offset, "l",
                            -offset, -offset, "l", offset, -offset, "Z"];
                        break;
                    case "west":
                    case "westsouth":
                    case "westnorth":
                        arr = [
                            "M", p.x - offset, p.y - offset, "l",
                            offset, offset, "l", -offset, offset, "Z"];
                        break;
                    case "north":
                    case "northeast":
                    case "northwest":
                        arr = [
                            "M", p.x - offset, p.y - offset, "l",
                            offset, offset, "l", offset, -offset, "Z"];
                        break;
                    case "south":
                    case "southeast":
                    case "southwest":
                        arr = [
                            "M", p.x - offset, p.y + offset, "l",
                            offset, -offset, "l", offset, offset, "Z"];
                        break;
                }
                return arr;
            };

            ChartTooltip.prototype._getFuncText = function (text, e) {
                if ($.isFunction(text)) {
                    var fmt = null, objTar, obj = {
                        target: null,
                        fmt: text
                    }, t;
                    if (e && e.target) {
                        // obj.target = $(e.target).data("raphaelObj");
                        // objTar = $(e.target).data("raphaelObj");
                        // if (!objTar) {
                        // objTar = $(e.target.parentNode).data("raphaelObj");
                        // }
                        // obj.target = objTar;
                        t = e.target;
                        if (!t.raphael || !t.raphaelid) {
                            t = t.parentNode;
                        }
                        if (t.raphael && t.raphaelid) {
                            objTar = this.paper.getById(t.raphaelid);
                            obj.target = objTar;
                        } else {
                            obj.target = e.target;
                        }
                    }
                    fmt = $.proxy(obj.fmt, obj);
                    return fmt().toString();
                }
                return text;
            };

            ChartTooltip.prototype._translateCallout = function (duration) {
                var o = this.options, width = this.width, height = this.height, gapLength = this.gapLength, offsetLength = this.offsetLength, calloutOffset = this.calloutOffset, callout = this.tooltipElements.callout;
                if (o.calloutSide) {
                    var offset = gapLength || offsetLength;
                    switch (o.calloutSide) {
                        case "south":
                        case "north":
                            if (duration) {
                                callout.animate({
                                    "translation": (-width / 2 + offset + calloutOffset) + ",0"
                                }, duration);
                            } else {
                                callout.translate(-width / 2 + offset + calloutOffset, 0);
                            }
                            break;
                        case "east":
                        case "west":
                            if (duration) {
                                callout.animate({
                                    "translation": "0," + (-height / 2 + offset + calloutOffset)
                                }, duration);
                            } else {
                                callout.translate(0, -height / 2 + offset + calloutOffset);
                            }
                            break;
                    }
                }
            };

            ChartTooltip.replacer = function (all, key, obj) {
                var res = obj, objNotationRegex = /(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g;
                key.replace(objNotationRegex, function (all, name, quote, quotedName, isFunc) {
                    name = name || quotedName;
                    if (res) {
                        if (res[name] !== typeof ('undefined')) {
                            res = res[name];
                        }
                        if (typeof res === "function" && isFunc) {
                            res = res();
                        }
                    }
                });
                res = (res === null || res === obj ? all : res).toString();
                return res;
            };

            ChartTooltip.fill = function (str, obj) {
                var tokenRegex = /\{([^\}]+)\}/g;
                return String(str).replace(tokenRegex, function (all, key) {
                    return ChartTooltip.replacer(all, key, obj);
                });
            };

            ChartTooltip.prototype._createPath = function (point, position, set) {
                var pos = position.split("-"), r = 5, bb = set.getBBox(), o = this.options, p = o.padding, gapLength = this.gapLength, offsetLength = this.offsetLength, padding = p && !isNaN(p) ? parseInt(p) : 0, w = Math.round(bb.width + padding * 2), h = Math.round(bb.height + padding * 2), x = Math.round(bb.x - padding) - r, y = Math.round(bb.y - padding) - r, gap = 0, off = 0, dx = 0, dy = 0, shapes = null, mask = null, out = null;
                if (o.width) {
                    w = w > o.width ? w : o.width;
                }
                if (o.height) {
                    h = h > o.height ? h : o.height;
                }
                this.width = w;
                this.height = h;
                gap = Math.min(h / 4, w / 4, gapLength);
                if (offsetLength) {
                    offsetLength = Math.min(h / 4, w / 4, offsetLength);
                }
                if (offsetLength) {
                    off = offsetLength;
                    shapes = {
                        top: "M{x},{y}h{w4},{w4},{w4},{w4}a{r},{r},0,0,1,{r},{r}" + "v{h4},{h4},{h4},{h4}a{r},{r},0,0,1,-{r},{r}l-{right}," + "0-{offset},0,-{left},0a{r},{r},0,0,1-{r}-{r}" + "v-{h4}-{h4}-{h4}-{h4}a{r},{r},0,0,1,{r}-{r}z",
                        bottom: "M{x},{y}l{left},0,{offset},0,{right},0a{r},{r}," + "0,0,1,{r},{r}v{h4},{h4},{h4},{h4}a{r},{r},0,0,1,-{r}," + "{r}h-{w4}-{w4}-{w4}-{w4}a{r},{r},0,0,1-{r}-{r}" + "v-{h4}-{h4}-{h4}-{h4}a{r},{r},0,0,1,{r}-{r}z",
                        right: "M{x},{y}h{w4},{w4},{w4},{w4}a{r},{r},0,0,1,{r},{r}" + "v{h4},{h4},{h4},{h4}a{r},{r},0,0,1,-{r},{r}" + "h-{w4}-{w4}-{w4}-{w4}a{r},{r},0,0,1-{r}-{r}" + "l0-{bottom},0-{offset},0-{top}a{r},{r},0,0,1,{r}-{r}z",
                        left: "M{x},{y}h{w4},{w4},{w4},{w4}a{r},{r},0,0,1,{r},{r}" + "l0,{top},0,{offset},0,{bottom}a{r},{r},0,0,1,-{r}," + "{r}h-{w4}-{w4}-{w4}-{w4}a{r},{r},0,0,1-{r}-{r}" + "v-{h4}-{h4}-{h4}-{h4}a{r},{r},0,0,1,{r}-{r}z"
                    };
                } else {
                    shapes = {
                        top: "M{x},{y}h{w4},{w4},{w4},{w4}a{r},{r},0,0,1,{r},{r}" + "v{h4},{h4},{h4},{h4}a{r},{r},0,0,1,-{r},{r}" + "l-{right},0-{gap},{gap}-{gap}-{gap}-{left},0a{r},{r},0,0,1" + "-{r}-{r}v-{h4}-{h4}-{h4}-{h4}a{r},{r},0,0,1,{r}-{r}z",
                        bottom: "M{x},{y}l{left},0,{gap}-{gap},{gap},{gap},{right},0" + "a{r},{r},0,0,1,{r},{r}v{h4},{h4},{h4},{h4}a{r},{r},0,0,1," + "-{r},{r}h-{w4}-{w4}-{w4}-{w4}a{r},{r},0,0," + "1-{r}-{r}v-{h4}-{h4}-{h4}-{h4}a{r},{r},0,0,1,{r}-{r}z",
                        right: "M{x},{y}h{w4},{w4},{w4},{w4}a{r},{r},0,0,1,{r},{r}" + "v{h4},{h4},{h4},{h4}a{r},{r},0,0,1,-{r},{r}h-{w4}-{w4}" + "-{w4}-{w4}a{r},{r},0,0,1-{r}-{r}l0-{bottom}-{gap}-{gap}," + "{gap}-{gap},0-{top}a{r},{r},0,0,1,{r}-{r}z",
                        left: "M{x},{y}h{w4},{w4},{w4},{w4}a{r},{r},0,0,1,{r},{r}" + "l0,{top},{gap},{gap}-{gap},{gap},0,{bottom}a{r},{r},0,0,1," + "-{r},{r}h-{w4}-{w4}-{w4}-{w4}a{r},{r},0,0,1-{r}-{r}" + "v-{h4}-{h4}-{h4}-{h4}a{r},{r},0,0,1,{r}-{r}z"
                    };
                }
                mask = [
                    {
                        x: x + r,
                        y: y,
                        w: w,
                        w4: w / 4,
                        h4: h / 4,
                        left: 0,
                        right: w - gap * 2 - off * 2,
                        top: 0,
                        bottom: h - gap * 2 - off * 2,
                        r: r,
                        h: h,
                        gap: gap,
                        offset: off * 2
                    }, {
                        x: x + r,
                        y: y,
                        w: w,
                        w4: w / 4,
                        h4: h / 4,
                        left: w / 2 - gap - off,
                        right: w / 2 - gap - off,
                        top: h / 2 - gap - off,
                        bottom: h / 2 - gap - off,
                        r: r,
                        h: h,
                        gap: gap,
                        offset: off * 2
                    }, {
                        x: x + r,
                        y: y,
                        w: w,
                        w4: w / 4,
                        h4: h / 4,
                        right: 0,
                        left: w - gap * 2 - off * 2,
                        bottom: 0,
                        top: h - gap * 2 - off * 2,
                        r: r,
                        h: h,
                        gap: gap,
                        offset: off * 2
                    }][pos[1] === "middle" ? 1 : ((pos[1] === "left" || pos[1] === "top") ? 1 : 0) * 2];
                out = this.paper.path(ChartTooltip.fill(shapes[pos[0]], mask));
                switch (pos[0]) {
                    case "top":
                        dx = point.x - (x + r + mask.left + gap + offsetLength);
                        dy = point.y - (y + r + h + r + gap + offsetLength);
                        break;
                    case "bottom":
                        dx = point.x - (x + r + mask.left + gap + offsetLength);
                        dy = point.y - (y - gap - offsetLength);
                        break;
                    case "left":
                        dx = point.x - (x + r + w + r + gap + offsetLength);
                        dy = point.y - (y + r + mask.top + gap + offsetLength);
                        break;
                    case "right":
                        dx = point.x - (x - gap - off);
                        dy = point.y - (y + r + mask.top + gap + off);
                        break;
                }
                out.translate(dx, dy);

                //set.translate(dx, dy);
                set.transform(Raphael.format("...t{0},{1}", dx, dy));
                return out;
            };

            ChartTooltip.prototype._isWindowCollision = function (container, compass, offsetX, offsetY, ox, oy, windowCollisionDetection) {
                var box = container.getBBox(), counter = 0, cps = compass.toLowerCase(), x = box.x + ox, y = box.y + oy, w = this.paper.width, h = this.paper.height, offX = offsetX, offY = offsetY, strokeWidth = container.attr("stroke-width"), flip = windowCollisionDetection === true || windowCollisionDetection === "flip";
                if (Raphael.vml) {
                    w = $(this.paper.canvas).width();
                    h = $(this.paper.canvas).height();
                }
                if (x - strokeWidth < 0) {
                    // counter++;
                    if (flip) {
                        if (cps.toLowerCase().indexOf("west") === -1) {
                            // check if window collision after change compass.
                            if (x + box.width / 2 + box.width - offsetX <= w) {
                                counter++;
                                cps = cps.toLowerCase() + "east";
                                offX = 0 - offsetX;
                            }
                        } else {
                            if (x + box.width + box.width - offsetX <= w) {
                                counter++;
                                cps = cps.toLowerCase().replace("west", "east");
                                offX = 0 - offsetX;
                            }
                        }
                    } else {
                        //fit
                        counter++;
                        offX = 0 - x + strokeWidth + offsetX;
                    }
                }
                if (y - strokeWidth < 0) {
                    if (flip) {
                        // counter++;
                        if (cps.toLowerCase().indexOf("north") === -1) {
                            // check if window collision after change compass.
                            if (y + box.height / 2 + box.height - offsetY <= h) {
                                counter++;
                                cps = cps.toLowerCase() + "south";
                                offY = 0 - offsetY;
                            }
                        } else {
                            if (y + box.height + box.height - offsetY <= h) {
                                counter++;
                                cps = cps.toLowerCase().replace("north", "south");
                                offY = 0 - offsetY;
                            }
                        }
                    } else {
                        //fit
                        counter++;
                        offY = 0 - y + strokeWidth + offsetY;
                    }
                }
                if (x + box.width + strokeWidth > w) {
                    if (flip) {
                        // counter++;
                        if (cps.toLowerCase().indexOf("east") === -1) {
                            // check if window collision after change compass.
                            if (x - box.width / 2 - offsetX >= 0) {
                                counter++;
                                cps = cps.toLowerCase() + "west";
                                offX = 0 - offsetX;
                            }
                        } else {
                            if (x - box.width - offsetX >= 0) {
                                counter++;
                                cps = cps.toLowerCase().replace("east", "west");
                                offX = 0 - offsetX;
                            }
                        }
                    } else {
                        //fit
                        counter++;
                        offX = w - (x + box.width + strokeWidth) + offsetX;
                    }
                }
                if (y + box.height + strokeWidth > h) {
                    if (flip) {
                        // counter++;
                        if (cps.toLowerCase().indexOf("south") === -1) {
                            // check if window collision after change compass.
                            if (y - box.height / 2 - offsetY >= 0) {
                                counter++;
                                cps = cps.toLowerCase() + "north";
                                offY = 0 - offsetY;
                            }
                        } else {
                            if (y - box.height - offsetY >= 0) {
                                counter++;
                                cps = cps.toLowerCase().replace("south", "north");
                                offY = 0 - offsetY;
                            }
                        }
                    } else {
                        //fit
                        counter++;
                        offY = h - (y + box.height + strokeWidth) + offsetY;
                    }
                }
                if (counter) {
                    return {
                        compass: cps,
                        offsetX: offX,
                        offsetY: offY
                    };
                }
                return false;
            };

            ChartTooltip.prototype._createHTMLTooltipEles = function (point, tit, cont, windowCollisionDetection, compass, offsetX, offsetY) {
                var o = this.options, newPoint, pointOffset, ttTarget = this.toolTipTarget, targetOffset, ttContent, title, content, titleStyle = "", contentStyle = "", showAnimation;
                pointOffset = this._getPointOffset(compass);

                targetOffset = { x: 0, y: 0 };
                targetOffset.x = ttTarget.parent().offset().left;
                targetOffset.y = ttTarget.parent().offset().top;

                newPoint = {};
                newPoint.x = point.x + targetOffset.x + pointOffset.x + offsetX;
                newPoint.y = point.y + targetOffset.y + pointOffset.y + offsetY;

                ttContent = "";
                if (tit && tit.length > 0) {
                    title = tit.replace(/(?:\r\n|\n|\r)/g, '<br>');
                    if (o.titleStyle) {
                        titleStyle = "color:" + o.titleStyle["fill"] + ";font-size:" + o.titleStyle["font-size"];
                    }
                    ttContent += "<div style='" + titleStyle + "'>" + title + "</div>";
                }
                if (cont && cont.length > 0) {
                    content = cont.replace(/(?:\r\n|\n|\r)/g, '<br>');
                    if (o.contentStyle) {
                        contentStyle = "color:" + o.contentStyle["fill"] + ";font-size:" + o.contentStyle["font-size"] + ";font-family:" + o.contentStyle["font-family"];
                    }
                    ttContent += "<div style='" + contentStyle + "'>" + content + "</div>";
                }

                ttTarget.wijtooltip("option", "content", ttContent);

                ttTarget.wijtooltip("showAt", newPoint);
            };

            ChartTooltip.prototype._getPointOffset = function (compass) {
                var pointOffsetVal = 2, offset = { x: 0, y: 0 };
                switch (compass) {
                    case "north":
                        offset.x = 0;
                        offset.y = -pointOffsetVal;
                        break;
                    case "south":
                        offset.x = 0;
                        offset.y = pointOffsetVal;
                        break;
                    case "east":
                        offset.x = pointOffsetVal;
                        offset.y = 0;
                        break;
                    case "west":
                        offset.x = -pointOffsetVal;
                        offset.y = 0;
                    case "northeast":
                    case "eastnorth":
                        offset.x = pointOffsetVal;
                        offset.y = -pointOffsetVal;
                        break;
                    case "northwest":
                    case "westnorth":
                        offset.x = -pointOffsetVal;
                        offset.y = -pointOffsetVal;
                        break;
                    case "southeast":
                    case "eastsouth":
                        offset.x = pointOffsetVal;
                        offset.y = pointOffsetVal;
                        break;
                    case "southwest":
                    case "westsouth":
                        offset.x = -pointOffsetVal;
                        offset.y = pointOffsetVal;
                        break;
                }
                return offset;
            };

            ChartTooltip.prototype._createSVGTooltipEles = function (point, tit, cont, windowCollisionDetection, compass, offsetX, offsetY) {
                var _this = this;
                var titleBox, contentBox, position, set = this.paper.set(), arrPath = null, animated = null, o = this.options, closeBtnLength = this.closeBtnLength, calloutOffset = this.calloutOffset, op = null, ox = 0, oy = 0, duration = 250, idx = 0, len = 0, isWindowCollision, newPoint = {
                    x: point.x,
                    y: point.y
                }, offset = this.offset, anim = null, trans = null;

                $.wijraphael.clearRaphaelCache();
                position = this._convertCompassToPosition(compass);
                newPoint.x += offsetX + offset.x;
                newPoint.y += offsetY + offset.y;
                this.elements = this.paper.set();

                if (this.title) {
                    $.each(this.title, function (i, t) {
                        $(t.node).unbind(".Rtooltip");
                    });
                    this.title.wijRemove();
                }
                if (tit && tit.length > 0) {
                    this.title = this.paper.htmlText(-1000, -1000, tit, o.titleStyle);
                    this.elements.push(this.title);
                    titleBox = this.title.getBBox();
                } else {
                    titleBox = {
                        left: -1000,
                        top: -1000,
                        width: 0,
                        height: 0
                    };
                }
                if (this.content) {
                    $.each(this.content, function (i, c) {
                        $(c.node).unbind(".Rtooltip");
                    });
                    this.content.wijRemove();
                }
                if (cont && cont.length > 0) {
                    this.content = this.paper.htmlText(-1000, -1000, cont, o.contentStyle);
                    this.elements.push(this.content);
                    contentBox = this.content.getBBox();
                } else {
                    contentBox = {
                        left: -1000,
                        top: -1000,
                        width: 0,
                        height: 0
                    };
                }
                if (this.closeBtn) {
                    for (idx = 0, len = this.closeBtn.length; idx < len; idx++) {
                        this.closeBtn[idx].unclick();
                    }
                    this.closeBtn.wijRemove();
                }
                if (this.content) {
                    // content.translate(0, titleBox.height / 2 +
                    // contentBox.height / 2);
                    this.content.transform(Raphael.format("T0,{0}", titleBox.height / 2 + contentBox.height / 2));
                }
                if (this.title) {
                    // content.translate(0, titleBox.height / 2 +
                    // contentBox.height / 2);
                    this.title.transform(Raphael.format("T0,{0}", 0));
                }
                if (o.closeBehavior === "sticky") {
                    this.closeBtn = this.paper.closeBtn(-1000, -1000, closeBtnLength);
                    this.elements.push(this.closeBtn);
                    if (o.width && o.width > titleBox.width + closeBtnLength * 2 && o.width > contentBox.width + closeBtnLength * 2) {
                        // closeBtn.translate(o.width - closeBtnLength,
                        // closeBtnLength);
                        this.closeBtn.transform(Raphael.format("T{0},{1}", o.width - closeBtnLength, closeBtnLength));
                    } else if (titleBox.width >= contentBox.width - closeBtnLength * 2) {
                        // closeBtn.translate(titleBox.width +
                        // closeBtnLength, closeBtnLength);
                        this.closeBtn.transform(Raphael.format("T{0},{1}", titleBox.width + closeBtnLength, closeBtnLength));
                    } else {
                        // closeBtn.translate(contentBox.width -
                        // closeBtnLength, closeBtnLength);
                        this.closeBtn.transform(Raphael.format("T{0},{1}", contentBox.width - closeBtnLength, closeBtnLength));
                    }

                    // bind click event.
                    $.each(this.closeBtn, function (i, btn) {
                        var self = _this;
                        btn.click(function (e) {
                            self._hide(e);
                        });
                    });
                }
                if (this.title) {
                    set.push(this.title);
                    if (o.relatedElement) {
                        this.title.insertBefore(o.relatedElement);
                    }
                }
                if (this.content) {
                    set.push(this.content);
                    if (o.relatedElement) {
                        this.content.insertBefore(o.relatedElement);
                    }
                }
                if (this.closeBtn) {
                    set.push(this.closeBtn);
                    if (o.relatedElement) {
                        this.closeBtn.insertBefore(o.relatedElement);
                    }
                }
                if (!o.showCallout) {
                    this.gapLength = 0;
                }
                if (o.calloutSide || o.calloutFilled) {
                    this.gapLength = 0;
                    this.offsetLength = o.calloutLength / 2;
                    if (o.calloutSide) {
                        position = this._convertCompassToPosition(o.calloutSide);
                    }
                }
                if (o.calloutSide && set.length === 0) {
                    this.content = this.paper.htmlText(-1000, -1000, " ");
                    set.push(this.content);
                    if (o.relatedElement) {
                        this.content.insertBefore(o.relatedElement);
                    }
                }
                if (this.callout) {
                    $(this.callout.node).unbind(".Rtooltip");
                    this.callout.wijRemove();
                }
                if (this.container) {
                    $(this.container.node).unbind(".Rtooltip");
                    this.container.wijRemove();
                }

                // container = self.path();
                if (this.lastPoint) {
                    if (o.showCallout && (o.calloutSide || o.calloutFilled)) {
                        arrPath = this._getCalloutArr(this.lastPoint, this.offsetLength);

                        this.callout = this.paper.path(arrPath.concat(" "));
                        if (o.relatedElement) {
                            this.callout.insertBefore(o.relatedElement);
                        }
                        if (o.calloutFilled) {
                            this.callout.attr(o.calloutFilledStyle);
                        }
                        if (o.calloutSide) {
                            this._translateCallout(0);
                        }
                    }
                    this.container = this._createPath(this.lastPoint, position, set);
                    if (o.relatedElement) {
                        this.container.insertBefore(o.relatedElement);
                    }
                    if (windowCollisionDetection) {
                        isWindowCollision = this._isWindowCollision(this.container, compass, offsetX, offsetY, newPoint.x - this.lastPoint.x, newPoint.y - this.lastPoint.y, windowCollisionDetection);

                        // TODO: window collision
                        if (isWindowCollision) {
                            this._createTooltipEles(point, tit, cont, false, isWindowCollision.compass, isWindowCollision.offsetX, isWindowCollision.offsetY);
                            return;
                        }
                    }
                    this.elements.push(this.callout);
                    this.elements.push(this.container);
                    ox = newPoint.x - this.lastPoint.x;
                    oy = newPoint.y - this.lastPoint.y;
                    trans = Raphael.format("...T{0},{1}", ox, oy);
                    anim = Raphael.animation({ transform: trans }, duration);
                    if (this.container) {
                        // container.animate({ "translation": ox + "," + oy },
                        // duration);
                        if (o.showAnimated || o.animated) {
                            this.container.animate(anim);
                        } else {
                            this.container.attr("transform", trans);
                        }
                    }
                    if (this.title) {
                        // title.animate({ "translation": ox + "," + oy },
                        // duration);
                        if (o.showAnimated || o.animated) {
                            this.title.animate(anim);
                        } else {
                            this.title.attr("transform", trans);
                        }
                    }
                    if (this.content) {
                        // content.animate({ "translation": ox + "," + oy },
                        // duration);
                        if (o.showAnimated || o.animated) {
                            this.content.animate(anim);
                        } else {
                            this.content.attr("transform", trans);
                        }
                    }
                    if (this.closeBtn) {
                        // closeBtn.animate({ "translation": ox + "," + oy },
                        // duration);
                        if (o.showAnimated || o.animated) {
                            this.closeBtn.animate(anim);
                        } else {
                            this.closeBtn.attr("transform", trans);
                        }
                    }
                    if (this.callout) {
                        // callout.animate({ "translation": ox + "," + oy },
                        // duration);
                        if (o.showAnimated || o.animated) {
                            this.callout.animate(anim);
                        } else {
                            this.callout.attr("transform", trans);
                        }
                    }
                } else {
                    if (o.showCallout && (o.calloutSide || o.calloutFilled)) {
                        arrPath = this._getCalloutArr(newPoint, this.offsetLength);
                        this.callout = this.paper.path(arrPath.concat(" "));
                        if (o.relatedElement) {
                            this.callout.insertBefore(o.relatedElement);
                        }
                        if (o.calloutFilled) {
                            this.callout.attr(o.calloutFilledStyle);
                        }
                        if (o.calloutSide) {
                            this._translateCallout(0);
                        }
                    }
                    this.container = this._createPath(newPoint, position, set);
                    if (o.relatedElement) {
                        this.container.insertBefore(o.relatedElement);
                    }
                    if (windowCollisionDetection) {
                        isWindowCollision = this._isWindowCollision(this.container, compass, offsetX, offsetY, 0, 0, windowCollisionDetection);

                        // TODO: window collision
                        if (isWindowCollision) {
                            this._createTooltipEles(point, tit, cont, false, isWindowCollision.compass, isWindowCollision.offsetX, isWindowCollision.offsetY);
                            return;
                        }
                    }
                    this.elements.push(this.callout);
                    this.elements.push(this.container);
                    if (o.showAnimated || o.animated) {
                        animated = o.showAnimated;
                        if (!animated) {
                            animated = o.animated;
                        }
                        if (animated && ChartTooltip.animations[animated]) {
                            op = {
                                animated: animated,
                                duration: o.showDuration || o.duration,
                                easing: o.showEasing || o.easing,
                                context: this.elements,
                                show: true
                            };
                            ChartTooltip.animations[animated](op);
                        }
                    }
                }
                this.lastPoint = newPoint;

                // If the document mode of IE is less than 9, it doesn't support svg.
                // The chart will be rendered as vml.  But when raphael try to access the toHex funtion from cache to convert color to hex mode.
                // It will throw 'Permission denied' error and then return 'none'.
                // We provide a workaround to avoid this issue.
                // We convert the color to hex before Rapheal convert it, then set the converted color to the container of tooltip.
                if ($.browser.msie && document.documentMode <= 8) {
                    this.container.attr($.extend({}, o.style, {
                        fill: this.fillColorForIE8,
                        stroke: this.strokeColorForIE8
                    }));
                } else {
                    this.container.attr(o.style);
                }

                // container.toFront();
                if (o.relatedElement) {
                    if (this.title) {
                        this.title.insertBefore(o.relatedElement);
                    }
                    if (this.content) {
                        this.content.insertBefore(o.relatedElement);
                    }
                    if (this.closeBtn) {
                        this.closeBtn.insertBefore(o.relatedElement);
                    }
                } else {
                    set.toFront();
                }
                // set.toFront();
                /*
                * if (o.closeBehavior === "auto") {
                * $(container.node).bind("mouseover.Rtooltip", function (e) {
                * _clearTimers(); }).bind("mouseout.Rtooltip", function (e) {
                * _hide(e); }); if (title) { $.each(title, function (i, t) {
                * $(t.node).bind("mouseover.Rtooltip", function (e) {
                * _clearTimers(); }).bind("mouseout.Rtooltip", function (e) {
                * _hide(e); }); }); } if (content) { $.each(content, function
                * (i, c) { $(c.node).bind("mouseover.Rtooltip", function (e) {
                * _clearTimers(); }).bind("mouseout.Rtooltip", function (e) {
                * _hide(e); }); }); } if (callout) {
                * $(callout.node).bind("mouseover.Rtooltip", function (e) {
                * _clearTimers(); }).bind("mouseout.Rtooltip", function (e) {
                * _hide(e); }); } }
                */
            };

            ChartTooltip.prototype._createTooltipEles = function (point, tit, cont, windowCollisionDetection, compass, offsetX, offsetY) {
                if (this.isContentHtml) {
                    this._createHTMLTooltipEles(point, tit, cont, windowCollisionDetection, compass, offsetX, offsetY);
                } else {
                    this._createSVGTooltipEles(point, tit, cont, windowCollisionDetection, compass, offsetX, offsetY);
                }
            };

            ChartTooltip.prototype._createTooltip = function (point, e) {
                var tit = null, cont = null, fmt = null, obj = null, o = this.options, objTar, t;
                if ($.isFunction(o.beforeShowing)) {
                    fmt = null;
                    obj = {
                        target: null,
                        options: o,
                        fmt: o.beforeShowing
                    };
                    if (e && e.target) {
                        // objTar = $(e.target).data("raphaelObj");
                        // if (!objTar) {
                        // objTar = $(e.target.parentNode).data("raphaelObj");
                        // }
                        // obj.target = objTar;
                        t = e.target;
                        if (!t.raphael || !t.raphaelid) {
                            t = t.parentNode;
                        }
                        if (t.raphael && t.raphaelid) {
                            objTar = this.paper.getById(t.raphaelid);
                            obj.target = objTar;
                        } else {
                            objTar = e.target;
                            obj.target = objTar;
                        }
                    }
                    fmt = $.proxy(obj.fmt, obj);
                    if (fmt() === false) {
                        return;
                    }
                    ;
                }
                tit = o.title;
                cont = o.content;
                tit = this._getFuncText(tit, e);
                cont = this._getFuncText(cont, e);
                if (!tit && !cont) {
                    return;
                }

                this._createTooltipEles(point, tit, cont, o.windowCollisionDetection, o.compass, o.offsetX, o.offsetY);
            };

            ChartTooltip.prototype._showAt = function (point, e) {
                var o = this.options, self = this;

                this._clearTimers();
                if (o.showDelay) {
                    this.intentShowTimer = window.setTimeout(function () {
                        self._createTooltip(point, e);
                    }, o.showDelay);
                } else {
                    this._createTooltip(point, e);
                }
            };

            ChartTooltip.prototype._show = function (e) {
                var position = $(this.paper.canvas.parentNode).offset(), offsetX = position.left, offsetY = position.top, o = this.options, relativeTo = o.relativeTo, point = {
                    x: 0,
                    y: 0
                }, raphaelObj = null, t = e.target;
                switch (relativeTo) {
                    case "mouse":
                        point.x = e.pageX - offsetX;
                        point.y = e.pageY - offsetY;
                        break;
                    case "element":
                        if (!t.raphael || !t.raphaelid) {
                            t = t.parentNode;
                        }
                        if (t.raphael && t.raphaelid) {
                            raphaelObj = this.paper.getById(t.raphaelid);
                            point = this._getShowPoint(raphaelObj, o.compass);
                        }
                        break;
                }
                this._showAt(point, e);
            };

            ChartTooltip.prototype._bindEvent = function (tar) {
                var o = this.options, self = this;
                switch (o.triggers) {
                    case "hover":
                        $(tar.node).bind("mouseover.Rtooltip", function (e) {
                            self._show(e);
                        }).bind("mouseout.Rtooltip", function (e) {
                            if (o.closeBehavior === "auto") {
                                self._hide(e);
                            }
                        });
                        if (o.mouseTrailing && o.relativeTo === "mouse") {
                            $(tar.node).bind("mousemove.Rtooltip", function (e) {
                                self._show(e);
                            });
                        }
                        break;
                    case "click":
                        $(tar.node).bind("click.Rtooltip", function (e) {
                            self._show(e);
                        });
                        break;
                    case "custom":
                        break;
                }
            };

            ChartTooltip.prototype._bindLiveEvent = function (tars) {
                var i, ii;
                if (tars) {
                    if (tars.length) {
                        for (i = 0, ii = tars.length; i < ii; i++) {
                            this._bindEvent(tars[i]);
                        }
                    } else {
                        this._bindEvent(tars);
                    }
                }
            };

            ChartTooltip.prototype._bindLiveEventBySelector = function (selector) {
                var o = this.options, self = this;
                if (selector) {
                    switch (o.triggers) {
                        case "hover":
                            selector.on("mouseover.Rtooltip", function (e) {
                                self._show(e);
                            }).on("mouseout.Rtooltip", function (e) {
                                if (o.closeBehavior === "auto") {
                                    self._hide(e);
                                }
                            });
                            if (o.mouseTrailing && o.relativeTo === "mouse") {
                                selector.on("mousemove.Rtooltip", function (e) {
                                    self._show(e);
                                });
                            }
                            break;
                        case "click":
                            selector.on("click.Rtooltip", function (e) {
                                self._show(e);
                            });
                            break;
                        case "custom":
                            break;
                    }
                }
            };

            ChartTooltip.prototype._unbindLiveEvent = function (targets, selector) {
                var i, ii;
                if (targets) {
                    if (targets.length) {
                        for (i = 0, ii = targets.length; i < ii; i++) {
                            $(targets[i].node).unbind(".Rtooltip");
                        }
                    } else {
                        $(targets.node).unbind(".Rtooltip");
                    }
                }
                if (selector) {
                    selector.off("Rtooltip").off(".Rtooltip");
                }
            };

            ChartTooltip.prototype._destroy = function () {
                this._unbindLiveEvent(this.targets, this.selector);
                this._removeTooltip(0);
                if (this.isContentHtml) {
                    $(this.paper.canvas).wijtooltip("destroy");
                }
            };

            ChartTooltip.prototype.hide = function (hideImmediately) {
                if (typeof hideImmediately === "undefined") { hideImmediately = false; }
                var self = this, o = self.options, hideDelay = o.hideDelay, hideDuration = o.hideDuration;
                if (hideImmediately) {
                    o.hideDelay = 0;
                    o.hideDuration = 0;
                    self._hide();
                    o.hideDelay = hideDelay;
                    o.hideDuration = hideDuration;
                } else {
                    self._hide();
                }
            };

            ChartTooltip.prototype.showAt = function (point, e) {
                this._showAt(point, e);
            };

            ChartTooltip.prototype.resetCalloutOffset = function (offset) {
                var o = this.options, currentOffset = o.calloutOffset, side = o.calloutSide, ani = o.calloutAnimation, tooltipElements = this.tooltipElements;
                if (tooltipElements.callout) {
                    if (side === "south" || side === "north") {
                        tooltipElements.callout.animate({
                            "translation": (offset - currentOffset) + ",0"
                        }, ani.duration, ani.easing);
                    } else if (side === "east" || side === "west") {
                        tooltipElements.callout.animate({
                            "translation": "0," + (offset - currentOffset)
                        }, ani.duration, ani.easing);
                    }
                }
                o.calloutOffset = offset;
            };

            ChartTooltip.prototype.destroy = function () {
                this._destroy();
            };

            ChartTooltip.prototype.getOptions = function () {
                return this.options;
            };

            ChartTooltip.prototype.setTargets = function (targets) {
                this.targets = targets;
                this._bindLiveEvent(targets);
            };

            ChartTooltip.prototype.setSelector = function (selector) {
                this.selector = selector;
                this._bindLiveEventBySelector(selector);
            };

            ChartTooltip.prototype.setOptions = function (opts) {
                $.extend(true, this.options, opts);
            };

            ChartTooltip.animations = {
                fade: function (options) {
                    var eles = options.context;
                    if (options.show) {
                        eles.attr({ "opacity": 0 });
                        eles.wijAnimate({ "opacity": 1 }, options.duration, options.easing);
                    } else {
                        eles.wijAnimate({ "opacity": 0 }, options.duration, options.easing);
                    }
                }
            };
            return ChartTooltip;
        })();
        chart.ChartTooltip = ChartTooltip;

        //for original API
        Raphael.fn.tooltip = { animations: ChartTooltip.animations };

        /** @ignore */
        var AdjustLabel = (function () {
            function AdjustLabel(bBox) {
                this.labels = [];
                this.crossLabels = {};
                this.bBox = bBox;
            }
            AdjustLabel.prototype.push = function (label) {
                var bBox = label.wijGetBBox();
                this.labels.push({
                    ele: label,
                    x: bBox.x,
                    y: bBox.y,
                    width: bBox.width,
                    height: bBox.height,
                    overlaps: [],
                    bakBBox: bBox
                });
            };

            AdjustLabel.prototype.pushCross = function (idx1, idx2) {
                var label1, label2, dx, dy, tmp;
                if (!this.crossLabels[Raphael.format("{0}-{1}", idx1, idx2)] && !this.crossLabels[Raphael.format("{0}-{1}", idx2, idx1)]) {
                    label1 = this.labels[idx1];
                    label2 = this.labels[idx2];
                    this.crossLabels[Raphael.format("{0}-{1}", idx1, idx2)] = {
                        label1: label1,
                        label2: label2,
                        dx: this._getAdjust(label1, label2, "h"),
                        dy: this._getAdjust(label1, label2, "v")
                    };
                }
            };

            AdjustLabel.prototype._detect = function (label1, label2) {
                return ((label1.x + label1.width > label2.x && label1.x < label2.x) || (label2.x + label2.width > label1.x && label2.x < label1.x)) && ((label1.y + label1.height > label2.y && label1.y < label2.y) || (label2.y + label2.height > label1.y && label2.y < label1.y));
            };

            AdjustLabel.prototype._resetOverlaps = function () {
                this.crossLabels = {};
            };

            AdjustLabel.prototype._detects = function () {
                var len = this.labels.length, label1, label2;
                for (var i = 0; i < len; i++) {
                    for (var j = i + 1; j < len; j++) {
                        label1 = this.labels[i];
                        label2 = this.labels[j];
                        if (this._detect(label1, label2)) {
                            this.pushCross(i, j);
                        }
                    }
                }
            };

            AdjustLabel.prototype._getAdjust = function (label1, label2, dir) {
                var obj = { dx: 0, needRevert: false };
                if (dir === "h") {
                    if (label1.x < label2.x) {
                        obj.dx = label1.x + label1.width - label2.x;
                    } else {
                        obj.dx = label2.x + label2.width - label1.x;
                        obj.needRevert = true;
                    }
                } else {
                    if (label1.y < label2.y) {
                        obj.dx = label1.y + label1.height - label2.y;
                    } else {
                        obj.dx = label2.y + label2.height - label1.y;
                        obj.needRevert = true;
                    }
                }
                return obj;
            };

            AdjustLabel.prototype._adjustlabel = function (label1, label2, dx, dir) {
                if (dir === "h") {
                    label1.x -= dx / 2;
                    label2.x += dx / 2;

                    if (this.bBox) {
                        if (label1.x < this.bBox.x) {
                            label1.x = this.bBox.x;
                            label2.x = label2.x + (this.bBox.x - label1.x);
                        } else if (label2.x > this.bBox.x + this.bBox.width) {
                            label2.x = this.bBox.x + this.bBox.width;
                            label1.x -= label2.x - this.bBox.x + this.bBox.width;
                        }
                    }
                } else {
                    label1.y -= dx / 2;
                    label2.y += dx / 2;
                    if (this.bBox) {
                        if (label1.y < this.bBox.y) {
                            label1.y = this.bBox.y;
                            label2.y = label2.y + (this.bBox.y - label1.y);
                        } else if (label2.y > this.bBox.y + this.bBox.height) {
                            label2.y = this.bBox.y + this.bBox.height;
                            label1.y -= label2.y - this.bBox.y + this.bBox.height;
                        }
                    }
                }
            };

            AdjustLabel.prototype._adjustInternal = function () {
                var _this = this;
                $.each(this.crossLabels, function (i, labelObj) {
                    var label1 = labelObj.label1, label2 = labelObj.label2, dx = labelObj.dx, dy = labelObj.dy;

                    if (dx.dx < dy.dx) {
                        if (dy.needRevert) {
                            _this._adjustlabel(label2, label1, dy.dx, "v");
                        } else {
                            _this._adjustlabel(label1, label2, dy.dx, "v");
                        }
                    } else {
                        if (dx.needRevert) {
                            _this._adjustlabel(label2, label1, dx.dx, "h");
                        } else {
                            _this._adjustlabel(label1, label2, dx.dx, "h");
                        }
                    }
                });
            };

            AdjustLabel.prototype._adjustTheEdge = function () {
                var _this = this;
                if (this.bBox) {
                    $.each(this.labels, function (i, label) {
                        if (label.x < _this.bBox.x) {
                            label.x = _this.bBox.x;
                        } else if (label.x + label.width > _this.bBox.x + _this.bBox.width) {
                            label.x = _this.bBox.x + _this.bBox.width - label.width;
                        }

                        if (label.y < _this.bBox.y) {
                            label.y = _this.bBox.y;
                        } else if (label.y + label.height > _this.bBox.y + _this.bBox.height) {
                            label.y = _this.bBox.y + _this.bBox.height - label.height;
                        }
                    });
                }
            };

            AdjustLabel.prototype._translateLabels = function () {
                $.each(this.labels, function (i, label) {
                    if (label.x !== label.bakBBox.x) {
                        label.ele.attr("x", label.x + label.width / 2);
                        label.bakBBox.x = label.x;
                    }

                    if (label.y !== label.bakBBox.y) {
                        label.ele.attr("y", label.y + label.height / 2);
                        label.bakBBox.y = label.y;
                    }
                });
            };

            AdjustLabel.prototype.adjust = function () {
                var maxCalculate = 1000;
                while (maxCalculate > 0) {
                    this._resetOverlaps();
                    this._adjustTheEdge();
                    this._detects();
                    if ($.isEmptyObject(this.crossLabels)) {
                        break;
                    }
                    maxCalculate--;
                    this._adjustInternal();
                }
                this._translateLabels();
            };
            return AdjustLabel;
        })();
        chart.AdjustLabel = AdjustLabel;

        /** @widget */
        var wijchartcore = (function (_super) {
            __extends(wijchartcore, _super);
            function wijchartcore() {
                _super.apply(this, arguments);
                this.innerState = {};
            }
            wijchartcore.prototype._setOption = function (key, value) {
                var self = this, o = self.options, ev = null, len = 0, idx = 0, oldXMajorFactor = o.axis.x.tickMajor.factor, oldXMinorFactor = o.axis.x.tickMinor.factor, oldYMajorFactor, oldYMinorFactor, bakYAxis, newYAxis, hoverStyleLen, baseAxis = wijchartcore.prototype.options.axis, oldYAxis, axisVal;

                /*
                if (key === "dataSource" || key === "data") {
                self.seriesTransition = true;
                o.dataSource = value;
                //restore the binded data
                if (self.seriesList) {
                o.seriesList = $.arrayClone(self.seriesList);
                }
                self._init();
                }
                */
                if (key === "dataSource") {
                    self.seriesTransition = true;
                    o.dataSource = value;

                    //restore the binded data
                    if (self.seriesList) {
                        o.seriesList = $.arrayClone(self.seriesList);
                    }
                    self._init();
                } else if (key === "data") {
                    self.seriesTransition = true;
                    o.data = value;

                    //restore the binded data
                    if (self.seriesList) {
                        o.seriesList = $.arrayClone(self.seriesList);
                    }
                    self._init();
                } else if (key === "seriesList") {
                    if (!value) {
                        value = [];
                    }

                    ev = $.Event("beforeserieschange");
                    if (self._trigger("beforeSeriesChange", ev, {
                        oldSeriesList: o.seriesList,
                        newSeriesList: value
                    }) === false) {
                        return false;
                    }
                    o.seriesList = value;
                    self.seriesList = $.arrayClone(value);
                    self._trigger("seriesChanged", null, value);
                    self.seriesTransition = true;
                    self._seriesListSeted();
                    self._init();
                } else {
                    if ($.isPlainObject(o[key])) {
                        if (key === "axis") {
                            if ($.isArray(o.axis.y)) {
                                bakYAxis = $.arrayClone([].concat(o.axis.y));
                            } else {
                                bakYAxis = $.extend(true, {}, o.axis.y);
                            }
                        }

                        //extend the axis from base chartcore.
                        if (key === "axis") {
                            //extend axis value first to prevent modify original data.
                            axisVal = $.extend(true, {}, value);

                            //if (!$.isArray(axisVal.y))
                            //    axisVal.y = [axisVal.y]; // make 'y' multiaxis automatically
                            //if min/max value is set, set autoMin and autoMax to false.
                            self._verifyAxisAutoMinMax(axisVal);
                            $.extend(true, o.axis.x, axisVal.x || {});
                            if ($.isArray(o.axis.y) || $.isArray(axisVal.y)) {
                                oldYAxis = {};
                            } else {
                                oldYAxis = o.axis.y;
                            }
                            if ($.isArray(axisVal.y)) {
                                $.each(axisVal.y, function (i, _yaxis) {
                                    axisVal.y[i] = $.extend(true, {}, baseAxis.y, oldYAxis, _yaxis);
                                });
                                o.axis.y = axisVal.y;
                            } else {
                                o.axis.y = $.extend(true, {}, baseAxis.y, oldYAxis, axisVal.y);
                            }
                        } else {
                            $.extend(true, o[key], value);
                        }
                        if (key === "indicator") {
                            this._unbindCanvasEvents();
                            this._bindCanvasEvents();
                        }

                        if (key === "axis") {
                            newYAxis = o.axis.y;
                            if (o.axis.x.tickMajor.factor < 0) {
                                o.axis.x.tickMajor.factor = oldXMajorFactor;
                            }
                            if (o.axis.x.tickMinor.factor < 0) {
                                o.axis.x.tickMinor.factor = oldXMinorFactor;
                            }

                            //case origin y is object, now is object
                            if (!$.isArray(newYAxis)) {
                                if ($.isArray(bakYAxis)) {
                                    oldYMajorFactor = bakYAxis[0].tickMajor.factor;
                                    oldYMinorFactor = bakYAxis[0].tickMinor.factor;
                                } else {
                                    oldXMajorFactor = bakYAxis.tickMajor.factor;
                                    oldXMinorFactor = bakYAxis.tickMinor.factor;
                                }
                                if (o.axis.y.tickMajor && o.axis.y.tickMajor.factor !== undefined && o.axis.y.tickMajor.factor < 0) {
                                    o.axis.y.tickMajor.factor = oldYMajorFactor;
                                }
                                if (o.axis.y.tickMinor && o.axis.y.tickMinor.factor !== undefined && o.axis.y.tickMinor.factor < 0) {
                                    o.axis.y.tickMinor.factor = oldYMinorFactor;
                                }
                            } else {
                                if (!$.isArray(bakYAxis)) {
                                    bakYAxis = [bakYAxis];
                                }
                                $.each(newYAxis, function (i, yAxis) {
                                    var baky = bakYAxis[i] || {};
                                    if (baky.tickMajor && baky.tickMajor.factor && yAxis.tickMajor && yAxis.tickMajor.factor) {
                                        if (yAxis.tickMajor.factor < 0) {
                                            yAxis.tickMajor.factor = baky.tickMajor.factor;
                                        }
                                    }
                                    if (baky.tickMinor && baky.tickMinor.factor && yAxis.tickMinor && yAxis.tickMinor.factor) {
                                        if (yAxis.tickMinor.factor < 0) {
                                            yAxis.tickMinor.factor = baky.tickMinor.factor;
                                        }
                                    }
                                });
                            }
                        }
                    } else {
                        _super.prototype._setOption.call(this, key, value);
                        // o[key] = value;
                    }
                }

                if (key === "autoResize") {
                    self._unbindResizeEvent();
                    self._bindResizeEvent();
                }

                // fixed a issue that when set the disabled option,
                // because the chart is paint by
                // wij***chart plugin, and the disabled set to the plugin
                // as a value, not a refrence,
                // so the plugin's disabled value can't change
                // when set the disabled to charts.
                // now, we just repaint the chart.
                if (key === "seriesTransition" || key === "animation") {
                    //||
                    //	key === "disabled") {
                    return;
                }

                if (key === "hint") {
                    self._resetTooltip();
                    return;
                }

                len = o.seriesList.length;

                if (key === "seriesList" || key === "seriesStyles" || key === "seriesHoverStyles") {
                    //backup the styles. when drawed the charts, restore the styles.
                    if (key !== "seriesList") {
                        self._handleChartStyles();
                    }
                    self.styles = {
                        style: [].concat(o.seriesStyles.slice(0, o.seriesStyles.length)),
                        hoverStyles: [].concat(o.seriesHoverStyles.slice(0, o.seriesHoverStyles.length))
                    };
                    self._initStyles();
                }

                if (key === "seriesList" || key === "seriesHoverStyles") {
                    hoverStyleLen = o.seriesHoverStyles.length;
                    for (idx = hoverStyleLen; idx < len; idx++) {
                        o.seriesHoverStyles[idx] = o.seriesHoverStyles[idx % hoverStyleLen];
                    }
                }

                // fixed an issue that if set height and width option,
                // the chart element's height is not reset.
                if (key === "height" || key === "width") {
                    self.chartElement[key](value);
                }

                if (key === "culture" || key === "cultureCalendar") {
                    self._innerCulture = null;
                    self._resetCulture();
                }

                self.redraw();
            };

            wijchartcore.prototype._innerDisable = function () {
                _super.prototype._innerDisable.call(this);
                this._handleDisabledOption(true, this.chartElement);
            };

            wijchartcore.prototype._innerEnable = function () {
                _super.prototype._innerEnable.call(this);
                this._handleDisabledOption(false, this.chartElement);
            };

            wijchartcore.prototype._toggleDisable = function () {
                var self = this, e = self.element;
                if (self._isDisabled()) {
                    self._opacityHolder = e.css("opacity");
                    e.css("opacity", disabledCss);
                } else {
                    e.css("opacity", self._opacityHolder);
                }
            };

            wijchartcore.prototype._isTrendline = function (series) {
                if (series.isTrendline || series.type === ChartConsts.strTrendline) {
                    return true;
                }
                return false;
            };

            wijchartcore.prototype._preHandleSeriesData = function () {
                //handler the trendline data
                var self = this, opts = self.options, seriesList = opts.seriesList, axis = opts.axis;

                $.each(seriesList, function (i, series) {
                    var data = series.data, valuesX = [], valuesY = [], length, k, innerData;

                    if (!self._isTrendline(series)) {
                        return true;
                    }
                    if (data.xy && $.isArray(data.xy) && data.xy.length) {
                        length = data.xy.length;
                        while (k < length) {
                            valuesX.push(data.xy[k++]);
                            valuesY.push(data.xy[k++]);
                        }
                        data.x = valuesX;
                        data.y = valuesY;
                    } else if (!data.x) {
                        valuesX = [];

                        $.each(valuesY, function (i) {
                            valuesX.push(i);
                        });

                        data.x = valuesX;
                    }
                    try  {
                        innerData = ChartDataUtil.processValues(data.x, data.y, series.fitType, axis.x.autoMin, axis.x.autoMax, axis.x.min, axis.x.max, series.order, series.sampleCount, series.display, undefined);
                    } catch (e) {
                        innerData = undefined;
                    }
                    if (innerData === undefined) {
                        series.isValid = false;
                    } else {
                        series.isValid = true;
                        series.innerData = innerData;
                    }
                });
            };

            wijchartcore.prototype._seriesListSeted = function () {
            };

            wijchartcore.prototype._initStyles = function () {
                var o = this.options, styles = o.seriesStyles, hoverStyles = o.seriesHoverStyles, stylesLen, seriesLen, hoverStylesLen, i;

                if (o.seriesList) {
                    seriesLen = o.seriesList.length || 0;
                }

                if (o.seriesStyles) {
                    stylesLen = o.seriesStyles.length || 0;
                }

                if (o.seriesHoverStyles) {
                    hoverStylesLen = o.seriesHoverStyles.length || 0;
                }

                if (seriesLen > stylesLen && stylesLen) {
                    for (i = stylesLen; i < seriesLen; i++) {
                        styles[i] = styles[i % stylesLen];
                    }
                }

                if (seriesLen > hoverStylesLen && hoverStylesLen) {
                    for (i = hoverStylesLen; i < seriesLen; i++) {
                        hoverStyles[i] = hoverStyles[i % hoverStylesLen];
                    }
                }
            };

            wijchartcore.prototype._verifyAxisAutoMinMax = function (axis) {
                var isNullOrUndefined = function (value) {
                    return value === null || typeof value === "undefined";
                };
                if (axis.x) {
                    if (!isNullOrUndefined(axis.x.min)) {
                        axis.x.autoMin = false;
                    } else {
                        axis.x.autoMin = true;
                    }
                    if (!isNullOrUndefined(axis.x.max)) {
                        axis.x.autoMax = false;
                    } else {
                        axis.x.autoMax = true;
                    }
                }
                if (axis.y) {
                    if ($.isArray(axis.y)) {
                        $.each(axis.y, function (i, yaxis) {
                            if (!isNullOrUndefined(yaxis.min)) {
                                yaxis.autoMin = false;
                            } else {
                                yaxis.autoMin = true;
                            }
                            if (!isNullOrUndefined(yaxis.max)) {
                                yaxis.autoMax = false;
                            } else {
                                yaxis.autoMax = true;
                            }
                        });
                    } else {
                        var yAxis = axis.y;
                        if (!isNullOrUndefined(yAxis.min)) {
                            yAxis.autoMin = false;
                        } else {
                            yAxis.autoMin = true;
                        }
                        if (!isNullOrUndefined(yAxis.max)) {
                            yAxis.autoMax = false;
                        } else {
                            yAxis.autoMax = true;
                        }
                    }
                }
            };

            wijchartcore.prototype._addChartVisibilityObserver = function () {
                var self = this, ele = self.element;

                if (ele.is(":hidden") && ele.wijAddVisibilityObserver) {
                    if (ele.hasClass("wijmo-wijobserver-visibility")) {
                        return;
                    }

                    ele.wijAddVisibilityObserver(function () {
                        self.redraw();
                        if (self.element.wijRemoveVisibilityObserver) {
                            self.element.wijRemoveVisibilityObserver();
                        }
                    }, "wijchart");
                }
            };

            wijchartcore.prototype._create = function () {
                var self = this, o = self.options, width = o.width || self.element.width(), height = o.height || self.element.height(), newEle = null, canvas;

                // enable touch support:
                if (window.wijmoApplyWijTouchUtilEvents) {
                    $ = window.wijmoApplyWijTouchUtilEvents($);
                }

                //if min/max value is set, set autoMin and autoMax to false.
                self._verifyAxisAutoMinMax(o.axis);

                self.updating = 0;
                self.innerState = {};
                self.axisCompass = {};

                self._addChartVisibilityObserver();

                // Add for parse date options for jUICE. D.H
                // TO DO
                if ($.isFunction(window["wijmoASPNetParseOptions"])) {
                    window["wijmoASPNetParseOptions"](o);
                }

                // backup the styles. when drawed the charts, restore the styles.
                // when postback the styles, if doesn't clone the styles,
                // the serverside will get the extended styles. when the add a series data,
                // the extend style will wrong.
                self.styles = {
                    style: [].concat(o.seriesStyles.slice(0, o.seriesStyles.length)),
                    hoverStyles: [].concat(o.seriesHoverStyles.slice(0, o.seriesHoverStyles.length))
                };

                if (o.hint && typeof o.hint.content === "string" && window[o.hint.content]) {
                    o.hint.content = window[o.hint.content];
                }
                if (o.hint && typeof o.hint.title === "string" && window[o.hint.title]) {
                    o.hint.title = window[o.hint.title];
                }

                self.legendEles = [];
                self.axisEles = [];
                self.legends = [];
                self.legendIcons = [];
                self.legendDots = [];
                self.chartLabelEles = [];
                self.seriesEles = [];

                if (self.element.length > 0) {
                    if (self.element.is("table")) {
                        self._parseTable();
                        newEle = $("<div></div>");

                        if (width) {
                            newEle.css("width", width);
                        }

                        if (height) {
                            newEle.css("height", height);
                        }

                        self.element.after(newEle);
                        self.chartElement = newEle;
                    } else {
                        self.chartElement = self.element;
                    }

                    self.chartElement.addClass("ui-widget");

                    try  {
                        canvas = Raphael(self.chartElement[0], width, height);
                    } catch (e) {
                        var displayCss = self.chartElement.css("display");
                        newEle = $("<div></div>").insertBefore(self.chartElement).append(self.chartElement);
                        self.chartElement.addClass("ui-helper-hidden-accessible").appendTo($('body'));
                        if (displayCss === "none") {
                            self.chartElement.css("display", "block");
                        }
                        canvas = Raphael(self.chartElement[0], width, height);
                        self.chartElement.appendTo(newEle).unwrap().removeClass("ui-helper-hidden-accessible");
                        if (displayCss === "none") {
                            self.chartElement.css("display", "none");
                        }
                    }
                    self.canvas = canvas;

                    //add comments to fix tfs issue 27816, if element's height is not set,
                    //element's height will be 4px larger than canvas's,
                    //so set height to element is height is 0;
                    if (height === 0 && o.height !== 0) {
                        self.element.height(canvas.height);
                    }

                    // end comments.
                    // add custom attribute to canvas
                    // fixed the issue 20422 by dail on 2012-3-12, If user set
                    // rotation and scale. the transform will only effect on scale.
                    canvas.customAttributes.rotation = function (num) {
                        //return {transform: "...R" + num};
                        this.transform("...R" + num);
                    };
                    canvas.customAttributes.scale = function (num) {
                        //return {transform: "...S" + num};
                        this.transform("...S" + num);
                    };
                    canvas.customAttributes.translation = function (x, y) {
                        //return {transform: Raphael.format("...T{0},{1}", x, y)};
                        this.transform(Raphael.format("...T{0},{1}", x, y));
                    };

                    // end
                    self._bindLiveEvents();
                    _super.prototype._create.call(this);
                }
            };

            wijchartcore.prototype._handleChartStyles = function () {
                this._extendArrayFromBase("seriesStyles");
                this._extendArrayFromBase("seriesHoverStyles");

                var o = this.options, defFill = this._getDefFill();
                $.each(o.seriesStyles, function (idx, style) {
                    if (!style.fill) {
                        style.fill = defFill[idx];
                    }
                });
            };

            wijchartcore.prototype._extendArrayFromBase = function (optionName) {
                var result = $.extend(true, [], wijchartcore.prototype.options[optionName], this.options[optionName]);

                this.options[optionName] = result;
            };

            wijchartcore.prototype._getDefFill = function () {
                var defFill = [
                    "#00cc00",
                    "#0099cc",
                    "#0055cc",
                    "#2200cc",
                    "#8800cc",
                    "#d9007e",
                    "#ff0000",
                    "#ff6600",
                    "#ff9900",
                    "#ffcc00",
                    "#ffff00",
                    "#ace600"
                ];
                return defFill;
            };

            wijchartcore.prototype._getCulture = function (name) {
                if (!this._innerCulture) {
                    this._resetCulture(name);
                }
                return this._innerCulture;
            };
            wijchartcore.prototype._resetCulture = function (culture) {
                var cal = $.wijGetCulture(culture || this.options.culture, this.options.cultureCalendar);
                this._innerCulture = cal;
            };

            wijchartcore.prototype._handleDisabledOption = function (disabled, element) {
                var self = this;
                if (disabled) {
                    if (!self.disabledDiv) {
                        self.disabledDiv = self._createDisabledDiv(element);
                    }
                    self.disabledDiv.appendTo("body");
                } else {
                    if (self.disabledDiv) {
                        self.disabledDiv.remove();
                        self.disabledDiv = null;
                    }
                }
            };

            wijchartcore.prototype._createDisabledDiv = function (outerEle) {
                var self = this, o = self.options, ele = outerEle || self.element, eleOffset = ele.offset(), disabledWidth = o.width || ele.outerWidth(), disabledHeight = o.height || ele.outerHeight(), disabledDiv;

                disabledDiv = $("<div></div>").css({
                    "z-index": "99999",
                    position: "absolute",
                    width: disabledWidth,
                    height: disabledHeight,
                    left: eleOffset.left,
                    top: eleOffset.top
                });

                if (Raphael.vml) {
                    disabledDiv.addClass(o.wijCSS.stateDisabled).css("background-color", "#fff");
                }

                return disabledDiv;
            };

            wijchartcore.prototype._bindData = function () {
                var _this = this;
                var self = this, o = self.options, dataSource = o.dataSource, seriesList = o.seriesList, shareData = o.data, cacheObj = {};

                $.each(seriesList, function (i, series) {
                    var ds = series.dataSource || dataSource;

                    if (ds && series.data || series.type === "sharedPie") {
                        _this._bindSeriesData(ds, series, cacheObj);
                    }
                });
            };

            wijchartcore.prototype._bindSeriesData = function (ds, series, cacheObj) {
                var data = series.data, dataX = data.x, dataY = data.y, shareData = this.options.data;

                if (dataX && dataX.bind) {
                    data.xField = dataX.bind;
                    data.x = this._getBindData(ds, data.xField);
                } else if (shareData && shareData.x && shareData.x.bind) {
                    if (cacheObj.sharedXList === undefined) {
                        cacheObj.sharedXList = this._getBindData(ds, shareData.x.bind);
                    }
                    data.x = cacheObj.sharedXList;
                }
                if (dataY && dataY.bind) {
                    data.y = this._getBindData(ds, dataY.bind);
                }
            };

            wijchartcore.prototype._getBindData = function (dataSource, bind) {
                if ($.isArray(dataSource)) {
                    var arr = [];
                    $.each(dataSource, function (i, data) {
                        if (data && data[bind] !== undefined) {
                            arr.push(data[bind]);
                        }
                    });
                    return arr;
                }
                return null;
            };

            wijchartcore.prototype._hanldSharedXData = function () {
                var self = this, o = self.options, seriesList = o.seriesList, data = o.data;

                if (data) {
                    $.each(seriesList, function (i, series) {
                        var d = series.data;
                        if (d.x === undefined || d.x === null && $.isArray(data.x)) {
                            d.x = data.x;
                        }
                    });
                }
            };

            wijchartcore.prototype._init = function () {
                var self = this, o = self.options, seriesList;

                // back up the seriesList
                if (!self.rendered) {
                    self.seriesList = $.arrayClone(o.seriesList);
                }

                // bind dataSource
                self._bindData();
                self._hanldSharedXData();

                seriesList = o.seriesList.concat();
                $.each(seriesList, function (i, series) {
                    var data = series.data, idx;
                    if (typeof data === 'undefined' || data === null) {
                        idx = $.inArray(series, o.seriesList);
                        o.seriesList.splice(idx, 1);
                    }
                });
                seriesList = null;

                /*
                * o.seriesList = $.grep(o.seriesList, function(series, i) { var
                * data = series.data; if (typeof data === 'undefined' || data ===
                * null) { return false; } return true; });
                */
                if (!self.rendered && !self.updating) {
                    self._paint();
                }
                //super._init();
            };

            /**
            * Remove the functionality completely. This will return the element back to its pre-init state.
            */
            wijchartcore.prototype.destroy = function () {
                var self = this, o = self.options;
                self._unbindLiveEvents();
                self._clearChartElement();
                self.chartElement.removeClass("ui-widget");

                $("." + o.wijCSS.canvasObject, self.chartElement[0]).off(self.widgetName).off("." + self.widgetName);

                if (self.element !== self.chartElement) {
                    self.chartElement.remove();
                }

                self.element.empty();

                if (self.styles) {
                    self.styles = null;
                }

                // Add for fixing bug 16039
                if (self.disabledDiv) {
                    self.disabledDiv.remove();
                    self.disabledDiv = null;
                }

                // end for bug 16039
                if (self.chartHeader) {
                    self.chartHeader.destroy();
                    self.chartHeader = null;
                }
                if (self.chartFooter) {
                    self.chartFooter.destroy();
                    self.chartFooter = null;
                }
                if (self.chartXAxis) {
                    self.chartXAxis.destroy();
                    self.chartXAxis = null;
                }
                if (self.chartYAxis) {
                    $.each(self.chartYAxis, function (idx, yAxis) {
                        yAxis.destroy();
                        yAxis = null;
                    });
                    self.chartYAxis = null;
                }
                if (self.chartLegend) {
                    self.chartLegend.destroy();
                    self.chartLegend = null;
                }

                _super.prototype.destroy.call(this);
            };

            /**
            * Returns a reference to the Raphael canvas object.
            * @returns {Raphael} Reference to raphael canvas object.
            * @example
            * $("#chartcore").wijchartcore("getCanvas")
            */
            wijchartcore.prototype.getCanvas = function () {
                return this.canvas;
            };

            /**
            * Exports the chart in a graphic format.
            * The export method only works when wijmo.exporter.chartExport's reference is on the page.
            * @remarks Default exported file type is png, possible types are: jpg, png, gif, bmp, tiff, pdf.
            * @param {string|Object} exportSettings
            * 1.The name of the exported file.
            * 2.Settings of exporting, should be conformed to wijmo.exporter.ChartExportSetting
            * @param {?string} type The type of the exported file.
            * @param {?string} pdfSettings The setting of pdf.
            * @param {?string} serviceUrl The export service url.
            * @param {?string} exportMethod with different mode,
            * 1. "Content" Sending chart markup to the service for exporting. It requires IE9 or high version installed on the service host. It has better performance than Options mode.
            * 2. "Options" Sending chart widget options to the service for exporting.
            * @example
            * $("#chartcore").wijchartcore("exportChart", "chart", "png");
            */
            wijchartcore.prototype.exportChart = function (exportSettings, type, pdfSettings, serviceUrl, exportMethod) {
            };

            /**
            * Add series point to the series list.
            * @param {number} seriesIndex The index of the series that the point will be inserted to.
            * @param {object} point The point that will be inserted to.
            * @param {Boolean} shift A value that indicates whether to shift the first point.
            */
            wijchartcore.prototype.addSeriesPoint = function (seriesIndex, point, shift) {
                var seriesList = this.options.seriesList, series = null, data = null;

                if (seriesIndex >= seriesList.length) {
                    return;
                }

                series = seriesList[seriesIndex];
                data = series.data || [];
                data.x.push(point.x);
                data.y.push(point.y);

                if (shift) {
                    data.x.shift();
                    data.y.shift();
                }

                this._setOption("seriesList", seriesList);
            };

            /**
            * Suspend automatic updates to the chart while reseting the options.
            */
            wijchartcore.prototype.beginUpdate = function () {
                var self = this;
                self.updating++;
            };

            /**
            * Restore automatic updates to the chart after the options has been reset.
            */
            wijchartcore.prototype.endUpdate = function () {
                var self = this;
                self.updating--;
                self.redraw();
            };

            /**
            * This method redraws the chart.
            * @param {?Boolean} drawIfNeeded A value that indicates whether to redraw the chart regardless of whether
            * the chart already exists. If true, then the chart is redrawn only if it was not already created. If false,
            * then the chart is redrawn, even if it already exists.
            */
            wijchartcore.prototype.redraw = function (drawIfNeeded) {
                var self = this, o = self.options, width = 0, height = 0;

                if (self.updating > 0) {
                    return;
                }

                if (drawIfNeeded && self.rendered) {
                    return;
                }

                width = o.width || self.element.width();
                height = o.height || self.element.height();

                if (width < 1 || height < 1) {
                    return;
                }

                if (!self.element.is(":hidden")) {
                    self.canvas.setSize(width, height);
                    self._paint();
                } else {
                    self._addChartVisibilityObserver();
                }
            };

            wijchartcore.prototype._parseTable = function () {
                if (!this.element.is("table")) {
                    return;
                }
                var self = this, ele = self.element, o = self.options, captions = $("caption", ele), theaders = $("thead th", ele), seriesList = [], sList = $("tbody tr", ele);

                if (captions.length) {
                    o.header = $.extend({
                        visible: true,
                        text: $.trim($(captions[0]).text())
                    }, o.header);
                    if (captions.length > 1) {
                        o.footer = $.extend({
                            visibel: true,
                            text: $.trim($(captions[1]).text())
                        }, o.footer);
                    }
                }

                // legend
                o.legend = $.extend({
                    visible: true
                }, o.legend);

                self._getSeriesFromTR(theaders, sList, seriesList);

                self.options.seriesList = seriesList;
            };

            wijchartcore.prototype._getSeriesFromTR = function (theaders, sList, seriesList) {
                var valuesX = [], val = null, series = null;

                // seriesList
                if (theaders.length) {
                    theaders.each(function () {
                        val = $.trim($(this).text());
                        valuesX.push(val);
                    });
                }
                if (sList.length) {
                    sList.each(function () {
                        var th = $("th", $(this)), label = $.trim(th.text()), valuesY = [], tds = $("td", $(this));

                        if (tds.length) {
                            tds.each(function (idx, ele) {
                                var td = $(this);
                                valuesY.push(parseFloat($.trim(td.text())));
                            });
                        }
                        series = {
                            label: label,
                            legendEntry: true,
                            data: {
                                x: valuesX,
                                y: valuesY
                            }
                        };
                        seriesList.push(series);
                    });
                }
            };

            wijchartcore.prototype._destroyRaphaelArray = function (objs) {
                if (!objs) {
                    return;
                }
                var len = objs.length, i = 0, ele, obj;

                for (; len && i < len; i++) {
                    ele = objs[i];
                    if (ele && ele[0]) {
                        obj = $(ele.node);
                        obj.unbind().removeData();
                        ele.wijRemove();
                        obj.remove();
                        obj = null;
                    }
                    objs[i] = null;
                }
            };

            wijchartcore.prototype._clearChartElement = function () {
                var self = this, fields = self.chartElement.data("fields");

                self._destroyRaphaelArray(self.breakLineEles);

                self._destroyRaphaelArray(self.chartLabelEles);

                if (self.tooltip) {
                    self.tooltip.destroy();
                    self.tooltip = null;
                }

                self.dataPoints = null;
                self.pointXs = null;
                if (fields && fields.trackers) {
                    self._destroyRaphaelArray(fields.trackers);
                    fields.trackers = null;
                }

                self.breakLineEles = [];

                self.chartLabelEles = [];

                if (fields && fields.chartElements) {
                    $.each(fields.chartElements, function (key, eles) {
                        self._destroyRaphaelArray(eles);
                    });
                    fields.chartElements = null;
                }

                if (fields && fields.seriesEles) {
                    fields.seriesEles = null;
                }

                if (self.seriesEles) {
                    self.seriesEles = [];
                }

                self.canvas.clear();
                self.innerState = null;
                self.axisInfo = null;
                self.seriesGroup = null;
                self.lastAxisOffset = null;
                self.innerState = {};
            };

            wijchartcore.prototype._text = function (x, y, text) {
                var textElement = this.canvas.text(x, y, text);

                if (this.options.disableDefaultTextStyle) {
                    textElement.node["style"].cssText = "";
                }

                return textElement;
            };

            wijchartcore.prototype._paint = function () {
                var self = this, o = self.options, element = self.element, hidden = element.css("display") === "none" || element.css("visibility") === "hidden", oldLeft, oldPosition = null;

                // ev = $.Event("beforepaint");
                if (hidden) {
                    oldLeft = element.css("left");
                    oldPosition = element.css("position");
                    element.css("left", "-10000px");
                    element.css("position", "absolute");
                    element.show();
                }

                if (element.is(":hidden")) {
                    if (hidden) {
                        element.css("left", oldLeft);
                        element.css("position", oldPosition);
                        element.hide();
                    }
                    return;
                }

                self._clearChartElement();
                if (self._trigger("beforePaint") === false) {
                    return;
                }

                // self._trigger("beforepaint", ev);
                self._initStyles();
                self._preHandleSeriesData();

                self.canvasBounds = {
                    startX: 0,
                    endX: o.width || element.width(),
                    startY: 0,
                    endY: o.height || element.height()
                };
                self._paintHeader();
                self._paintFooter();
                self._paintChartLegend();
                self._paintChartArea();

                //self._paintChartLabels();
                if (o.indicator && o.indicator.visible) {
                    if (this.pointXs) {
                        this.pointXs = this.pointXs.sort(function (a, b) {
                            return a - b;
                        });
                    }
                }
                self._paintTooltip();

                self._trigger("painted");

                self.rendered = true;

                // restore the backup options.
                if (self.styles) {
                    o.seriesStyles = self.styles.style;
                    o.seriesHoverStyles = self.styles.hoverStyles;
                }

                // restore the axis "min" and "max"
                if (o.axis && o.axis.x && self.axisInfo && self.axisInfo.x) {
                    o.axis.x.max = self.axisInfo.x.originalMax;
                    o.axis.x.min = self.axisInfo.x.originalMin;
                }

                //$.wijraphael.clearRaphaelCache();
                if (hidden) {
                    element.css("left", oldLeft);
                    element.css("position", oldPosition);
                    element.hide();
                }
            };

            // indicator tooltip
            wijchartcore.prototype._paintIndicater = function () {
            };

            wijchartcore.prototype._calculatePosition = function (compass, width, height) {
                var point = { x: 0, y: 0 }, marginX = 5, marginY = 5, canvasBounds = this.canvasBounds;
                switch (compass) {
                    case "north":
                        point.x = (canvasBounds.endX - canvasBounds.startX) / 2;
                        point.y = canvasBounds.startY + height / 2 + marginY;
                        canvasBounds.startY = canvasBounds.startY + marginY * 2 + height;
                        break;
                    case "south":
                        point.x = (canvasBounds.endX - canvasBounds.startX) / 2;
                        point.y = canvasBounds.endY - height / 2 - marginY;
                        canvasBounds.endY = canvasBounds.endY - marginY * 2 - height;
                        break;
                    case "east":
                        point.x = canvasBounds.endX - width / 2 - marginX;
                        point.y = (canvasBounds.endY - canvasBounds.startY) / 2;
                        canvasBounds.endX = canvasBounds.endX - marginX * 2 - width;
                        break;
                    case "west":
                        point.x = canvasBounds.startX + width / 2 + marginX;
                        point.y = (canvasBounds.endY - canvasBounds.startY) / 2;
                        canvasBounds.startX = canvasBounds.startX + marginX * 2 + width;
                        break;
                }
                return point;
            };

            wijchartcore.prototype._paintHeader = function () {
                var self = this, o = self.options, headerOptions = {
                    text: o.header.text,
                    textStyle: $.extend(true, {}, o.textStyle, o.header.textStyle),
                    textCSS: o.wijCSS.headerText,
                    containerStyle: o.header.style,
                    containerCSS: o.wijCSS.headerContainer,
                    compass: o.header.compass,
                    visible: o.header.visible,
                    canvasBounds: self.canvasBounds,
                    disableDefaultTextStyle: o.disableDefaultTextStyle
                }, textBBox;

                if (!self.chartHeader) {
                    self.chartHeader = new Title(this.canvas, headerOptions);
                    self.chartHeader.render();
                } else {
                    self.chartHeader.redraw(headerOptions);
                }

                self.canvasBounds = self.chartHeader.updatedCanvasBounds;
            };

            wijchartcore.prototype._paintFooter = function () {
                var self = this, o = self.options, footerOptions = {
                    text: o.footer.text,
                    textStyle: $.extend(true, {}, o.textStyle, o.footer.textStyle),
                    textCSS: o.wijCSS.footerText,
                    containerStyle: o.footer.style,
                    containerCSS: o.wijCSS.footerContainer,
                    compass: o.footer.compass,
                    visible: o.footer.visible,
                    canvasBounds: self.canvasBounds,
                    disableDefaultTextStyle: o.disableDefaultTextStyle
                }, textBBox;

                if (!self.chartFooter) {
                    self.chartFooter = new Title(this.canvas, footerOptions);
                    self.chartFooter.render();
                } else {
                    self.chartFooter.redraw(footerOptions);
                }

                self.canvasBounds = self.chartFooter.updatedCanvasBounds;
            };

            wijchartcore.prototype._getRotationByCompass = function (compass) {
                var rotation = 0;

                if (compass === "east") {
                    rotation = 90;
                } else if (compass === "west") {
                    rotation = -90;
                }

                return rotation;
            };

            wijchartcore.prototype._getLegendStyle = function (seriesStyle) {
                return seriesStyle;
            };

            // This method will replace the method "_paintLegend" until "Legend" class completed.
            wijchartcore.prototype._paintChartLegend = function () {
                var legendOptions = this._getLegendRendererOptions();

                if (this.options.legend.visible) {
                    if (!this.chartLegend) {
                        this.chartLegend = new Legend(this.canvas, legendOptions);
                        this.chartLegend.render();
                    } else {
                        this.chartLegend.redraw(legendOptions);
                    }
                    this.canvasBounds = this.chartLegend.updatedCanvasBounds;
                }
            };

            // Get options for "Legend"
            wijchartcore.prototype._getLegendRendererOptions = function () {
                var self = this, o = self.options, legend = o.legend, chartsSeries = o.seriesList, chartsSeriesStyles = o.seriesStyles, legendOptions;

                legendOptions = self._getLegendbasicInfo();
                legendOptions.legendInfoList = self._getLegendSeriesInfoList();

                if (legend.reversed) {
                    legendOptions.legendInfoList = legendOptions.legendInfoList.reverse();
                }
                $.each(legendOptions.legendInfoList, function (idx, lInfo) {
                    lInfo.legendIdx = idx;
                });

                return legendOptions;
            };

            // Get basic legend info such as canvasBounds, compass, CSS, Style, iconSize...
            // LineChart, BubbleChart and ScatterChart will overwrite this method
            // since they should set different "iconSize".
            wijchartcore.prototype._getLegendbasicInfo = function () {
                var self = this, o = self.options, legend = o.legend, legendInfo, chartsSeries = o.seriesList, chartsSeriesStyles = o.seriesStyles, legendOptions = {
                    /** base **/
                    disableDefaultTextStyle: o.disableDefaultTextStyle,
                    canvasBounds: self.canvasBounds,
                    disabled: self._isDisabled(),
                    compass: legend.compass,
                    orientation: legend.orientation,
                    legendCSS: o.wijCSS.legendContainer,
                    legendStyle: legend.style,
                    legendMargin: 2,
                    legendInfoList: [],
                    title: legend.text,
                    titleStyle: $.extend(true, {}, o.textStyle, legend.textStyle, legend.titleStyle),
                    titleCSS: o.wijCSS.legendTitle,
                    labelStyle: $.extend(true, {}, o.textStyle, legend.textStyle),
                    labelWidth: legend.textWidth,
                    labelCSS: o.wijCSS.legendText + " " + o.wijCSS.legend,
                    labelMargin: legend.textMargin,
                    labelCoverCSS: o.wijCSS.legendTextCover + " " + o.wijCSS.legend,
                    iconSize: $.extend(true, {
                        width: 22,
                        height: 10,
                        r: 0
                    }, legend.size),
                    iconCSS: o.wijCSS.legendIcon + " " + o.wijCSS.legend,
                    markerCSS: Raphael.format("{0} {1} {2}", o.wijCSS.legend, o.wijCSS.legendDot, o.wijCSS.canvasObject),
                    legendClickFunc: function (eventData) {
                        self._legendClickFunc(eventData);
                    }
                };

                return legendOptions;
            };

            wijchartcore.prototype._legendClickFunc = function (data) {
                var self = this, seriesIdx = data.seriesIdx, fields = self.chartElement.data("fields"), seriesEles = self.seriesEles, seriesEle;

                if (seriesIdx === null || seriesIdx === undefined) {
                    return;
                }

                if (fields && fields.seriesEles) {
                    seriesEles = fields.seriesEles;
                }
                seriesEle = seriesEles[seriesIdx];
                if (!seriesEle) {
                    return;
                }
                if (!data.visible) {
                    self._showSerieEles(seriesEles[seriesIdx]);
                } else {
                    self._hideSerieEles(seriesEles[seriesIdx]);
                }
                self._toggleDataBoundAnnotation(seriesIdx, !data.visible);
            };

            wijchartcore.prototype._toggleDataBoundAnnotation = function (seriesIdx, visible) {
                var fields = this.chartElement.data("fields"), boundAnnotations;
                if (fields && fields.boundAnnotations && fields.boundAnnotations[seriesIdx]) {
                    boundAnnotations = fields.boundAnnotations[seriesIdx];
                    $.each(boundAnnotations, function (key, annoUI) {
                        annoUI.toggleVisibility(visible);
                    });
                }
            };

            // Get legendInfoList from chart seriesList.
            // CompositeChart will overwrite this method since "pie" type series will contains multi legend items.
            wijchartcore.prototype._getLegendSeriesInfoList = function () {
                var self = this, o = self.options, legendInfo, chartsSeries = o.seriesList, chartsSeriesStyles = o.seriesStyles, seriesStyle, legendInfoList = [], availableSeriesIndex = 0;
                ;
                $.each(chartsSeries, function (idx, series) {
                    seriesStyle = self._getLegendStyle(chartsSeriesStyles[idx]);

                    if (series.legendEntry !== false) {
                        if (series.isTrendline) {
                            legendInfo = self._getTrendLineLegendInfoFromSeries(availableSeriesIndex, series, seriesStyle);
                        } else {
                            legendInfo = self._getLegendInfoFromSeries(availableSeriesIndex, series, seriesStyle);
                        }
                        if (legendInfo) {
                            legendInfoList.push(legendInfo);
                        }
                    }

                    if (!series.isTrendline || TrendlineRender.validateType(series.fitType)) {
                        availableSeriesIndex++;
                    }
                });

                return legendInfoList;
            };

            // Get a legendInfo from a trend line series.
            wijchartcore.prototype._getTrendLineLegendInfoFromSeries = function (seriesIdx, series, seriesStyle) {
                var iconStyle, legendSize = this.options.legend.size, legendInfo = this._getBasicLegendInfoFromSeries(seriesIdx, series, seriesStyle);

                if (series.fitType) {
                    if (!TrendlineRender.validateType(series.fitType)) {
                        return undefined;
                    }
                }

                iconStyle = legendInfo.iconStyle;

                legendInfo.icon = "line";

                legendInfo.iconSize = $.extend(true, {}, { width: 22, height: 1 }, this.options.legend.size);

                return legendInfo;
            };

            // Get legend info from a normal series (Not trendline).
            // LineChart, BubbleChart, ScatterChart and CompositieChart will overwrite this method.
            wijchartcore.prototype._getLegendInfoFromSeries = function (seriesIdx, series, seriesStyle) {
                return this._getBasicLegendInfoFromSeries(seriesIdx, series, seriesStyle);
            };

            wijchartcore.prototype._getBasicLegendInfoFromSeries = function (seriesIdx, series, seriesStyle) {
                var iconType = "rect", legendInfo, iconStyle = $.extend(true, {
                    fill: "none",
                    opacity: 1,
                    stroke: "black"
                }, seriesStyle);
                if (!(parseInt(iconStyle["stroke-width"]) === 0)) {
                    iconStyle = $.extend(iconStyle, { "stroke-width": 1 });
                }

                legendInfo = {
                    icon: iconType,
                    iconStyle: iconStyle,
                    label: series.label,
                    markers: undefined,
                    markerVisible: false,
                    markerStyle: undefined,
                    seriesVisible: !(series.visible === false),
                    legendIdx: 0,
                    seriesIdx: seriesIdx,
                    iconSize: undefined
                };

                return legendInfo;
            };

            wijchartcore.prototype._hasAxes = function () {
                if (this.widgetName === "wijpiechart") {
                    return false;
                }
                return true;
            };

            wijchartcore.prototype._applyAxisText = function (axisOptions, axisInfo) {
                var self = this, text = axisOptions.text, textBounds = null, tempText = null, textStyle = null, textMarginVer = 0, textMarginHor = 0, canvasBounds = axisInfo.bounds || self.canvasBounds;

                if (text !== null && text !== undefined && text.length > 0) {
                    tempText = self._text(-100, -100, text);
                    textStyle = $.extend(true, {}, self.options.textStyle, axisOptions.textStyle);
                    tempText.attr(textStyle);
                    textBounds = tempText.wijGetBBox();
                    if (textStyle["margin-left"]) {
                        textMarginHor += parseFloat(textStyle["margin-left"]);
                    }
                    if (textStyle["margin-top"]) {
                        textMarginVer += parseFloat(textStyle["margin-top"]);
                    }
                    if (textStyle["margin-right"]) {
                        textMarginHor += parseFloat(textStyle["margin-right"]);
                    }
                    if (textStyle["margin-bottom"]) {
                        textMarginVer += parseFloat(textStyle["margin-bottom"]);
                    }

                    switch (axisOptions.compass) {
                        case "north":
                            canvasBounds.startY += (textBounds.height + textMarginVer);
                            break;
                        case "south":
                            canvasBounds.endY -= (textBounds.height + textMarginVer);
                            break;
                        case "east":
                            canvasBounds.endX -= (textBounds.height + textMarginHor);
                            break;
                        case "west":
                            canvasBounds.startX += (textBounds.height + textMarginHor);
                            break;
                    }
                    tempText.wijRemove();
                    tempText = null;
                }

                return textBounds;
            };

            wijchartcore.prototype._isSeriesListDataEmpty = function () {
                var _this = this;
                var self = this, sl = self.options.seriesList, isEmpty = true;

                $.each(sl, function (idx, s) {
                    if (!_this._checkSeriesDataEmpty(s)) {
                        isEmpty = false;
                        return false;
                    }
                });

                return isEmpty;
            };

            wijchartcore.prototype._checkEmptyData = function (arr) {
                if (!arr || !$.isArray(arr)) {
                    return true;
                }
                return false;
            };

            wijchartcore.prototype._checkSeriesDataEmpty = function (series) {
                var checkEmptyData = this._checkEmptyData, data = series.data;
                if (!data || ((checkEmptyData(data.x) || checkEmptyData(data.y)) && checkEmptyData(data.xy))) {
                    return true;
                } else if (this._isTrendline(series) && (!series.isValid || !series.innerData)) {
                    return true;
                } else {
                    return false;
                }
            };

            wijchartcore.prototype._setTooltipContent = function (obj) {
                var self = this, tooltipObjs, title, content, tooltip = self.tooltip, hintOptions, newOptions = {}, hint = self.options.hint, isFunction = $.isFunction;
                if (tooltip) {
                    // if the chart is line chart or compositechart, the data.x value is the marker position.
                    // change the value to the x value.
                    tooltipObjs = [];
                    $.each(obj, function (i, tooltipObj) {
                        var valX = tooltipObj.valX, valY = tooltipObj.valY;
                        if (valX && valY) {
                            tooltipObjs.push($.extend({}, tooltipObj, {
                                x: valX,
                                y: valY
                            }));
                        } else {
                            tooltipObjs.push(tooltipObj);
                        }
                    });
                    hintOptions = tooltip.getOptions();
                    title = hint.title;
                    content = hint.content;

                    if (isFunction(title)) {
                        newOptions.title = function () {
                            return title.call(tooltipObjs);
                        };
                    }

                    if (isFunction(content)) {
                        newOptions.content = function () {
                            return content.call(tooltipObjs);
                        };
                    }

                    tooltip.setOptions(newOptions);
                }
            };

            wijchartcore.prototype._setTooltip = function () {
                var self = this, o = self.options, tooltip = self.tooltip, obj;

                if (tooltip) {
                    obj = {
                        closeBehavior: "none",
                        style: {
                            stroke: o.indicator.style.stroke
                        },
                        animated: false,
                        showDelay: 0,
                        hideDelay: 0,
                        windowCollisionDetection: "fit",
                        beforeShowing: function (e, d) {
                            if (this.target && self.indicatorLine) {
                                return false;
                            }
                        }
                    };
                    if (o.horizontal) {
                        obj.compass = "east";
                    }
                    tooltip.setOptions(obj);
                }
            };

            // when mouse up in plot area, reset the tooltip options.
            wijchartcore.prototype._resetTooltip = function () {
                var self = this, o = self.options, hint = o.hint, title = hint.title, content = hint.content, tooltip = self.tooltip, isFunction = $.isFunction, obj = $.extend(true, {}, this.options.hint);

                if (tooltip) {
                    obj.animated = hint.animated;
                    obj.showDelay = hint.showDelay;
                    obj.hideDelay = hint.hideDelay;
                    obj.title = hint.title;
                    obj.content = hint.content;
                    obj.closeBehavior = hint.closeBehavior || "auto";
                    obj.windowCollisionDetection = "fit";

                    if (isFunction(title)) {
                        obj.title = function () {
                            return self._getTooltipText(title, this.target);
                        };
                    }

                    if (isFunction(content)) {
                        obj.content = function () {
                            return self._getTooltipText(content, this.target);
                        };
                    }

                    obj.beforeShowing = function () {
                        self._onBeforeTooltipShowing(this);
                    };
                    tooltip.setOptions(obj);
                }
            };

            wijchartcore.prototype._fotmatTooltip = function (val) {
                var self = this;
                if (self._isDate(val)) {
                    return Globalize.format(val, "f", self._getCulture());
                } else if (!isNaN(val)) {
                    return Globalize.format(parseFloat(val), "n", self._getCulture());
                } else {
                    return val;
                }
            };

            wijchartcore.prototype._setDefaultTooltipText = function (data) {
                var label = data.label;
                if (data.lineSeries && data.lineSeries.label) {
                    label = data.lineSeries.label;
                }
                return label + ":" + this._fotmatTooltip(data.y);
            };

            wijchartcore.prototype._paintTooltip = function () {
                var self = this, o = self.options, hint = o.hint, hintEnable = !self._isDisabled() && hint.enable, hintEx = hint, title, content, isFunction = $.isFunction;

                if (hintEnable && !self.tooltip) {
                    hintEx = $.extend(true, {}, hint, {});
                    title = hint.title;
                    content = hint.content;

                    // set default hint.
                    if (!content) {
                        content = hint.content = function () {
                            var label;
                            if ($.isArray(this)) {
                                var str = "";
                                $.each(this, function (i, data) {
                                    str += self._setDefaultTooltipText(data) + "\n";
                                });
                                return str;
                            } else {
                                return self._setDefaultTooltipText(this);
                            }
                        };
                    }

                    if (isFunction(title)) {
                        hintEx.title = function () {
                            return self._getTooltipText(title, this.target);
                        };
                    }

                    if (isFunction(content)) {
                        hintEx.content = function () {
                            return self._getTooltipText(content, this.target);
                        };
                    }

                    hintEx.beforeShowing = function () {
                        self._onBeforeTooltipShowing(this);
                    };

                    self.tooltip = new ChartTooltip(self.canvas, null, hintEx);
                }
            };

            wijchartcore.prototype._getTooltipText = function (fmt, target) {
                var dataObj = $(target.node).data("wijchartDataObj"), obj = {
                    data: dataObj,
                    label: dataObj.label,
                    x: dataObj.x,
                    y: dataObj.y,
                    target: target,
                    fmt: fmt
                };
                return $.proxy(fmt, obj)();
            };

            wijchartcore.prototype._onBeforeTooltipShowing = function (tooltip) {
                var target = tooltip.target, hintStyle = this.options.hint.style;

                if (target) {
                    tooltip.options.style.stroke = hintStyle.stroke || target.attrs.stroke || target.attrs.fill;
                }
            };

            wijchartcore.prototype._paintChartArea = function () {
                var self = this, o = self.options, axisOption = o.axis, axisTextOffset = 2, xTextBounds = null, yTextBounds = null, extremeValue = {}, maxtries = 5, offsetX = 0, offsetY = 0, isMultiYAxis = $.isArray(axisOption.y), yAxisCount = 0, yIdx, yaxisOpt, key, xOrigin, yOrigin;

                var xAxisInfo, yAxisInfoSingle, yAxisInfo;

                self._applyMargins();

                self.isMultiYAxis = isMultiYAxis;

                if (self._isSeriesListDataEmpty()) {
                    return;
                }

                if (isMultiYAxis) {
                    $.each(axisOption.y, function (i, yaxis) {
                        axisOption.y[i] = $.extend(true, new wijchartcore_options().axis.y, yaxis);
                    });
                }

                if (self._hasAxes()) {
                    // Restore from cache.
                    if (self.innerState.axisInfo) {
                        self.axisInfo = self.innerState.axisInfo;
                        self.canvasBounds = self.innerState.canvasBounds;
                    } else {
                        xTextBounds = self._applyAxisText(axisOption.x, {});

                        xAxisInfo = {
                            id: "x",
                            tprec: 0,
                            isTime: false,
                            height: 0,
                            offset: 0,
                            vOffset: 0,
                            max: 0,
                            min: 0,
                            originalMax: 0,
                            originalMin: 0,
                            majorTickRect: null,
                            minorTickRect: null,
                            annoFormatString: null,
                            textBounds: xTextBounds,
                            axisTextOffset: axisTextOffset,
                            autoMax: true,
                            autoMin: true,
                            autoMajor: true,
                            autoMinor: true,
                            annoMethod: axisOption.x.annoMethod,
                            valueLabels: axisOption.x.valueLabels || [],
                            bounds: null
                        };

                        yAxisInfo = new Array(); // typed array of chart_axisInfo

                        self.axisInfo = {
                            x: xAxisInfo,
                            y: yAxisInfo
                        };

                        self.axisCompass[axisOption.x.compass] = true;

                        if (isMultiYAxis) {
                            $.each(axisOption.y, function (i, axisY) {
                                yTextBounds = self._applyAxisText(axisY, {});

                                yAxisInfoSingle = {
                                    id: "y" + i,
                                    height: 0,
                                    tprec: 0,
                                    isTime: false,
                                    offset: 0,
                                    vOffset: 0,
                                    max: 0,
                                    min: 0,
                                    originalMax: 0,
                                    originalMin: 0,
                                    majorTickRect: null,
                                    minorTickRect: null,
                                    annoFormatString: null,
                                    textBounds: yTextBounds,
                                    axisTextOffset: axisTextOffset,
                                    autoMax: true,
                                    autoMin: true,
                                    autoMajor: true,
                                    autoMinor: true,
                                    annoMethod: axisY.annoMethod,
                                    valueLabels: axisY.valueLabels || [],
                                    bounds: null
                                };

                                self.axisInfo.y[i.toString()] = yAxisInfoSingle;

                                if (!self.axisCompass[axisY.compass]) {
                                    self.axisCompass[axisY.compass] = true;
                                }
                            });
                        } else {
                            yTextBounds = self._applyAxisText(axisOption.y, {});
                            self.axisInfo.y["0"] = {
                                id: "y",
                                tprec: 0,
                                isTime: false,
                                offset: 0,
                                vOffset: 0,
                                max: 0,
                                min: 0,
                                originalMax: 0,
                                originalMin: 0,
                                majorTickRect: null,
                                minorTickRect: null,
                                annoFormatString: null,
                                textBounds: yTextBounds,
                                axisTextOffset: axisTextOffset,
                                autoMax: true,
                                autoMin: true,
                                autoMajor: true,
                                autoMinor: true,
                                annoMethod: axisOption.y.annoMethod,
                                valueLabels: axisOption.y.valueLabels || []
                            };

                            if (!self.axisCompass[axisOption.y.compass]) {
                                self.axisCompass[axisOption.y.compass] = true;
                            }
                        }

                        self._getSeriesGroup(isMultiYAxis);
                        extremeValue = self._getDataExtreme(isMultiYAxis);
                        self.extremeValue = extremeValue;

                        // handle x axis.
                        if (axisOption.x.autoMin && self.axisInfo.x.autoMin) {
                            axisOption.x.min = extremeValue.txn;
                            xOrigin = axisOption.x.origin;

                            // If "min" is not set by user and "origin" is set,
                            // Compare the "origin" and the extreme value,
                            // use the less one to ensure the axis visible
                            if (!(xOrigin === null || typeof xOrigin === "undefined") && (!self.axisInfo.x.isTime) && xOrigin < axisOption.x.min) {
                                axisOption.x.min = xOrigin;
                            }
                        } else if (axisOption.x.min && self._isDate(axisOption.x.min)) {
                            // if is date time, convert to number.
                            axisOption.x.min = $.toOADate(axisOption.x.min);
                        }
                        if (axisOption.x.autoMax && self.axisInfo.x.autoMax) {
                            axisOption.x.max = extremeValue.txx;
                        } else if (axisOption.x.max && self._isDate(axisOption.x.max)) {
                            // if is date time, convert to number.
                            axisOption.x.max = $.toOADate(axisOption.x.max);
                        }

                        $.each(extremeValue.y, function (key, exval) {
                            yAxisCount++;
                        });

                        for (yIdx = 0; yIdx < (axisOption.y.length || 1); yIdx++) {
                            yaxisOpt = axisOption.y[yIdx] || axisOption.y;
                            key = yIdx.toString();
                            if (yaxisOpt.autoMin && self.axisInfo.y[key].autoMin && extremeValue.y[key]) {
                                yaxisOpt.min = extremeValue.y[key].tyn;
                                yOrigin = yaxisOpt.origin;
                                if (!(yOrigin === null || typeof yOrigin === "undefined") && (!self.axisInfo.y[key].isTime) && yOrigin < yaxisOpt.min) {
                                    yaxisOpt.min = yOrigin;
                                }
                            } else if (yaxisOpt.min && self._isDate(yaxisOpt.min)) {
                                // if is date time, convert to number.
                                yaxisOpt.min = $.toOADate(yaxisOpt.min);
                            }

                            if (yaxisOpt.autoMax && self.axisInfo.y[key].autoMax && extremeValue.y[key]) {
                                yaxisOpt.max = extremeValue.y[key].tyx || 0;
                            } else if (yaxisOpt.max && self._isDate(yaxisOpt.max)) {
                                // if is date time, convert to number.
                                yaxisOpt.max = $.toOADate(yaxisOpt.max);
                            }

                            do {
                                offsetY = self._autoPosition(self.axisInfo, axisOption, "y", key);
                                offsetX = self._autoPosition(self.axisInfo, axisOption, "x", key);

                                if (offsetY === self.axisInfo.y[key].offset && offsetX === self.axisInfo.x.offset) {
                                    maxtries = 0;
                                    break;
                                }
                                if (!isNaN(offsetX) && !isNaN(offsetY)) {
                                    if (offsetY !== self.axisInfo.y[key].offset && offsetY !== 0) {
                                        self.axisInfo.y[key].offset = offsetY;
                                        self.axisInfo.y[key].vOffset = offsetX;
                                    }
                                    if (offsetX !== self.axisInfo.x.offset && offsetX !== 0) {
                                        self.axisInfo.x.offset = offsetX;
                                        self.axisInfo.x.vOffset = offsetY;
                                    }
                                }
                                maxtries--;
                            } while(maxtries > 0);
                        }

                        self._adjustPlotArea(axisOption.x, self.axisInfo.x);
                        self._adjustPlotArea(axisOption.y, self.axisInfo.y, true);

                        self.innerState.axisInfo = self.axisInfo;
                        self.innerState.canvasBounds = self.canvasBounds;
                    }
                    self._paintAxes();
                    self._paintPlotArea();
                } else {
                    self._paintPlotArea();
                }
            };

            wijchartcore.prototype._getSeriesGroup = function (isMultiYAxis) {
                var self = this, o = self.options, group = {};

                $.each(o.seriesList, function (i, serie) {
                    if (serie.yAxis && isMultiYAxis) {
                        if (group[serie.yAxis.toString()]) {
                            group[serie.yAxis.toString()].push(serie);
                        } else {
                            group[serie.yAxis.toString()] = [serie];
                        }
                    } else {
                        if (group["0"]) {
                            group["0"].push(serie);
                        } else {
                            group["0"] = [serie];
                        }
                    }
                });
                self.seriesGroup = group;
            };

            wijchartcore.prototype._adjustPlotArea = function (axisOptions, axisInfo, isYAxis) {
                var canvasBounds = this.canvasBounds, maxKey, maxOffsets = {
                    east: Number.MIN_VALUE,
                    west: Number.MIN_VALUE,
                    south: Number.MIN_VALUE,
                    north: Number.MIN_VALUE
                };

                if (isYAxis) {
                    $.each(axisInfo, function (key, axisInf) {
                        maxKey = key;
                    });
                    $.each(axisInfo, function (key, axisInf) {
                        var opt = axisOptions[key] || axisOptions, compass = opt.compass;
                        opt.max = axisInf.max;
                        opt.min = axisInf.min;

                        switch (compass) {
                            case "north":
                                maxOffsets.north = Math.max(axisInf.offset, maxOffsets.north);
                                break;
                            case "south":
                                maxOffsets.south = Math.max(axisInf.offset, maxOffsets.south);
                                break;
                            case "east":
                                maxOffsets.east = Math.max(axisInf.offset, maxOffsets.east);
                                break;
                            case "west":
                                maxOffsets.west = Math.max(axisInf.offset, maxOffsets.west);

                                break;
                        }
                    });

                    if (maxOffsets.north !== Number.MIN_VALUE) {
                        canvasBounds.startY += maxOffsets.north;
                    }

                    if (maxOffsets.south !== Number.MIN_VALUE) {
                        canvasBounds.endY -= maxOffsets.south;
                    }

                    if (maxOffsets.east !== Number.MIN_VALUE) {
                        canvasBounds.endX -= maxOffsets.east;
                    }

                    if (maxOffsets.west !== Number.MIN_VALUE) {
                        canvasBounds.startX += maxOffsets.west;
                    }
                } else {
                    axisOptions.max = axisInfo.max;
                    axisOptions.min = axisInfo.min;

                    switch (axisOptions.compass) {
                        case "north":
                            canvasBounds.startY += axisInfo.offset;
                            break;
                        case "south":
                            canvasBounds.endY -= axisInfo.offset;
                            break;
                        case "east":
                            canvasBounds.endX -= axisInfo.offset;
                            break;
                        case "west":
                            canvasBounds.startX += axisInfo.offset;
                            break;
                    }
                }
            };

            wijchartcore.prototype._autoPosition = function (axisInfo, axisOptions, dir, key) {
                // this._adjustCartesianCompass();
                // base._autoPosition();
                return this._autoPositionCartesianAxis(axisInfo, axisOptions, dir, key);
            };

            wijchartcore.prototype._autoPositionCartesianAxis = function (axisInfo, axisOptions, dir, key) {
                var self = this, extent = null, innerAxisInfo, innerAxisOptions, oppositeAxisInfo, oppositeAxisOptions, compass, origin, max, min, lastAxisOffset = self.lastAxisOffset || {}, offset, lastOffset;

                if (dir === "y") {
                    innerAxisInfo = axisInfo.y[key];
                    innerAxisOptions = axisOptions.y[key] || axisOptions.y;
                    oppositeAxisOptions = axisOptions.x;
                    oppositeAxisInfo = axisInfo.x;
                } else {
                    innerAxisInfo = axisInfo.x;
                    innerAxisOptions = axisOptions.x;
                    oppositeAxisInfo = axisInfo.y[key];
                    oppositeAxisOptions = axisOptions.y[key] || axisOptions.y;
                }
                compass = innerAxisOptions.compass;
                origin = oppositeAxisOptions.origin;
                max = oppositeAxisInfo.max;
                min = oppositeAxisInfo.min;

                if (origin !== null && self._isDate(origin)) {
                    origin = $.toOADate(origin);
                }

                self._calculateParameters(innerAxisInfo, innerAxisOptions);
                extent = self._getMaxExtents(innerAxisInfo, innerAxisOptions);
                switch (compass) {
                    case "north":
                    case "south":
                        offset = extent.height;
                        innerAxisInfo.maxExtent = offset;

                        break;
                    case "east":
                    case "west":
                        offset = extent.width;
                        innerAxisInfo.maxExtent = offset;

                        break;
                }
                if (dir === "y" && lastAxisOffset[compass]) {
                    $.each(lastAxisOffset[compass], function (k, offsetObj) {
                        if (k !== key) {
                            lastOffset = offsetObj;
                        }
                    });
                    if (lastOffset && !innerAxisInfo.isPartAxis) {
                        innerAxisInfo.preStartOffset = lastOffset;
                        offset += (lastOffset);
                    }
                }
                if (dir === "y") {
                    if (lastAxisOffset[compass] === undefined) {
                        lastAxisOffset[compass] = {};
                    }

                    lastAxisOffset[compass][key] = offset + self._getAxisLabelBox(innerAxisOptions).width;
                    self.lastAxisOffset = lastAxisOffset;
                }

                return offset;
            };

            wijchartcore.prototype._getAxisLabelBox = function (axisOption) {
                var self = this, o = self.options, text = axisOption.text, marginTop = 0, marginRight = 0, marginLeft = 0, marginBottom = 0, textElement, bbox, isVertical = self._isVertical(axisOption.compass), textStyle = $.extend(true, {}, o.textStyle, axisOption.textStyle);

                if (textStyle["margin-top"]) {
                    marginTop = parseFloat(textStyle["margin-top"]);
                }
                if (textStyle["margin-left"]) {
                    marginLeft = parseFloat(textStyle["margin-left"]);
                }
                if (textStyle["margin-right"]) {
                    marginRight = parseFloat(textStyle["margin-right"]);
                }
                if (textStyle["margin-bottom"]) {
                    marginBottom = parseFloat(textStyle["margin-bottom"]);
                }
                textElement = self._text(0, 0, text);
                textElement.attr(textStyle);
                if (isVertical) {
                    textElement.transform("...R-90");
                }
                bbox = textElement.wijGetBBox();
                textElement.wijRemove();
                textElement = null;
                return {
                    width: bbox.width + marginLeft + marginRight,
                    height: bbox.height + marginBottom + marginTop
                };
            };

            wijchartcore.prototype._getMaxExtents = function (axisInfo, axisOptions, axisRect) {
                var self = this, o = self.options, majorTickValues = null, maxExtent = {
                    width: 0,
                    height: 0
                }, min = axisInfo.min, max = axisInfo.max, isTime = axisInfo.isTime, formatString = axisOptions.annoFormatString, is100pc = o.is100Percent, index = 0, compass = axisOptions.compass, labels = axisOptions.labels, textStyle, hasDefaultRotation = false, canvasBounds = axisInfo.bounds || self.canvasBounds, width, transform;

                axisInfo.majorTickRect = self._getTickRect(axisInfo, axisOptions, true, true, axisRect);
                axisInfo.minorTickRect = self._getTickRect(axisInfo, axisOptions, false, true, axisRect);
                majorTickValues = self._getMajorTickValues(axisInfo, axisOptions);

                //if (axisInfo.id === "x") {
                //	majorTickValues = this._adjustTickValuesForCandlestickChart(majorTickValues);
                //}
                if (!axisOptions.textVisible) {
                    return maxExtent;
                }
                if (!formatString || formatString.length === 0) {
                    formatString = axisInfo.annoFormatString;
                }

                textStyle = $.extend(true, {}, o.textStyle, axisOptions.textStyle, labels.style);
                transform = textStyle.transform;

                //why use the $.each for check the transform string?
                //maybe in the older Raphael, the transform is an array.
                // now just use update it like this.
                hasDefaultRotation = transform && /r/i.test(transform);

                //if (transform && transform.length) {
                //	$.each(transform, function (i, t) {
                //		if (t[0].toLowerCase() === "r") {
                //			hasDefaultRotation = true;
                //			return false;
                //		}
                //	});
                //}
                // hasDefaultRotation = typeof (textStyle.rotation) !== "undefined";
                textStyle = $.extend(true, textStyle, axisInfo.textStyle);
                width = canvasBounds.endX - canvasBounds.startX - axisInfo.vOffset - axisInfo.axisTextOffset;
                if (majorTickValues && majorTickValues.length) {
                    width = width / (majorTickValues.length - 1);
                    $.each(majorTickValues, function (idx, mtv) {
                        var txt, size, txtClone;

                        if (mtv < min || mtv > max) {
                            return true;
                        }

                        //if (axisOptions.annoMethod === "valueLabels") {
                        if (axisInfo.annoMethod === "valueLabels") {
                            if (mtv < 0) {
                                return true;
                            }

                            //if (index >= axisOptions.valueLabels.length) {
                            if (index >= axisInfo.valueLabels.length) {
                                return false;
                            }

                            //// mtv = axisOptions.valueLabels[index].text;
                            //mtv = axisOptions.valueLabels[index];
                            mtv = axisInfo.valueLabels[index];
                            if (mtv.text) {
                                mtv = mtv.text;
                            } else if (typeof mtv.value !== "undefined") {
                                mtv = mtv.value;
                                if (formatString && formatString.length) {
                                    // mtv = $.format(mtv, formatString);
                                    mtv = Globalize.format(mtv, formatString, self._getCulture());
                                }
                            }
                        } else if (axisInfo.annoMethod === "values") {
                            //} else if (axisOptions.annoMethod === "values") {
                            //if (axisInfo.id === "x") {
                            //	mtv = self._getXTickText(mtv);
                            //}
                            if (formatString && formatString.length) {
                                if (isTime) {
                                    mtv = $.fromOADate(mtv);
                                }

                                // mtv = $.format(mtv, formatString);
                                mtv = Globalize.format(mtv, formatString, self._getCulture());
                            } else if (is100pc && axisInfo.id === "y") {
                                // mtv = $.format(mtv, "p0");
                                mtv = Globalize.format(mtv, "p0", self._getCulture());
                            }
                        }

                        if (labels.width) {
                            txt = self.canvas.wrapText(-100, -100, mtv, labels.width, labels.textAlign, textStyle);
                        } else {
                            txt = self._text(-100, -100, mtv).attr(textStyle);
                        }

                        size = txt.wijGetBBox();

                        if (!self._isVertical(compass) && !hasDefaultRotation && axisInfo.annoMethod === "valueLabels") {
                            //axisOptions.annoMethod === "valueLabels") {
                            if (size.width > width) {
                                txt.attr({ transform: "r-45" });
                                size = txt.wijGetBBox();

                                /*
                                * if (!txt.attr().rotation) { txt.attr({ rotation:
                                * -45 }); textStyle.rotation = -45;
                                * axisInfo.textStyle = { rotation: -45 }; size =
                                * txt.wijGetBBox(); }
                                */
                                if (idx === 0) {
                                    textStyle.transform = "r-45";
                                    axisInfo.textStyle = {
                                        transform: "r-45"
                                    };
                                    txtClone = txt.clone();
                                    txtClone.attr({ transform: "r0" });
                                    size = txtClone.wijGetBBox();
                                    if (Math.sqrt(2) * size.height > width) {
                                        txt.attr({ transform: "r-90" });

                                        // textStyle.transform.push(["r", -90]);
                                        textStyle.transform = "r-90";
                                        axisInfo.textStyle = {
                                            transform: "r-90"
                                        };
                                    }
                                    txtClone.wijRemove();
                                    txtClone = null;
                                    size = txt.wijGetBBox();
                                }
                            }
                            /*
                            * if (idx === 0 && txt.attr().rotation &&
                            * txt.attr().rotation === -45) { txtClone =
                            * txt.clone(); txtClone.attr({ rotation: 0 }); size =
                            * txtClone.wijGetBBox(); if (Math.sqrt(2) * size.height >
                            * width) { txt.attr({ rotation: -90 });
                            * textStyle.rotation = -90; axisInfo.textStyle = {
                            * rotation: -90 }; } txtClone.wijRemove(); size =
                            * txt.wijGetBBox(); }
                            */
                        }
                        txt.wijRemove();
                        txt = null;
                        if (size.width > maxExtent.width) {
                            maxExtent.width = size.width;
                        }

                        if (size.height > maxExtent.height) {
                            maxExtent.height = size.height;
                        }

                        index++;
                    });
                }
                if (maxExtent.width < labels.width) {
                    maxExtent.width = labels.width;
                }

                axisInfo.labelWidth = maxExtent.width;
                return maxExtent;
            };

            wijchartcore.prototype._getMajorTickValues = function (axisInfo, axisOptions) {
                var rc = [], autoTick = axisOptions.autoMajor, unitTick = axisOptions.unitMajor, max, min, valueLabels = axisInfo.valueLabels;
                if (valueLabels && valueLabels.length > 0) {
                    $.each(valueLabels, function (idx, valueLabel) {
                        if (typeof valueLabel.text !== "undefined" || typeof valueLabel.value !== "undefined") {
                            return false;
                        }
                        if (typeof valueLabel === "string") {
                            valueLabels[idx] = {
                                text: valueLabel,
                                gridLine: false
                            };
                        } else {
                            valueLabels[idx] = {
                                value: valueLabel,
                                gridLine: false
                            };
                        }
                    });
                }

                //if (axisOptions.annoMethod === "valueLabels" &&
                if (axisInfo.annoMethod === "valueLabels" && valueLabels && valueLabels.length > 0 && typeof valueLabels[0].value !== "undefined") {
                    rc = this._getSortedDataValues(axisInfo, axisOptions);
                    return rc;
                }
                if (axisInfo.id === "x") {
                    max = autoTick ? axisInfo.max : axisInfo.originalMax;
                    min = autoTick ? axisInfo.min : axisInfo.originalMin;
                } else {
                    max = axisInfo.max;
                    min = axisInfo.min;
                }
                rc = this._getTickValues(max, min, unitTick, axisInfo.tprec, !axisInfo.isTime, autoTick);
                return rc;
            };

            wijchartcore.prototype._getSortedDataValues = function (axisInfo, axisOptions) {
                var self = this, rc = [], valueLabels = axisInfo.valueLabels;

                //valueLabels = axisOptions.valueLabels;
                $.each(valueLabels, function (idx, label) {
                    var val = label.value;
                    if (self._isDate(val)) {
                        rc.push($.toOADate(val));
                    } else if (typeof val === 'number') {
                        rc.push(val);
                    } else {
                        rc.push(idx);
                    }
                    // if (self._isDate(label)) {
                    // rc.push($.toOADate(label));
                    // } else if (typeof label === 'number') {
                    // rc.push(label);
                    // } else {
                    // rc.push(idx);
                    // }
                });

                // TODO: ignore blank labels.
                return rc;
            };

            wijchartcore.prototype._getMinorTickValues = function (axisInfo, axisOptions) {
                var rc = [], autoTick = axisOptions.autoMinor, unitTick = axisOptions.unitMinor, max, min;

                if (axisInfo.id === "x") {
                    max = autoTick ? axisInfo.max : axisInfo.originalMax;
                    min = autoTick ? axisInfo.min : axisInfo.originalMin;
                } else {
                    max = axisInfo.max;
                    min = axisInfo.min;
                }
                rc = this._getTickValues(max, min, unitTick, axisInfo.tprec, !axisInfo.isTime, autoTick);
                return rc;
            };

            wijchartcore.prototype._getTickValues = function (smax, smin, unit, tickprec, round, autoTick) {
                var self = this, vals = [], value, sminOriginal = smin, smaxOriginal = smax, i = 0, xs = 0, imax = 0, imin = 0, n = 0, smin2 = 0;

                try  {
                    if (unit === 0) {
                        vals = [smax, smin];
                    } else {
                        if (autoTick) {
                            if (tickprec + 1 < 0) {
                                tickprec = -1;
                            } else if (tickprec + 1 > 15) {
                                tickprec = 14;
                            }
                            smin2 = $.round(ChartDataUtil.signedCeiling(smin / unit) * unit, tickprec + 1);
                            if (smin2 < smax) {
                                smin = smin2;
                            }
                            imax = parseInt($.round(smax / unit, 5).toString(), 10);
                            imin = parseInt($.round(smin / unit, 5).toString(), 10);
                            n = parseInt((imax - imin + 1).toString(), 10);
                            if (n > 1) {
                                xs = imin * unit;
                                if (xs < smin) {
                                    n--;
                                    smin += unit;
                                }
                                xs = smin + (n - 1) * unit;
                                if (xs > smax) {
                                    n--;
                                }
                            }
                            if (n < 1) {
                                n = 2;
                                smin = sminOriginal;
                                unit = smax - smin;
                            }
                        } else {
                            n = parseInt(((smax - smin) / unit + 1).toString(), 10);
                            if (n > 1) {
                                xs = smin + (n - 1) * unit;
                                if (xs > smax) {
                                    n--;
                                }
                            }
                            if (n < 1) {
                                n = 2;
                                unit = smax - smin;
                            }
                        }

                        for (i = 0; i < n; i++) {
                            if (round) {
                                // vals[i] = $.round(smin + i * unit, tickprec + 1);
                                if (autoTick) {
                                    value = $.round(smin + i * unit, tickprec + 1);
                                } else {
                                    value = smin + i * unit;
                                }
                            } else {
                                value = smin + i * unit;
                            }
                            if (value <= smaxOriginal && value >= sminOriginal) {
                                vals.push(value);
                            }
                        }
                    }
                } catch (error) {
                }

                return vals;
            };

            // to do
            wijchartcore.prototype._getTickRect = function (axisInfo, axisOptions, isMajor, inAxisRect, axisRect) {
                var compass = axisOptions.compass, sizeFactor = 0, tick = null, majorSizeFactor = 3, minorSizeFactor = 2, thickness = 2, majorFactor = axisOptions.tickMajor.factor, minorFactor = axisOptions.tickMinor.factor, r = {
                    x: 0,
                    y: 0,
                    width: 0,
                    height: 0
                };
                if (isMajor) {
                    tick = axisOptions.tickMajor.position;
                    majorFactor = majorFactor > 0 ? majorFactor : 1;
                    sizeFactor = (majorSizeFactor * majorFactor);
                } else {
                    tick = axisOptions.tickMinor.position;
                    minorFactor = minorFactor > 0 ? minorFactor : 1;
                    sizeFactor = (minorSizeFactor * minorFactor);
                }
                if (tick === "none" || (tick === "inside" && inAxisRect)) {
                    sizeFactor = 0;
                }

                // if(isVertical) {
                if (compass === "east" || compass === "west") {
                    r = {
                        x: 0,
                        y: -1,
                        width: sizeFactor * thickness,
                        height: thickness
                    };
                    if ((compass === "east" && (tick === "outside" || (tick === "cross" && inAxisRect))) || (compass === "west" && tick === "inside")) {
                        // r.x = axisRect.x;
                        // if(inAxisRect) {
                        // r.x += axisRect.width;
                        // }
                        // else {
                        // r.width += axisRect.width;
                        // }
                        r.width += 2; // default value of axisRect is 2.
                    } else {
                        // r.x = axisRect.x - sizeFactor * thickness;
                        if (!inAxisRect) {
                            if (tick === "cross") {
                                r.width <<= 1;
                            }

                            // r.width += axisRect.width;
                            r.width += 2;
                        }
                    }
                } else {
                    r = {
                        x: -1,
                        y: 0,
                        width: thickness,
                        height: sizeFactor * thickness
                    };
                    if ((compass === "south" && (tick === "outside" || (tick === "corss" && inAxisRect))) || (compass === "north" && tick === "inside")) {
                        // r.y = axisRect.y;
                        // if(inAxisRect) {
                        // r.y += axisRect.height;
                        // }
                        // else {
                        // r.height += axisRect.height;
                        // }
                        r.height += 2;
                    } else {
                        // r.y = axisRect.y - sizeFactor * thickness;
                        if (!inAxisRect) {
                            if (tick === "cross") {
                                r.height <<= 1;
                            }

                            // r.height += axisRect.height;
                            r.height += 2;
                        }
                    }
                }
                return r;
            };

            wijchartcore.prototype._applyMargins = function () {
                var self = this, o = self.options, canvasBounds = self.canvasBounds;

                canvasBounds.startX += o.marginLeft;
                canvasBounds.endX -= o.marginRight;
                canvasBounds.startY += o.marginTop;
                canvasBounds.endY -= o.marginBottom;
            };

            wijchartcore.prototype._paintAxes = function () {
                // paint x axis
                var self = this, axis = self.options.axis, axisInfo = self.axisInfo, ox = axis.x, oy = axis.y, x = axisInfo.x, y = axisInfo.y, axisElements, movingElements;

                axisElements = self._paintChartAxis(ox, x, self.chartXAxis);
                if (!self.chartXAxis) {
                    self.chartXAxis = axisElements.axisRenderer;
                }
                movingElements = axisElements.movingElements;

                $.each(y, function (key, yaxis) {
                    var opt = oy[key] || oy;
                    if (opt.origin !== null) {
                        self._translateAxisIfNeeded(movingElements, ox.compass, opt.origin, opt.compass, yaxis.max, yaxis.min);
                    }
                });

                //			if (oy.origin !== null) {
                //				self._translateAxisIfNeeded(axisElements, ox.compass,
                //					oy.origin, oy.compass, y.max, y.min);
                //			}
                $.each(y, function (key, yaxis) {
                    var opt = oy[key] || oy;
                    if (!self.chartYAxis) {
                        self.chartYAxis = [];
                    }

                    axisElements = self._paintChartAxis(opt, yaxis, self.chartYAxis[key]);
                    if (!self.chartYAxis[key]) {
                        self.chartYAxis[key] = axisElements.axisRenderer;
                    }
                    movingElements = axisElements.movingElements;

                    if (ox.origin !== null) {
                        self._translateAxisIfNeeded(movingElements, opt.compass, ox.origin, ox.compass, x.max, x.min);
                    }
                });
            };

            wijchartcore.prototype._getChartAxisRenderOptions = function (axisOption, axisInfo) {
                var self = this, o = self.options, ai = axisInfo, ao = axisOption, compass = ao.compass, isVertical = compass === "east" || compass === "west", formatString = ao.annoFormatString, xAxisRenderOptions;

                if (!formatString || formatString.length === 0) {
                    formatString = ai.annoFormatString;
                }

                xAxisRenderOptions = {
                    /** base */
                    disableDefaultTextStyle: o.disableDefaultTextStyle,
                    canvasBounds: ai.bounds || self.canvasBounds,
                    /** axis options */
                    axisStyle: ao.style,
                    axisCSS: o.wijCSS.axis,
                    origin: ao.origin,
                    max: ai.max,
                    min: ai.min,
                    originalMax: ai.originalMax,
                    originalMin: ai.originalMin,
                    annoMethod: ai.annoMethod,
                    annoFormatString: formatString,
                    visible: ao.visible,
                    compass: compass,
                    valueLabels: ai.valueLabels,
                    axisMaxLabelSize: ai["maxExtent"],
                    axisOffset: (!isVertical || ai.isPartAxis || !ai.preStartOffset) ? 0 : ai.preStartOffset,
                    /** axis title options */
                    titleAlignment: ao.alignment,
                    titleVisible: ao.textVisible,
                    titleText: ao.text,
                    titleStyle: $.extend(true, {}, o.textStyle, ao.textStyle),
                    titleCSS: o.wijCSS.axisText,
                    /** axis label options */
                    axisLabelOffset: ai.axisTextOffset,
                    labelCSS: o.wijCSS.axisLabel,
                    labelStyle: $.extend(true, {}, o.textStyle, ao.textStyle, ao.labels.style, ai["textStyle"]),
                    labelOptions: {
                        textAlign: ao.labels.textAlign,
                        width: (ao.labels.width ? ai.labelWidth : null)
                    },
                    /** axis tick and grid options */
                    tickCSS: o.wijCSS.axisTick,
                    gridCSS: o.wijCSS.axisGridLine,
                    autoMajor: ao.autoMajor,
                    autoMinor: ao.autoMinor,
                    unitMajor: ao.unitMajor,
                    unitMinor: ao.unitMinor,
                    gridMajor: ao.gridMajor,
                    gridMinor: ao.gridMinor,
                    tickMajor: ao.tickMajor,
                    tickMinor: ao.tickMinor,
                    /** Others */
                    is100Percent: o.is100Percent && ai.id === "y",
                    culture: o.culture,
                    cultureCalendar: o.cultureCalendar,
                    tprec: ai.tprec,
                    isTime: ai.isTime
                };

                return xAxisRenderOptions;
            };

            wijchartcore.prototype._paintChartAxis = function (axisOption, axisInfo, renderer) {
                var self = this, axisMovingElements = [], xAxisRenderOptions, breakLineEle, startX, startY;

                xAxisRenderOptions = self._getChartAxisRenderOptions(axisOption, axisInfo);

                if (!renderer) {
                    renderer = new Axis(self.canvas, xAxisRenderOptions);
                    renderer.render();
                } else {
                    renderer.redraw(xAxisRenderOptions);
                }

                if (renderer.axisMainLineEle) {
                    axisMovingElements.push(renderer.axisMainLineEle);
                }

                $.each(renderer.axisDotGroupList, function (idx, dotGroup) {
                    if (dotGroup.tick) {
                        axisMovingElements.push(dotGroup.tick);
                    }
                    if (dotGroup.label) {
                        axisMovingElements.push(dotGroup.label);
                    }
                });

                if (renderer.axisTitleEle) {
                    axisMovingElements.push(renderer.axisTitleEle);
                }

                if (axisInfo.isPartAxis && !axisInfo.isLastAxis) {
                    startX = renderer.startPoint.x;
                    startY = renderer.startPoint.y;
                    breakLineEle = self.canvas.path(["M", startX.toString(), (startY + axisInfo.vOffset / 2).toString(), "H", (startX + axisInfo.maxExtent * 2).toString()].join());
                    axisMovingElements.push(breakLineEle);
                    if (!self.breakLineEles) {
                        self.breakLineEles = [];
                    }
                    self.breakLineEles.push(breakLineEle);
                }

                return {
                    axisRenderer: renderer,
                    movingElements: axisMovingElements
                };
            };

            wijchartcore.prototype._translateAxisIfNeeded = function (xAxisElements, xCompass, yOrigin, yCompass, yMax, yMin) {
                var self = this, isVertical = yCompass === "west" || yCompass === "east", bounds = self.canvasBounds, origin = yOrigin, offset;

                if (self._isDate(origin)) {
                    origin = $.toOADate(origin);
                }

                if (!isVertical) {
                    if (xCompass === "west") {
                        offset = (origin - yMin) / (yMax - yMin) * (bounds.endX - bounds.startX);
                    } else {
                        offset = (origin - yMax) / (yMax - yMin) * (bounds.endX - bounds.startX);
                    }

                    $.each(xAxisElements, function (idx, element) {
                        // element.translate(offset, 0);
                        element.transform(Raphael.format("...T{0},{1}", offset, 0));
                    });
                } else {
                    if (xCompass === "south") {
                        offset = (yMin - origin) / (yMax - yMin) * (bounds.endY - bounds.startY);
                    } else {
                        offset = (yMax - origin) / (yMax - yMin) * (bounds.endY - bounds.startY);
                    }

                    $.each(xAxisElements, function (idx, element) {
                        // element.translate(0, offset);
                        element.transform(Raphael.format("...T{0},{1}", 0, offset));
                    });
                }
            };

            wijchartcore.prototype._paintAxis = function (axisOptions, axisInfo) {
                var self = this, o = self.options, canvasBounds = axisInfo.bounds || self.canvasBounds, startPoint = {
                    x: 0,
                    y: 0
                }, endPoint = {
                    x: 0,
                    y: 0
                }, compass = axisOptions.compass, thickness = 2, isVertical = true, ax = null, majorTickValues = [], tempMinorTickValues = [], minorTickValues = [], max = axisInfo.max, min = axisInfo.min, unitMajor = axisOptions.unitMajor, unitMinor = axisOptions.unitMinor, tickMajor = axisOptions.tickMajor.position, tickMinor = axisOptions.tickMinor.position, axisSize = axisInfo.maxExtent, tickMajorStyle = axisOptions.tickMajor.style, tickMinorStyle = axisOptions.tickMinor.style, tickRectMajor = axisInfo.majorTickRect, tickRectMinor = axisInfo.minorTickRect, axisTextOffset = axisInfo.axisTextOffset, gridMajor = axisOptions.gridMajor, gridMinor = axisOptions.gridMinor, labels = axisOptions.labels, maxLen = 0, textInfos = [], index = 0, formatString = axisOptions.annoFormatString, textStyle = null, axisElements = [];

                tickRectMajor = self._getTickRect(axisInfo, axisOptions, true, false);
                tickRectMinor = self._getTickRect(axisInfo, axisOptions, false, false);

                if (!formatString || formatString.length === 0) {
                    formatString = axisInfo.annoFormatString;
                }
                majorTickValues = self._getMajorTickValues(axisInfo, axisOptions);

                //if (tickMinor !== "none") {
                tempMinorTickValues = self._getMinorTickValues(axisInfo, axisOptions);
                minorTickValues = self._resetMinorTickValues(tempMinorTickValues, majorTickValues);

                switch (compass) {
                    case "south":
                        startPoint.x = canvasBounds.startX;
                        startPoint.y = canvasBounds.endY;
                        endPoint.x = canvasBounds.endX;
                        endPoint.y = canvasBounds.endY;
                        isVertical = false;
                        break;
                    case "north":
                        startPoint.x = canvasBounds.startX;
                        startPoint.y = canvasBounds.startY - thickness;
                        endPoint.x = canvasBounds.endX;
                        endPoint.y = canvasBounds.startY - thickness;
                        isVertical = false;
                        break;
                    case "east":
                        //startPoint.x = canvasBounds.endX;
                        startPoint.x = canvasBounds.endX - thickness;
                        startPoint.y = canvasBounds.endY;

                        //endPoint.x = canvasBounds.endX;
                        endPoint.x = canvasBounds.endX - thickness;
                        endPoint.y = canvasBounds.startY + self._getOffsetOfAxis(axisOptions);
                        if (axisInfo.preStartOffset) {
                            startPoint.x += axisInfo.preStartOffset;
                            endPoint.x += axisInfo.preStartOffset;
                        }
                        break;
                    case "west":
                        //startPoint.x = canvasBounds.startX - thickness;
                        startPoint.x = canvasBounds.startX;
                        startPoint.y = canvasBounds.endY;

                        //endPoint.x = canvasBounds.startX - thickness;
                        endPoint.x = canvasBounds.startX;
                        endPoint.y = canvasBounds.startY + self._getOffsetOfAxis(axisOptions);
                        if (axisInfo.preStartOffset) {
                            startPoint.x -= axisInfo.preStartOffset;
                            endPoint.x -= axisInfo.preStartOffset;
                        }
                        break;
                }

                if (axisOptions.visible) {
                    ax = self.canvas.line(startPoint.x, startPoint.y, endPoint.x, endPoint.y).attr(axisOptions.style);
                    $.wijraphael.addClass($(ax.node), o.wijCSS.axis);

                    self.axisEles.push(ax);
                    axisElements.push(ax);
                }

                $.each(majorTickValues, function (idx, val) {
                    var text = val, isTime = axisInfo.isTime, is100Percent = o.is100Percent, retInfo, textInfo, vlGridLine = false, vlGridLineStyle = {};

                    if (val < min || val > max) {
                        index++;
                        return true;
                    }

                    if (axisInfo.annoMethod === "valueLabels") {
                        //if (axisOptions.annoMethod === "valueLabels") {
                        // if (val < 0) {
                        // return true;
                        // }
                        //if (index >= axisOptions.valueLabels.length) {
                        if (index >= axisInfo.valueLabels.length) {
                            return false;
                        }

                        //// text = axisOptions.valueLabels[index].text;
                        //text = axisOptions.valueLabels[index];
                        text = axisInfo.valueLabels[index];
                        vlGridLine = text.gridLine;
                        vlGridLineStyle = text.gridLineStyle;
                        if (text.text) {
                            text = text.text;
                        } else if (typeof text.value !== "undefined") {
                            text = text.value;
                            if (formatString && formatString.length) {
                                // text = $.format(text, formatString);
                                text = Globalize.format(text, formatString, self._getCulture());
                            }
                        }
                    } else if (axisInfo.annoMethod === "values") {
                        //} else if (axisOptions.annoMethod === "values") {
                        if (axisInfo.id === "x") {
                            text = self._getXTickText(text);
                        }

                        if (formatString && formatString.length) {
                            if (isTime) {
                                text = $.fromOADate(val);
                            }

                            // text = $.format(text, formatString);
                            text = Globalize.format(text, formatString, self._getCulture());
                        } else if (is100Percent && axisInfo.id === "y") {
                            // text = $.format(val, "p0");
                            text = Globalize.format(val, "p0", self._getCulture());
                        }
                    }

                    /*
                    * //TODO: mixed else { }
                    */
                    textStyle = $.extend(true, {}, o.textStyle, axisOptions.textStyle, labels.style, axisInfo.textStyle);

                    retInfo = self._paintMajorMinor(axisOptions.origin, max, min, val, tickMajor, unitMajor, tickRectMajor, compass, startPoint, endPoint, axisSize, axisTextOffset, tickMajorStyle, text, gridMajor, axisOptions.textVisible, textStyle, labels.textAlign, labels.width ? axisInfo.labelWidth : null, vlGridLine, vlGridLineStyle);

                    if (retInfo) {
                        if (retInfo.elements) {
                            axisElements = axisElements.concat(retInfo.elements);
                        }

                        textInfo = retInfo.textInfo;
                    }

                    if (textInfo) {
                        textInfos.push(textInfo);
                        if (maxLen < textInfo.len) {
                            maxLen = textInfo.len;
                        }
                    }

                    index++;
                });

                if (!labels.width) {
                    $.each(textInfos, function (idx, textInfo) {
                        var textElement = textInfo.text, offset = (textInfo.len - maxLen) / 2;
                        offset = labels.textAlign === "near" ? offset * -1 : offset;

                        if (isVertical) {
                            //textElement.translate(offset, 0);
                            textElement.transform(Raphael.format("...T{0},{1}", offset, 0));
                        } else {
                            //textElement.translate(0, offset);
                            textElement.transform(Raphael.format("...T{0},{1}", 0, offset));
                        }
                    });
                }

                $.each(minorTickValues, function (idx, val) {
                    var retInfo;

                    if (val > min && val < max) {
                        retInfo = self._paintMajorMinor(axisOptions.origin, max, min, val, tickMinor, unitMinor, tickRectMinor, compass, startPoint, endPoint, axisSize, axisTextOffset, tickMinorStyle, null, gridMinor, axisOptions.textVisible, textStyle, labels.textAlign, labels.width ? axisInfo.labelWidth : null);

                        if (retInfo && retInfo.elements) {
                            axisElements = axisElements.concat(retInfo.elements);
                        }
                    }
                });

                if (axisOptions.text && axisOptions.text.length > 0) {
                    axisElements.push(self._paintAxisText(axisOptions, axisInfo));
                }

                if (axisInfo.isPartAxis && !axisInfo.isLastAxis) {
                    axisElements.push(self.canvas.path(["M", startPoint.x.toString(), (startPoint.y + axisInfo.vOffset / 2).toString(), "H", (startPoint.x + axisInfo.maxExtent * 2).toString()].join()));
                }

                return axisElements;
            };

            wijchartcore.prototype._paintAxisText = function (axisOptions, axisInfo) {
                if (!axisOptions.text || axisOptions.text.length === 0) {
                    return;
                }
                var self = this, o = self.options, text = axisOptions.text, compass = axisOptions.compass, align = axisOptions.alignment, canvasBounds = axisInfo.bounds || self.canvasBounds, startX = canvasBounds.startX, startY = canvasBounds.startY, endX = canvasBounds.endX, endY = canvasBounds.endY, x = startX, y = startY, textBounds = axisInfo.textBounds, isVertical = self._isVertical(compass), axisTextOffset = axisInfo.axisTextOffset, tickRectMajor = axisInfo.majorTickRect, tick = axisOptions.tickMajor.position, tickLength = isVertical ? tickRectMajor.width : tickRectMajor.height, textStyle = null, textElement = null, marginTop = 0, marginLeft = 0, marginRight = 0, marginBottom = 0;

                textStyle = $.extend(true, {}, self.options.textStyle, axisOptions.textStyle);
                if (textStyle["margin-top"]) {
                    marginTop = parseFloat(textStyle["margin-top"]);
                }
                if (textStyle["margin-left"]) {
                    marginLeft = parseFloat(textStyle["margin-left"]);
                }
                if (textStyle["margin-right"]) {
                    marginRight = parseFloat(textStyle["margin-right"]);
                }
                if (textStyle["margin-bottom"]) {
                    marginBottom = parseFloat(textStyle["margin-bottom"]);
                }
                if (tick === "cross") {
                    tickLength = tickLength / 2;
                } else if (tick === "inside") {
                    tickLength = 0;
                }

                if (isVertical) {
                    switch (align) {
                        case "near":
                            y = endY - textBounds.width / 2;
                            break;
                        case "center":
                            y = (startY + endY) / 2;
                            break;
                        case "far":
                            y = startY + textBounds.width / 2;
                            break;
                    }

                    if (compass === "west") {
                        x = startX - (axisInfo.offset + axisTextOffset + tickLength + textBounds.height / 2 + marginRight);
                    } else {
                        x = endX + axisInfo.offset + axisTextOffset + tickLength + textBounds.height / 2 + marginLeft;
                    }
                } else {
                    switch (align) {
                        case "near":
                            x = startX + textBounds.width / 2;
                            break;
                        case "center":
                            x = (startX + endX) / 2;
                            break;
                        case "far":
                            x = endX - textBounds.width / 2;
                            break;
                    }

                    if (compass === "north") {
                        y = startY - (axisInfo.offset + axisTextOffset + tickLength + textBounds.height / 2 + marginBottom);
                    } else {
                        y = endY + axisInfo.offset + axisTextOffset + tickLength + textBounds.height / 2 + marginTop;
                    }
                }

                textElement = self._text(x, y, text);
                $.wijraphael.addClass($(textElement.node), o.wijCSS.axisText);
                self.axisEles.push(textElement);
                textElement.attr(textStyle);

                if (isVertical) {
                    // textElement.rotate(-90);
                    textElement.transform("...R-90");
                }

                return textElement;
            };

            wijchartcore.prototype._resetMinorTickValues = function (minorTickValues, majorTickValues) {
                var i = 0, j = 0, minorTickValue = null, majorTickValue = null;
                for (i = minorTickValues.length - 1; i >= 0; i--) {
                    minorTickValue = minorTickValues[i];
                    for (j = majorTickValues.length - 1; j >= 0; j--) {
                        majorTickValue = majorTickValues[j];
                        if (minorTickValue === majorTickValue) {
                            minorTickValues.splice(i, 1);
                        }
                    }
                }

                return minorTickValues;
            };

            wijchartcore.prototype._getXTickText = function (txt) {
                return txt;
            };

            wijchartcore.prototype._adjustTickValuesForCandlestickChart = function (tickValues) {
                return tickValues;
            };

            wijchartcore.prototype._paintMajorMinor = function (origin, max, min, val, tick, unit, tickRect, compass, startPoint, endPoint, axisSize, axisTextOffset, tickStyle, text, grid, textVisible, textStyle, textAlign, labelWidth, vlGridLine, vlGridLineStyle) {
                var self = this, x = startPoint.x, y = startPoint.y, o = self.options, tickX = -1, tickY = -1, isVertical = true, bs = self.canvasBounds, textInfo = null, tickElement = null, pathArr = [], arrPath = [], p = null, style = { "stroke-width": 2 }, txt = { text: null, len: 0 }, textBounds = null, retInfo = {}, majorMinorElements = [], axisCompass = self.axisCompass;

                switch (compass) {
                    case "south":
                        if (tick === "inside") {
                            y -= tickRect.height;
                        } else if (tick === "cross") {
                            y -= tickRect.height / 2;
                        }

                        if (labelWidth) {
                            tickY = y + axisTextOffset + tickRect.height;
                        } else {
                            tickY = y + axisTextOffset + tickRect.height + axisSize / 2;
                        }

                        isVertical = false;
                        break;
                    case "west":
                        if (tick === "outside") {
                            x -= tickRect.width;
                        } else if (tick === "cross") {
                            x -= tickRect.width / 2;
                        }

                        if (labelWidth) {
                            tickX = x - (axisTextOffset + axisSize);
                        } else {
                            tickX = x - (axisTextOffset + axisSize / 2);
                        }
                        break;
                    case "north":
                        if (tick === "outside") {
                            y -= tickRect.height;
                        } else if (tick === "cross") {
                            y -= tickRect.height / 2;
                        }

                        if (labelWidth) {
                            tickY = y - (axisTextOffset + axisSize);
                        } else {
                            tickY = y - (axisTextOffset + axisSize / 2);
                        }
                        isVertical = false;
                        break;
                    case "east":
                        if (tick === "inside") {
                            x -= tickRect.width;
                        } else if (tick === "cross") {
                            x -= tickRect.width / 2;
                        }

                        if (labelWidth) {
                            tickX = x + axisTextOffset + tickRect.width;
                        } else {
                            tickX = x + axisTextOffset + tickRect.width + axisSize / 2;
                        }
                        break;
                }

                if (isVertical) {
                    y += (val - min) / (max - min) * (endPoint.y - startPoint.y);
                    arrPath = ["M", bs.startX, y, "H", bs.endX];
                    if (grid.visible) {
                        //if ((y !== bs.startY && compass === "east") ||
                        //		(y !== bs.endY && compass === "west")) {
                        if ((y !== bs.startY || !axisCompass["north"]) && (y !== bs.endY || !axisCompass["south"]) || origin !== val) {
                            p = self.canvas.path(arrPath.join(" "));
                            $.wijraphael.addClass($(p.node), o.wijCSS.axisGridLine);
                            p.attr(grid.style);
                            self.axisEles.push(p);
                        }
                    }
                    if (vlGridLine) {
                        //if ((y !== bs.startY && compass === "east") ||
                        //		(y !== bs.endY && compass === "west")) {
                        if ((y !== bs.startY || !axisCompass["north"]) && (y !== bs.endY || !axisCompass["south"]) || origin !== val) {
                            p = self.canvas.path(arrPath.join(" "));
                            $.wijraphael.addClass($(p.node), o.wijCSS.axisGridLine);
                            p.attr($.extend(true, {}, grid.style, vlGridLineStyle));
                            self.axisEles.push(p);
                        }
                    }

                    tickY = y;

                    if (tick !== "none") {
                        pathArr = ["M", x, y, "h", tickRect.width];
                        tickStyle["stroke-width"] = tickRect.height;
                    }
                } else {
                    x += (val - min) / (max - min) * (endPoint.x - startPoint.x);
                    arrPath = ["M", x, bs.startY, "V", bs.endY];
                    if (grid.visible) {
                        //if ((x !== bs.startX && compass === "south") ||
                        //		(x !== bs.endX && compass === "north")) {
                        if ((x !== bs.startX || !axisCompass["west"]) && (x !== bs.endX || !axisCompass["east"]) || origin !== val) {
                            p = self.canvas.path(arrPath.join(" "));
                            $.wijraphael.addClass($(p.node), o.wijCSS.axisGridLine);
                            p.attr(grid.style);
                            self.axisEles.push(p);
                        }
                    }
                    if (vlGridLine) {
                        //if ((y !== bs.startY && compass === "south") ||
                        //		(y !== bs.endY && compass === "north")) {
                        if ((x !== bs.startX || !axisCompass["west"]) && (x !== bs.endX || !axisCompass["east"]) || origin !== val) {
                            p = self.canvas.path(arrPath.join(" "));
                            $.wijraphael.addClass($(p.node), o.wijCSS.axisGridLine);
                            p.attr($.extend(true, {}, grid.style, vlGridLineStyle));
                            self.axisEles.push(p);
                        }
                    }

                    if (labelWidth) {
                        tickX = x - labelWidth / 2;
                    } else {
                        tickX = x;
                    }

                    if (tick !== "none") {
                        pathArr = ["M", x, y, "v", tickRect.height];
                        tickStyle["stroke-width"] = tickRect.width;
                    }
                }

                if (tick !== "none") {
                    tickElement = self.canvas.path(pathArr.join(" "));
                    $.wijraphael.addClass($(tickElement.node), o.wijCSS.axisTick);
                    style = $.extend(style, tickStyle);
                    tickElement.attr(style);
                    self.axisEles.push(tickElement);
                    majorMinorElements.push(tickElement);
                }

                if (text !== null && textVisible) {
                    if (labelWidth) {
                        txt = self.canvas.wrapText(tickX, tickY, text.toString(), labelWidth, textAlign, textStyle);
                        $.wijraphael.addClass($(txt.node), o.wijCSS.axisLabel);
                        //if (isVertical) {
                        // txt.translate(0, -txt.getBBox().height / 2);
                        //txt.transform(Raphael.format("...T{0},{1}", 0,
                        //-txt.getBBox().height / 2));
                        //}
                    } else {
                        txt = self._text(tickX, tickY, text.toString());
                        $.wijraphael.addClass($(txt.node), o.wijCSS.axisLabel);
                        txt.attr(textStyle);
                    }

                    self.axisEles.push(txt);
                    majorMinorElements.push(txt);
                    if (!textVisible) {
                        txt.hide();
                    }
                    if (textAlign !== "center") {
                        textBounds = txt.getBBox();
                        textInfo = {
                            text: txt,
                            len: isVertical ? textBounds.width : textBounds.height
                        };
                    }
                }

                retInfo = { textInfo: textInfo, elements: majorMinorElements };

                return retInfo;
            };

            wijchartcore.prototype._paintPlotArea = function () {
            };

            wijchartcore.prototype._paintChartLabels = function () {
                var self = this, chartLabels = self.options.chartLabels;

                if (chartLabels && chartLabels.length) {
                    $.each(chartLabels, function (idx, chartLabel) {
                        var point;

                        chartLabel = $.extend(true, {
                            compass: "east",
                            attachMethod: "coordinate",
                            attachMethodData: {
                                seriesIndex: -1,
                                pointIndex: -1,
                                x: -1,
                                y: -1
                            },
                            offset: 0,
                            visible: false,
                            text: "",
                            connected: false
                        }, chartLabel);

                        if (chartLabel.visible) {
                            point = self._getChartLabelPointPosition(chartLabel);
                            if (typeof (point.x) !== "number" || typeof (point.y) !== "number") {
                                return false;
                            }
                            self._setChartLabel(chartLabel, point);
                        }
                    });
                }
            };

            wijchartcore.prototype._getChartLabelPointPosition = function (chartLabel) {
            };

            wijchartcore.prototype._setChartLabel = function (chartLabel, point, angle, calloutStyle) {
                var self = this, compass = chartLabel.compass, o = self.options, textStyle = $.extend(true, {}, o.textStyle, o.chartLabelStyle), text = self._text(0, 0, chartLabel.text).attr(textStyle), offset = chartLabel.offset, transX = 0, transY = 0, position = null, p = null;

                $.wijraphael.addClass($(text.node), o.wijCSS.labelText);
                self.chartLabelEles.push(text);

                position = self._getCompassTextPosition(compass, text.wijGetBBox(), offset, point, angle);

                if (offset && chartLabel.connected) {
                    p = self.canvas.path("M" + point.x + " " + point.y + "L" + position.endPoint.x + " " + position.endPoint.y);
                    $.wijraphael.addClass($(p.node), o.wijCSS.labelConnect);
                    p.attr(calloutStyle);
                    self.chartLabelEles.push(p);
                }

                transX = position.endPoint.x + position.offsetX;
                transY = position.endPoint.y + position.offsetY;

                // text.translate(transX, transY)
                // .toFront();
                text.transform(Raphael.format("...T{0},{1}", transX, transY)).toFront();
            };

            wijchartcore.prototype._getCompassTextPosition = function (compass, box, offset, point, angle) {
                var offsetX = 0, offsetY = 0, endPoint = { x: 0, y: 0 };

                switch (compass.toLowerCase()) {
                    case "east":
                        angle = 0;
                        break;
                    case "west":
                        angle = 180;
                        break;
                    case "north":
                        angle = 90;
                        break;
                    case "south":
                        angle = 270;
                        break;
                    case "northeast":
                        angle = 45;
                        break;
                    case "northwest":
                        angle = 135;
                        break;
                    case "southeast":
                        angle = 315;
                        break;
                    case "southwest":
                        angle = 225;
                        break;
                }

                if ((angle >= 0 && angle < 45 / 2) || (angle > 675 / 2 && angle < 360)) {
                    offsetX = box.width / 2;
                } else if (angle >= 45 / 2 && angle < 135 / 2) {
                    offsetX = box.width / 2;
                    offsetY = -1 * box.height / 2;
                } else if (angle >= 135 / 2 && angle < 225 / 2) {
                    offsetY = -1 * box.height / 2;
                } else if (angle >= 225 / 2 && angle < 315 / 2) {
                    offsetX = -1 * box.width / 2;
                    offsetY = -1 * box.height / 2;
                } else if (angle >= 315 / 2 && angle < 405 / 2) {
                    offsetX = -1 * box.width / 2;
                } else if (angle >= 405 / 2 && angle < 495 / 2) {
                    offsetX = -1 * box.width / 2;
                    offsetY = box.height / 2;
                } else if (angle >= 495 / 2 && angle < 585 / 2) {
                    offsetY = box.height / 2;
                } else {
                    offsetX = box.width / 2;
                    offsetY = box.height / 2;
                }

                endPoint = $.wijraphael.getPositionByAngle(point.x, point.y, offset, angle);

                return {
                    endPoint: endPoint,
                    offsetX: offsetX,
                    offsetY: offsetY
                };
            };

            wijchartcore.prototype._isTouchEnabled = function () {
                return $.support.isTouchEnabled && $.support.isTouchEnabled();
            };

            wijchartcore.prototype._mouseDown = function (e, args) {
                this._trigger("mouseDown", e, args);
            };

            wijchartcore.prototype._mouseUp = function (e, args) {
                this._trigger("mouseUp", e, args);
            };

            wijchartcore.prototype._mouseOver = function (e, args) {
                this._trigger("mouseOver", e, args);
            };

            wijchartcore.prototype._mouseOut = function (e, args) {
                this._trigger("mouseOut", e, args);
            };

            wijchartcore.prototype._mouseMove = function (e, args) {
                this._trigger("mouseMove", e, args);
            };

            wijchartcore.prototype._click = function (e, args) {
                this._trigger("click", e, args);
            };

            wijchartcore.prototype._mouseMoveInsidePlotArea = function (e, mousePos) {
                var self = this, o = self.options, indicator = o.indicator, canvas = self.canvas, point, bounds, path, offset = 0, tooltipObj = [], horizontal = o.horizontal;

                if (indicator && indicator.visible && this.isPlotAreaMouseDown) {
                    if (horizontal) {
                        point = this._calculatePositionByX(mousePos.top);
                    } else {
                        point = this._calculatePositionByX(mousePos.left);
                    }
                    if (point && this.indicatorLine) {
                        if (point.x !== this.lastIndicatorPosition) {
                            $.each(point.data, function (i, obj) {
                                if (obj.visible) {
                                    tooltipObj.push(obj);
                                }
                            });
                            if (tooltipObj.length > 0) {
                                bounds = self.canvasBounds;
                                if (horizontal) {
                                    this.indicatorLine.transform("T0 " + point.x);
                                } else {
                                    this.indicatorLine.transform("T" + point.x + " 0");
                                }

                                //							if (this.tooltip) {
                                //								this.tooltip.destroy();
                                //								this.tooltip = null;
                                //							}
                                //this.tooltip.hide();
                                //this._paintIndicatorTooltip(tooltipObj);
                                this._setTooltipContent(tooltipObj);

                                if (this.tooltip) {
                                    if (horizontal) {
                                        this.tooltip.showAt({ x: bounds.endX, y: point.x });
                                    } else {
                                        this.tooltip.showAt({ x: point.x, y: bounds.startY });
                                    }
                                }
                                this.lastIndicatorPosition = point.x;
                                self._indicatorLineShowing(tooltipObj);
                                this.lastIndicatorObjects = tooltipObj;
                            }
                        }
                    }
                }
            };

            // return a chart element point which is near the mouse.
            wijchartcore.prototype._calculatePositionByX = function (x) {
                var self = this, xArr = self.pointXs, position, points = self.dataPoints;
                if (xArr && xArr.length > 0) {
                    position = this._calculatePositionByXInternal(x, xArr);
                }
                if (points) {
                    return { x: position, data: points[position.toString()] };
                }
                return null;
            };

            wijchartcore.prototype._calculatePositionByXInternal = function (x, arr) {
                var len = arr.length, half, subArr;
                if (len === 1) {
                    return arr[0];
                } else if (len === 2) {
                    if (Math.abs(x - arr[0]) > Math.abs(x - arr[1])) {
                        return arr[1];
                    } else {
                        return arr[0];
                    }
                } else {
                    half = parseInt((len / 2).toString());
                    if (x > arr[half]) {
                        subArr = arr.slice(half);
                    } else {
                        subArr = arr.slice(0, half + 1);
                    }
                    return this._calculatePositionByXInternal(x, subArr);
                }
            };

            wijchartcore.prototype._mouseMoveOutsidePlotArea = function (e, mousePos) {
                if (this.indicatorLine) {
                    this.indicatorLine.wijRemove();
                    this.indicatorLine = null;
                    if (this.tooltip) {
                        this.tooltip.hide();
                    }
                    this._resetTooltip();
                }
            };

            wijchartcore.prototype._mouseDownInsidePlotArea = function (e, mousePos) {
                this.isPlotAreaMouseDown = true;
                var self = this, o = self.options, indicator = o.indicator, canvas = self.canvas, point, bounds, path, tooltipObj = [], horizontal = o.horizontal;

                if (indicator && indicator.visible && this.isPlotAreaMouseDown) {
                    self._setTooltip();
                    if (horizontal) {
                        point = this._calculatePositionByX(mousePos.top);
                    } else {
                        point = this._calculatePositionByX(mousePos.left);
                    }
                    if (point) {
                        // for each the points, if the element is not visible,
                        // don't show the indicator.
                        $.each(point.data, function (i, obj) {
                            if (obj.visible) {
                                tooltipObj.push(obj);
                            }
                        });
                        if (tooltipObj.length > 0) {
                            bounds = self.canvasBounds;
                            if (horizontal) {
                                path = ["M", bounds.startX, 0, "H", bounds.endX];
                            } else {
                                path = ["M", 0, bounds.startY, "V", bounds.endY];
                            }
                            if (this.indicatorLine) {
                                this.indicatorLine.wijRemove();
                            }
                            this.indicatorLine = canvas.path(path);
                            this.indicatorLine.attr(indicator.style);
                            if (horizontal) {
                                this.indicatorLine.transform("T0 " + point.x);
                            } else {
                                this.indicatorLine.transform("T" + point.x + " 0");
                            }

                            //						if (this.tooltip) {
                            //							this.tooltip.destroy();
                            //							this.tooltip = null;
                            //						}
                            // show tooltip
                            //this.tooltip.hide();
                            this._setTooltipContent(tooltipObj);

                            //this._paintIndicatorTooltip(tooltipObj);
                            if (this.tooltip) {
                                if (horizontal) {
                                    this.tooltip.showAt({ x: bounds.endX, y: point.x });
                                } else {
                                    this.tooltip.showAt({ x: point.x, y: bounds.startY });
                                }
                            }
                            this.lastIndicatorPosition = point.x;
                            self._indicatorLineShowing(tooltipObj);
                            this.lastIndicatorObjects = tooltipObj;
                        }
                    }
                    e.preventDefault();
                }
            };

            wijchartcore.prototype._indicatorLineShowing = function (obj) {
                if (this.lastIndicatorObjects) {
                    this._removeIndicatorStyles(this.lastIndicatorObjects);
                }
            };

            wijchartcore.prototype._removeIndicatorStyles = function (lastIndicatorObjects) {
            };

            wijchartcore.prototype._mouseUpInsidePlotArea = function (e, mousePos) {
                this.isPlotAreaMouseDown = false;
                if (this.indicatorLine) {
                    this.indicatorLine.wijRemove();
                    this.indicatorLine = null;
                    if (this.tooltip) {
                        this.tooltip.hide();
                    }
                    this._resetTooltip();
                }
                if (this.lastIndicatorObjects) {
                    this._removeIndicatorStyles(this.lastIndicatorObjects);
                    this.lastIndicatorObjects = null;
                }
            };

            wijchartcore.prototype._bindLiveEvents = function () {
                //this._bindLegendEvents();
                this._bindCanvasEvents();
                this._bindResizeEvent();
            };

            wijchartcore.prototype._bindResizeEvent = function () {
                var _this = this;
                this.resizeIntent = 250;
                if (this.options.autoResize) {
                    this.chartElement.on("resize." + this.widgetName, function () {
                        clearTimeout(_this.resizeTimer);
                        _this.resizeTimer = setTimeout(function () {
                            _this.redraw();
                        }, _this.resizeIntent);
                    });
                }
            };

            wijchartcore.prototype._unbindResizeEvent = function () {
                this.chartElement.off("resize." + this.widgetName);
            };

            wijchartcore.prototype._bindCanvasEvents = function () {
                var self = this, element = self.chartElement, touchEventPre = "", namespace = "." + this.widgetName;

                // In IE11, the -ms-touch-action changed to touch-action.
                if ($.support.isTouchEnabled && $.support.isTouchEnabled()) {
                    if (window.navigator["pointerEnabled"]) {
                        element.css("touch-action", "none");
                    } else if (window.navigator.msPointerEnabled) {
                        element.css("-ms-touch-action", "none");
                    }
                }

                // if support touch.
                if ($.support.isTouchEnabled && $.support.isTouchEnabled()) {
                    touchEventPre = "wij";
                }
                element.bind(touchEventPre + "mousemove" + namespace, function (e) {
                    var elePos = element.offset(), cBounds = self.canvasBounds, mousePos = {
                        left: (document.compatMode === "CSS1Compat" ? e.pageX : e.clientX) - elePos.left,
                        top: (document.compatMode === "CSS1Compat" ? e.pageY : e.clientY) - elePos.top
                    }, disabled = self._isDisabled();
                    if (disabled || cBounds === undefined) {
                        return;
                    }
                    if (mousePos.left >= cBounds.startX && mousePos.left <= cBounds.endX && mousePos.top >= cBounds.startY && mousePos.top <= cBounds.endY) {
                        self._mouseMoveInsidePlotArea(e, mousePos);
                    }
                });

                // Mousemove event may not catch quick moving,
                // in this condition, bind mouseout event to hide the tooltip.
                element.bind(touchEventPre + "mouseout" + namespace, function (e) {
                    var elePos = element.offset(), cBounds = self.canvasBounds, mousePos = {
                        left: (document.compatMode === "CSS1Compat" ? e.pageX : e.clientX) - elePos.left,
                        top: (document.compatMode === "CSS1Compat" ? e.pageY : e.clientY) - elePos.top
                    }, disabled = self._isDisabled();
                    if (disabled || cBounds === undefined) {
                        return;
                    }
                    if (mousePos.left >= cBounds.startX && mousePos.left <= cBounds.endX && mousePos.top >= cBounds.startY && mousePos.top <= cBounds.endY) {
                        return;
                    } else {
                        self._mouseMoveOutsidePlotArea(e, mousePos);
                    }
                });

                // End comments
                if (self.options.indicator && self.options.indicator.visible) {
                    element.bind(touchEventPre + "mousedown" + namespace, function (e) {
                        var elePos = element.offset(), cBounds = self.canvasBounds, mousePos = {
                            left: (document.compatMode === "CSS1Compat" ? e.pageX : e.clientX) - elePos.left,
                            top: (document.compatMode === "CSS1Compat" ? e.pageY : e.clientY) - elePos.top
                        }, disabled = self._isDisabled();
                        if (disabled || cBounds === undefined) {
                            return;
                        }
                        if (mousePos.left >= cBounds.startX && mousePos.left <= cBounds.endX && mousePos.top >= cBounds.startY && mousePos.top <= cBounds.endY) {
                            self._mouseDownInsidePlotArea(e, mousePos);
                        }
                    }).bind(touchEventPre + "mouseup" + namespace, function (e) {
                        var elePos = element.offset(), cBounds = self.canvasBounds, mousePos = {
                            left: (document.compatMode === "CSS1Compat" ? e.pageX : e.clientX) - elePos.left,
                            top: (document.compatMode === "CSS1Compat" ? e.pageY : e.clientY) - elePos.top
                        }, disabled = self._isDisabled();
                        if (disabled || cBounds === undefined) {
                            return;
                        }
                        if (mousePos.left >= cBounds.startX && mousePos.left <= cBounds.endX && mousePos.top >= cBounds.startY && mousePos.top <= cBounds.endY) {
                            self._mouseUpInsidePlotArea(e, mousePos);
                        }
                    });
                }
            };

            wijchartcore.prototype._unbindCanvasEvents = function () {
                // In IE11, the -ms-touch-action changed to touch-action.
                if ($.support.isTouchEnabled && $.support.isTouchEnabled()) {
                    if (window.navigator["pointerEnabled"]) {
                        this.element.css("touch-action", "");
                    } else if (window.navigator.msPointerEnabled) {
                        this.element.css("-ms-touch-action", "");
                    }
                }
                this.element.unbind("." + this.widgetName);
            };

            wijchartcore.prototype._bindLegendEvents = function () {
                var self = this, element = self.chartElement;
                element.delegate("." + self.options.wijCSS.legend, "click.wijchartcore", function (e) {
                    if (self._isDisabled()) {
                        return;
                    }
                    var tar = $(e.target);
                    if (tar[0].tagName && tar[0].tagName === "tspan") {
                        tar = tar.parent();
                    }
                    self._legendClick(tar);
                });
                //$(".wijchart-legend", element[0])
                //	.live("click." + widgetName, function (e) {
                //		if (self.options.disabled) {
                //			return;
                //		}
                //		var tar = $(e.target);
                //		if (tar[0].tagName && tar[0].tagName === "tspan") {
                //			tar = tar.parent();
                //		}
                //		self._legendClick(tar);
                //	});
            };

            wijchartcore.prototype._legendClick = function (obj) {
                if (typeof obj.data("index") === "undefined") {
                    return;
                }
                var self = this, l = self.options.legend, i = obj.data("index"), legendIndex = obj.data("legendIndex"), fields = self.chartElement.data("fields"), seriesEles = self.seriesEles, seriesEle, legendIcon = self.legendIcons[legendIndex], legend = self.legends[legendIndex], legendNode = l.textWidth ? $(legend[0].node) : $(legend.node), idx = i, legendDot;

                if (fields && fields.seriesEles) {
                    seriesEles = fields.seriesEles;
                }

                if (self.legendDots && self.legendDots.length > i) {
                    legendDot = self.legendDots[i];
                }

                if (l.reversed) {
                    idx = self.legends.length - 1 - i;
                }
                seriesEle = seriesEles[idx];

                if (self.legends.length) {
                    if (!legendNode.data("hidden")) {
                        if (seriesEle) {
                            self._hideSerieEles(seriesEle);
                        }
                        if (!legendNode.data("textOpacity")) {
                            if (l.textWidth) {
                                legendNode.data("textOpacity", legend[0].attr("opacity") || 1);
                            } else {
                                legendNode.data("textOpacity", legend.attr("opacity") || 1);
                            }
                        }

                        if (!legendNode.data("iconOpacity")) {
                            legendNode.data("iconOpacity", legendIcon.attr("opacity") || 1);
                        }

                        if (legendDot && !legendNode.data("dotOpacity")) {
                            legendNode.data("dotOpacity", legendIcon.attr("opacity") || 1);
                        }

                        legend.attr("opacity", "0.3");
                        legendIcon.attr("opacity", "0.3");
                        if (legendDot) {
                            legendDot.attr("opacity", "0.3");
                        }
                        legendNode.data("hidden", true);
                    } else {
                        if (seriesEle) {
                            self._showSerieEles(seriesEle);
                        }
                        legend.attr("opacity", legendNode.data("textOpacity"));
                        legendIcon.attr("opacity", legendNode.data("iconOpacity"));
                        if (legendDot) {
                            legendDot.attr("opacity", legendNode.data("dotOpacity"));
                        }
                        legendNode.data("hidden", false);
                    }
                }
            };

            wijchartcore.prototype._showSerieEles = function (seriesEle) {
            };

            wijchartcore.prototype._hideSerieEles = function (seriesEle) {
            };

            wijchartcore.prototype._unbindLiveEvents = function () {
                var self = this, o = self.options, element = this.chartElement, widgetName = self.widgetName;
                element.undelegate("." + o.wijCSS.legend, ".wijchartcore").undelegate("." + o.wijCSS.legend, "wijchartcore");
                this._unbindCanvasEvents();
                this._unbindResizeEvent();
            };

            wijchartcore.prototype._isBarChart = function () {
                return false;
            };

            wijchartcore.prototype._isPieChart = function () {
            };

            wijchartcore.prototype._validateSeriesData = function (series) {
                return false;
            };

            wijchartcore.prototype._getOffsetOfAxis = function (axisOptions) {
                return 0;
            };

            // methods for Axis
            wijchartcore.prototype._calculateParameters = function (axisInfo, axisOptions) {
                var self = this, maxData = axisOptions.max, minData = axisOptions.min, autoMax = axisOptions.autoMax && axisInfo.autoMax, autoMin = axisOptions.autoMin && axisInfo.autoMin, autoMajor = axisOptions.autoMajor && axisInfo.autoMajor, autoMinor = axisOptions.autoMinor && axisInfo.autoMinor, axisAnno = null, prec = null, isVL = axisInfo.annoMethod === "valueLabels", major = 0, newmax = 0, newmin = 0, dx = 0, tinc = 0, isTime = axisInfo.isTime, adjustMinValue = self.options.adjustMinValue;

                if (autoMax && maxData !== Number.MIN_VALUE) {
                    if (axisInfo.id !== "x" && self._isBarChart()) {
                        if (maxData < 0.0 && (0.5 * (maxData - minData) > -maxData)) {
                            maxData = 0.0;
                        }
                    }
                }

                if (autoMin && minData !== Number.MAX_VALUE) {
                    if (axisInfo.id !== "x" && self._isBarChart()) {
                        if (minData > 0.0 && (0.5 * (maxData - minData) > minData)) {
                            minData = 0.0;
                        }
                    }
                }

                if (maxData === minData) {
                    if (minData !== 0) {
                        minData -= 1;
                    }
                    maxData += 1;
                }

                dx = maxData - minData;

                if (isTime) {
                    axisAnno = axisOptions.annoFormatString;
                    if (!axisAnno || axisAnno.length === 0) {
                        axisAnno = ChartDataUtil.getTimeDefaultFormat(maxData, minData);
                        axisInfo.annoFormatString = axisAnno;
                    }
                    tinc = ChartDataUtil.niceTimeUnit(0.0, axisAnno);
                }
                prec = ChartDataUtil.nicePrecision(dx);
                axisInfo.tprec = prec;
                if (autoMax) {
                    if (isTime) {
                        newmax = ChartDataUtil.roundTime(maxData, tinc, true);
                        if (newmax < maxData) {
                            maxData = newmax + tinc;
                        } else {
                            maxData = newmax;
                        }
                    } else {
                        newmax = ChartDataUtil.precCeil(-prec, maxData);
                        if (typeof (newmax) === "number") {
                            maxData = newmax;
                        }
                    }
                }
                if (autoMin) {
                    if (isTime) {
                        newmin = ChartDataUtil.roundTime(minData, tinc, false);
                        if (newmin > minData) {
                            minData = newmin - tinc;
                        } else {
                            minData = newmin;
                        }
                    } else {
                        newmin = ChartDataUtil.precFloor(-prec, minData);
                        if (typeof (newmin) === "number") {
                            minData = newmin;
                        }
                    }
                }

                axisInfo.max = maxData;
                axisInfo.min = minData;
                axisInfo.originalMax = maxData;
                axisInfo.originalMin = minData;
                axisInfo.annoFormatString = axisAnno;
                axisInfo.tinc = tinc;

                if (autoMajor || autoMinor) {
                    dx = maxData - minData;
                    self._calculateMajorMinor(axisOptions, axisInfo);

                    // var minor = axisOptions.unitMinor;
                    major = axisOptions.unitMajor;
                    if (autoMax && major !== 0 && !isTime && !isVL) {
                        dx = maxData - parseInt((maxData / major).toString(), 10) * major;

                        if (dx !== 0) {
                            maxData += (major - dx);
                            maxData = ChartDataUtil.precCeil(-prec, maxData);
                        }
                    }

                    if (autoMin && major !== 0 && !isTime && !isVL) {
                        dx = minData - parseInt((minData / major).toString(), 10) * major;

                        if (dx !== 0) {
                            if (dx < 0) {
                                dx += major;
                            }

                            minData -= Math.abs(dx); // should always be less.
                            minData = ChartDataUtil.precFloor(-prec, minData);
                        }
                    }

                    if (autoMin && major !== 0 && !isVL && (typeof adjustMinValue === "undefined" || adjustMinValue === false) && autoMin && minData === axisOptions.min && minData - major >= 0 && axisInfo.id === "y") {
                        minData -= major;
                    }
                }

                /*
                * //TODO: if (!autoMajor || !autoMinor) { }
                */
                axisInfo.max = maxData;
                axisInfo.min = minData;
                axisInfo.originalMax = maxData;
                axisInfo.originalMin = minData;
            };

            wijchartcore.prototype._supportStacked = function () {
                return false;
            };

            wijchartcore.prototype._getDataExtreme = function (isMultiYAxis) {
                var val = {
                    txx: 0,
                    txn: 0,
                    tyx: 0,
                    tyn: 0
                }, valGroup;

                valGroup = this._getDataExtremes(val, isMultiYAxis);
                if (valGroup) {
                    if (valGroup.txn > valGroup.txx) {
                        valGroup.txn = 0;
                        valGroup.txx = 1;
                    }
                    return valGroup;
                } else {
                    if (val.txn > val.txx) {
                        val.txn = 0;
                        val.txx = 1;
                    }
                    return val;
                }
            };

            wijchartcore.prototype._getDataExtremes = function (val, isMultiYAxis) {
                var self = this, o = self.options, seriesList = o.seriesList, stacked = o.stacked && self._supportStacked(), is100Percent = o.is100Percent, axis = o.axis, axisInfo = self.axisInfo, valuesX = [], tlValsX = [], lastValuesY = [], valueLabels = [], validValue, valGroup = { y: {} }, xValueLabels = axis.x.valueLabels, xAnnoMethod = axisInfo.x.annoMethod, yAnnoMethod = axisInfo.y.annoMethod, seriesIndex = 0;

                if (!seriesList || seriesList.length === 0) {
                    return val;
                }

                //handle the seriesList's xy data
                $.each(seriesList, function (i, series) {
                    var data = series.data, xValues = [], yValues = [], length, k = 0;

                    if (data.xy && $.isArray(data.xy)) {
                        length = data.xy.length;
                        while (k < length) {
                            xValues.push(data.xy[k]);
                            yValues.push(data.xy[k + 1]);
                            k += 2;
                        }
                        data.x = xValues;
                        data.y = yValues;
                    }
                });

                if (self.seriesGroup) {
                    $.each(self.seriesGroup, function (key, seriesL) {
                        var valuesY = [], tlValsY = [], k = parseInt(key, 10);
                        $.each(seriesL, function (i, series) {
                            var data, index = 0, k = 0, valuesXY, len, xMinMax, yMinMax, isTrendLine, tData, isTrendline;
                            if (series.type === "pie" || series.type === "sharedPie") {
                                return true;
                            }

                            // support hole.
                            series = $.extend(true, { display: "show" }, series);

                            // end comments
                            // support hole.
                            if (series.display === "exclude") {
                                return true;
                            }

                            // end comments
                            isTrendline = self._isTrendline(series);

                            data = series.data;
                            valuesXY = [].concat(data.xy);
                            len = valuesXY.length;
                            valuesX = [].concat(data.x);
                            valuesY = [].concat(data.y);
                            if (!isTrendline) {
                                if (data.xy && len) {
                                    valuesX = [];
                                    valuesY = [];

                                    while (k < len) {
                                        valuesX[index] = valuesXY[k];
                                        valuesY[index] = valuesXY[k + 1];
                                        k += 2;
                                        index++;
                                        data.x = valuesX;
                                        data.y = valuesY;
                                    }
                                } else if (!data.x) {
                                    valuesX = [];

                                    $.each(valuesY, function (i) {
                                        valuesX.push(i);
                                    });

                                    data.x = valuesX;
                                }
                                if (stacked && i > 0) {
                                    $.each(valuesY, function (j) {
                                        valuesY[j] += lastValuesY[j];
                                    });
                                }
                                lastValuesY = valuesY;
                            } else {
                                if (!series.isValid || !series.innerData) {
                                    return true;
                                }
                                tlValsX = series.innerData.x;
                                tlValsY = series.innerData.y;
                            }

                            xMinMax = self._getMinMaxValue(isTrendline ? tlValsX : valuesX);
                            yMinMax = self._getMinMaxValue(isTrendline ? tlValsY : valuesY);

                            if (i === 0) {
                                val.tyx = yMinMax.max;
                                val.tyn = yMinMax.min;
                            } else {
                                if (val.tyx < yMinMax.max) {
                                    val.tyx = yMinMax.max;
                                }
                                if (val.tyn > yMinMax.min) {
                                    val.tyn = yMinMax.min;
                                }
                            }

                            if (seriesIndex === 0) {
                                val.txx = xMinMax.max;
                                val.txn = xMinMax.min;
                            } else {
                                if (val.txx < xMinMax.max) {
                                    val.txx = xMinMax.max;
                                }
                                if (val.txn > xMinMax.min) {
                                    val.txn = xMinMax.min;
                                }
                            }
                            seriesIndex++;
                        });

                        if (is100Percent) {
                            val.tyx = 1;
                            val.tyn = 0;
                        }

                        valGroup.y[key] = { tyx: val.tyx, tyn: val.tyn };
                        valGroup.txx = val.txx;
                        valGroup.txn = val.txn;
                        val.tyx = 0;
                        val.tyn = 0;

                        //val = {txx: val.txx, txn: val.txn, tyx: 0, tyn: 0 };
                        if (valuesY.length) {
                            validValue = ChartUtil.getFirstValidListValue(valuesY);
                            if (self._isDate(validValue)) {
                                axisInfo.y[key].isTime = true;
                            } else if (typeof (validValue) === "undefined") {
                                return true;
                            } else if (typeof (validValue) !== "number") {
                                $.each(valuesY, function (idx, valueY) {
                                    // valueLabels.push({
                                    // text: valueY,
                                    // value: idx
                                    // });
                                    // Add comments by RyanWu@20110707.
                                    // For fixing the issue#15881.
                                    // valueLabels.push(valueY);
                                    var formatString = axis.y.annoFormatString, value = valueY;

                                    if (formatString && formatString.length > 0) {
                                        // value = $.format(value, formatString);
                                        value = Globalize.format(value, formatString, self._getCulture());
                                    } else {
                                        value = value.toString();
                                    }

                                    // valueLabels.push(value);
                                    valueLabels.push({
                                        text: value,
                                        value: valueY,
                                        gridLine: false
                                    });
                                    // end by RyanWu@20110707.
                                });

                                //axis.y[k].annoMethod = "valueLabels";
                                axisInfo.y[key].annoMethod = "valueLabels";
                                if (!axis.y[k].valueLabels && axis.y[k].valueLabels.length === 0) {
                                    //axis.y[k].valueLabels = valueLabels;
                                    axisInfo.y[key].valueLabels = valueLabels;
                                } else {
                                    axisInfo.y[key].valueLabels = axis.y[k].valueLabels;
                                }

                                //axis.y[parseInt(key, 10)].valueLabels = valueLabels;
                                axis.x.max = valuesY.length - 1;
                                axis.x.min = 0;
                                axis.y[k].unitMajor = 1;
                                axis.x.unitMinor = 0.5;
                                axisInfo.y[key].autoMax = false;
                                axisInfo.y[key].autoMin = false;
                                axisInfo.y[key].autoMajor = false;
                                axisInfo.y[key].autoMinor = false;
                            }
                        }
                    });
                }

                self._getXAxisInfoValueLabels(axisInfo.x, axis.x);
                if (valuesX.length) {
                    validValue = ChartUtil.getFirstValidListValue(valuesX);
                    xValueLabels = axisInfo.x.valueLabels;

                    if (self._isDate(validValue)) {
                        axisInfo.x.isTime = true;
                    } else if (typeof (validValue) !== "number") {
                        $.each(valuesX, function (idx, valueX) {
                            var vLabel = {}, xvl, xvlType;
                            if (xAnnoMethod === "valueLabels" && xValueLabels && xValueLabels.length && idx < xValueLabels.length) {
                                xvl = xValueLabels[idx];
                                xvlType = typeof xvl;
                                if (xvlType === "string") {
                                    xvl = { text: xvl };
                                } else if (xvlType === "number" || self._isDate(xvl)) {
                                    xvl = { value: xvl };
                                }
                            }
                            vLabel = $.extend({
                                text: valueX,
                                value: idx,
                                gridLine: false
                            }, xvl);
                            valueLabels.push(vLabel);
                            // valueLabels.push(valueX);
                        });

                        //axis.x.annoMethod = "valueLabels";
                        //axis.x.valueLabels = valueLabels;
                        axis.x.max = valuesX.length - 1;
                        axis.x.min = 0;
                        axis.x.unitMajor = 1;
                        axis.x.unitMinor = 0.5;
                        axisInfo.x.annoMethod = "valueLabels";
                        axisInfo.x.valueLabels = valueLabels;
                        axisInfo.x.autoMax = false;
                        axisInfo.x.autoMin = false;
                        axisInfo.x.autoMajor = false;
                        axisInfo.x.autoMinor = false;
                    }
                }

                return valGroup;
                //return val;
            };

            wijchartcore.prototype._getXAxisInfoValueLabels = function (xAxisInfo, xAxisOptions) {
                var xAnnoMethod = xAxisOptions.annoMethod, xValueLabels = xAxisOptions.valueLabels;
                if (xAnnoMethod === "valueLabels" && xValueLabels && xValueLabels.length > 0) {
                    xAxisInfo.valueLabels = xValueLabels;
                }
            };

            wijchartcore.prototype._isVertical = function (compass) {
                return compass === "west" || compass === "east";
            };

            wijchartcore.prototype._isDate = function (obj) {
                if (!obj) {
                    return false;
                }
                return (typeof obj === 'object') && obj.constructor === Date;
            };

            wijchartcore.prototype._getMinMaxValue = function (array) {
                var self = this, val = {
                    min: 0,
                    max: 0
                }, i = 0, validValue;

                if (!array.length) {
                    return val;
                }

                validValue = ChartUtil.getFirstValidListValue(array);
                if (typeof (validValue) !== "number") {
                    if (self._isDate(validValue)) {
                        val.min = validValue;
                        val.max = validValue;
                    } else {
                        val.min = 0;
                        val.max = array.length - 1;
                        return val;
                    }
                } else {
                    val.min = validValue;
                    val.max = validValue;
                }

                for (i = 0; i < array.length; i++) {
                    if (array[i] === null || typeof array[i] === "undefined") {
                        continue;
                    }
                    if (typeof array[i] === "number" && isNaN(array[i])) {
                        continue;
                    }
                    if (array[i] < val.min) {
                        val.min = array[i];
                    } else if (array[i] > val.max) {
                        val.max = array[i];
                    }
                }

                if (self._isDate(val.min)) {
                    val.min = $.toOADate(val.min);
                    val.max = $.toOADate(val.max);
                }

                return val;
            };

            wijchartcore.prototype._getTickTextForCalculateUnit = function (value, axisInfo, prec) {
                var isTime = axisInfo.isTime, formatString = axisInfo.annoFormatString;

                if (isTime) {
                    return Globalize.format($.fromOADate(value), formatString, this._getCulture());
                } else {
                    return $.round(value, prec).toString();
                }
            };

            wijchartcore.prototype._calculateMajorMinor = function (axisOptions, axisInfo) {
                var self = this, o = self.options, canvasBounds = axisInfo.bounds || self.canvasBounds, autoMajor = axisOptions.autoMajor, autoMinor = axisOptions.autoMinor, maxData = axisInfo.max, minData = axisInfo.min, isTime = axisInfo.isTime, tinc = axisInfo.tinc, formatString = axisInfo.annoFormatString, maxText = null, minText = null, sizeMax = null, sizeMin = null, mx = null, mn = null, precision = null, _prec = null, textStyle = null, dx = maxData - minData, width = 0, height = 0, nticks = 0, major = 0;

                if (autoMajor) {
                    textStyle = $.extend(true, {}, o.textStyle, axisOptions.textStyle, axisOptions.labels.style);

                    if (!isTime) {
                        precision = ChartDataUtil.nicePrecision(dx);
                        _prec = precision + 1;

                        if (_prec < 0 || _prec > 15) {
                            _prec = 0;
                        }
                    }

                    maxText = this._getTickTextForCalculateUnit(maxData, axisInfo, precision);
                    minText = this._getTickTextForCalculateUnit(minData, axisInfo, precision);

                    mx = self._text(-1000, -1000, maxText).attr(textStyle);
                    mn = self._text(-1000, -1000, minText).attr(textStyle);

                    sizeMax = mx.wijGetBBox();
                    sizeMin = mn.wijGetBBox();

                    mx.wijRemove();
                    mx = null;
                    mn.wijRemove();
                    mn = null;

                    if (sizeMax.width < sizeMin.width) {
                        sizeMax.width = sizeMin.width;
                    }

                    if (sizeMax.height < sizeMin.height) {
                        sizeMax.height = sizeMin.height;
                    }

                    if (!self._isVertical(axisOptions.compass)) {
                        // Add comments by RyanWu@20100907.
                        // Subtract axisTextOffset because we must left
                        // the space between major text and major rect.
                        width = canvasBounds.endX - canvasBounds.startX - axisInfo.vOffset - axisInfo.axisTextOffset;
                        major = width / sizeMax.width;

                        if (Number.POSITIVE_INFINITY === major) {
                            nticks = 0;
                        } else {
                            nticks = parseInt(major.toString(), 10);
                        }
                    } else {
                        height = canvasBounds.endY - canvasBounds.startY - axisInfo.vOffset - axisInfo.axisTextOffset;
                        major = height / sizeMax.height;

                        if (Number.POSITIVE_INFINITY === major) {
                            nticks = 0;
                        } else {
                            nticks = parseInt(major.toString(), 10);
                        }
                    }

                    major = dx;
                    if (nticks > 0) {
                        dx /= nticks;
                        if (isTime) {
                            if (dx < tinc) {
                                major = tinc;
                            } else {
                                major = ChartDataUtil.niceTimeUnit(dx, axisInfo.annoFormatString);
                            }
                        } else {
                            axisInfo.tprec = ChartDataUtil.nicePrecision(dx);
                            major = ChartDataUtil.niceNumber(2 * dx, -precision, true);

                            if (major < dx) {
                                major = ChartDataUtil.niceNumber(dx, -precision + 1, false);
                            }

                            if (major < dx) {
                                major = ChartDataUtil.niceTickNumber(dx);
                            }
                        }
                    }

                    axisOptions.unitMajor = major;
                }

                if (autoMinor && axisOptions.unitMajor && !isNaN(axisOptions.unitMajor)) {
                    axisOptions.unitMinor = axisOptions.unitMajor / 2;
                }
            };
            return wijchartcore;
        })(wijmo.wijmoWidget);
        chart.wijchartcore = wijchartcore;

        var wijchartcore_options = (function () {
            function wijchartcore_options() {
                /**
                * Creates an array of AnnotationBase objects that contain the settings of the annotations to display in the chart.
                */
                this.annotations = [];
                /**
                * Sets the width of the chart in pixels.
                * @remarks
                * Note that this value overrides any value you may set in the <div> element that
                * you use in the body of the HTML page
                * If you specify a width in the <div> element that is different from this value,
                * the chart and its border go out of synch.
                * @type {?number}
                */
                this.width = null;
                /**
                * Sets the height of the barchart in pixels.
                * @remarks
                * Note that this value overrides any value you may set in the <div> element that
                * you use in the body of the HTML page. If you specify a height in the <div> element that
                * is different from this value, the chart and its border go out of synch.
                * @type {?number}
                */
                this.height = null;
                /**
                * this option uses internal
                * @ignore
                */
                this.wijCSS = new wijchartcore_css();
                /** A value that indicator the culture to format the chart text. */
                this.culture = "";
                /** Assigns the string value of the culture calendar that appears on the calendar.
                *	This option must work with culture option.
                */
                this.cultureCalendar = "";
                /** A value that indicates whether to redraw the chart automatically when resizing the chart element. */
                this.autoResize = true;
                /**
                * Creates an array of series objects that contain data values and labels to display in the chart.
                */
                this.seriesList = [];
                /**
                * Sets an array of style objects to use in rendering the bars for each series in the chart.
                * @remarks
                * Each style object in the array applies to one series in your seriesList,
                * so you need specify only as many style objects as you have series objects
                * in your seriesList. The style is also used in the legend entry for the series
                * in your seriesList. The style is also used in the legend entry for the series
                */
                this.seriesStyles = [
                    {
                        stroke: "#00cc00",
                        opacity: 0.9,
                        "stroke-width": 1
                    }, {
                        stroke: "#0099cc",
                        opacity: 0.9,
                        "stroke-width": 1
                    }, {
                        stroke: "#0055cc",
                        opacity: 0.9,
                        "stroke-width": 1
                    }, {
                        stroke: "#2200cc",
                        opacity: 0.9,
                        "stroke-width": 1
                    }, {
                        stroke: "#8800cc",
                        opacity: 0.9,
                        "stroke-width": 1
                    }, {
                        stroke: "#d9007e",
                        opacity: 0.9,
                        "stroke-width": 1
                    }, {
                        stroke: "#ff0000",
                        opacity: 0.9,
                        "stroke-width": 1
                    }, {
                        stroke: "#ff6600",
                        opacity: 0.9,
                        "stroke-width": 1
                    }, {
                        stroke: "#ff9900",
                        opacity: 0.9,
                        "stroke-width": 1
                    }, {
                        stroke: "#ffcc00",
                        opacity: 0.9,
                        "stroke-width": 1
                    }, {
                        stroke: "#ffff00",
                        opacity: 0.9,
                        "stroke-width": 1
                    }, {
                        stroke: "#ace600",
                        opacity: 0.9,
                        "stroke-width": 1
                    }];
                /**
                * Sets an array of styles to use in rendering bars in the chart when you hover over them.
                * @remarks
                * Each style object in the array applies to a series in your seriesList,so you need
                * specify only as many style objects as you have series objects in your seriesList
                */
                this.seriesHoverStyles = [
                    {
                        opacity: 1,
                        "stroke-width": 1.5
                    }, {
                        opacity: 1,
                        "stroke-width": 1.5
                    }, {
                        opacity: 1,
                        "stroke-width": 1.5
                    }, {
                        opacity: 1,
                        "stroke-width": 1.5
                    }, {
                        opacity: 1,
                        "stroke-width": 1.5
                    }, {
                        opacity: 1,
                        "stroke-width": 1.5
                    }, {
                        opacity: 1,
                        "stroke-width": 1.5
                    }, {
                        opacity: 1,
                        "stroke-width": 1.5
                    }, {
                        opacity: 1,
                        "stroke-width": 1.5
                    }, {
                        opacity: 1,
                        "stroke-width": 1.5
                    }, {
                        opacity: 1,
                        "stroke-width": 1.5
                    }, {
                        opacity: 1,
                        "stroke-width": 1.5
                    }];
                /**
                * Sets the amount of space in pixels between the chart area and the top edge of the <div> that defines the widget
                */
                this.marginTop = 25;
                /**
                * Sets the amount of space in pixels between the chart area and the right edge of the <div> that defines the widget
                */
                this.marginRight = 25;
                /**
                *  Sets the amount of space in pixels between the chart area and the bottom edge of the <div> that defines the widget.
                */
                this.marginBottom = 25;
                /**
                * Sets the amount of space in pixels between the chart area and the left edge of the <div> that defines the widget
                */
                this.marginLeft = 25;
                /**
                * Creates an object to use for the fallback style of any chart text that does not
                * have other style options set.
                * @remarks
                * Each type of text in the chart has a different set of styles applied by default, but if those styles are set to null,
                * or if a particular style option is not set by default, the chart falls back on any style options you set in this option.
                * Styles for specific types of chart text that may use this option as a fallback style are set in the following options:
                * axis x labels style
                *		axis x textStyle
                *		axis y labels style
                *		axis y textStyle
                *		chartLabelStyle
                *		footer textStyle
                *		header textStyle
                *		hint contentStyle
                *		hint titleStyle
                *		legend textStyle
                *		legend titleStyle
                * The style is defined in Raphael here is the documentation: http://raphaeljs.com/reference.html#Element.attr.
                * The style is the “attr” method’s parameters.
                */
                this.textStyle = {
                    fill: "#888",
                    "font-size": 10,
                    stroke: "none"
                };
                /** Sets up the object to use as the header of the barchart.*/
                this.header = {
                    /**
                    * A value that indicates the text to display in the header.
                    * @remarks
                    * If you leave this as an empty string, no header renders, regardless of any other header attributes.
                    */
                    text: "",
                    /**
                    * A value that indicates all of the style attributes to use in rendering the header.
                    * @remarks
                    * The style is defined in Raphael here is the documentation: http://raphaeljs.com/reference.html#Element.attr
                    * The style is the “attr” method’s parameters.
                    */
                    style: {
                        fill: "none",
                        stroke: "none"
                    },
                    /**
                    * A value that indicates the style of the header text.
                    * @remarks
                    * Note: Any style options set in the fallback textStyle option are used for any
                    * style options that are not set explicitly (or set by default) in this option.
                    */
                    textStyle: {
                        "font-size": 18,
                        fill: "#666",
                        stroke: "none"
                    },
                    /**
                    * A value that indicates the position of the header in relation to the chart.
                    * @remarks
                    * Valid Values:
                    *		"north" Renders the header above the chart.
                    *		"south" Renders the header below the chart.
                    *		"east" Renders the header to the right of the chart, with the text rotated 90 degrees.
                    *		"west" Renders the header to the left of the chart, with the text rotated 270 degrees.
                    */
                    compass: "north",
                    /**
                    * A value that indicates the visibility of the header.
                    */
                    visible: true
                };
                /**
                * Sets up the object to use as the footer of the barchart.
                */
                this.footer = {
                    /**
                    * A value that indicates the text to display in the footer.
                    * @remarks
                    * If you leave this as an empty string, no footer renders, regardless of any other footer attributes.
                    */
                    text: "",
                    /**
                    * A value that indicates all of the style attributes to use in rendering the footer.
                    * @remarks
                    * The style is defined in Raphael here is the documentation: http://raphaeljs.com/reference.html#Element.attr.
                    * The style is the “attr” method’s parameters.
                    */
                    style: {
                        fill: "#fff",
                        stroke: "none"
                    },
                    /**
                    * A value that indicates the style of the footer text.
                    * @remarks
                    * Note: Any style options set in the fallback textStyle option are used for
                    * any style options that are not set explicitly (or set by default) in this option.
                    * The style is defined in Raphael here is the documentation:http://raphaeljs.com/reference.html#Element.attr.
                    * The style is the “attr” method’s parameters.
                    */
                    textStyle: {
                        fill: "#000",
                        stroke: "none"
                    },
                    /**
                    * A value that indicates the position of the footer in relation to the chart.
                    * @remarks
                    * Valid Values:
                    * 		"north" Renders the footer above the chart.
                    *		"south" Renders the footer below the chart.
                    *		"east" Renders the footer to the right of the chart, with the text rotated 90 degrees.
                    *		"west" Renders the footer to the left of the chart, with the text rotated 270 degrees.
                    */
                    compass: "south",
                    /**
                    * A value that indicates the visibility of the footer.
                    */
                    visible: false
                };
                /**
                * Creates a legend object to display with the chart.
                * @remarks
                * By default, each series that you create in the seriesList is represented by a color in the legend,
                * using the seriesList label that you specify. If you do not specify a label,
                * it is labeled "undefined." If you do not want a series to appear in the legend,
                * you can set the seriesList legendEntry attribute to false.
                * By default, users can click a legend entry to toggle the data series it
                * represents in the chart.See Clickable Legend for code that allows you to disable this function.
                * @example
                * // This code creates a chart with a legend that is positioned below the chart (south),
                * // with series labels and colors in a row (horizontal), a grey outline and lighter
                * // grey fill (style), has a title that reads "Legend" (text), has 5 pixels of
                * // space around the text (textMargin), has series labels in a black 12-point font
                * // (textStyle), and has a 14-point font title (titleStyle)
                *    $(document).ready(function () {
                *        $("#wijbarchart").wijbarchart({
                *			legend: {
                *			compass: "south",
                *			orientation: "horizontal",
                *			style: {fill: "gainsboro", stroke: "grey"},
                *			text: "Legend",
                *			textMargin: {left: 5, top: 5, right: 5, bottom: 5 },
                *			textStyle: {fill: "black", "font-size": 12},
                *			titleStyle: {"font-size": 14}
                *			},
                *			seriesList: [{
                *			label: "US",
                *			data: {
                *			x: ['PS3', 'XBOX360', 'Wii'],
                *			y: [12.35, 21.50, 30.56]
                *			}
                *			},
                *			{
                *			label: "Japan",
                *			data: {
                *			x: ['PS3', 'XBOX360', 'Wii'],
                *			y: [4.58, 1.23, 9.67]
                *			}
                *			},
                *			{
                *			label: "Other",
                *			data: {
                *			x: ['PS3', 'XBOX360', 'Wii'],
                *			y: [31.59, 37.14, 65.32]
                *			}
                *			}],
                *		});
                *	});
                */
                this.legend = {
                    // / <summary>
                    /**
                    * A value that indicates the text to use as the title at the top of the legend.
                    * @remarks
                    * Set style properties on this text using the titleStyle attribute.
                    */
                    text: "",
                    /**
                    * A value in pixels that indicates the amount of space to leave around the text inside the legend.
                    */
                    textMargin: { left: 2, top: 2, right: 2, bottom: 2 },
                    /**
                    * A value that indicates the background color (fill) and border (stroke) of the legend.
                    * The style is defined in Raphael here is the documentation: http://raphaeljs.com/reference.html#Element.attr.
                    * The style is the 'attr' method's parameters.
                    */
                    style: {
                        fill: "none",
                        stroke: "none"
                    },
                    /**
                    * A value that indicates the width of the legend text.
                    */
                    textWidth: null,
                    /**
                    * A value that indicates the style of the series label text. The text values come from the seriesList labels.
                    * @remarks
                    * Note: Any style options set in the fallback textStyle option are used for
                    * any style options that are not set explicitly (or set by default) in this option.
                    * The style is defined in Raphael here is the documentation: http://raphaeljs.com/reference.html#Element.attr.
                    * The style is the 'attr' method's parameters.
                    */
                    textStyle: {
                        fill: "#333",
                        stroke: "none"
                    },
                    /**
                    * A value that indicates the style of the legend title. The text for the title is set in the text
                    * attribute of the legend.
                    * @remarks
                    * Note: Any style options set in the fallback textStyle option are used for any
                    * style options that are not set explicitly (or set by default) in this option.
                    * The style is defined in Raphael here is the documentation: http://raphaeljs.com/reference.html#Element.attr.
                    * The style is the 'attr' method's parameters.
                    */
                    titleStyle: {
                        "font-weight": "bold",
                        fill: "#000",
                        stroke: "none"
                    },
                    /**
                    * A value that indicates the compass position of the legend.
                    * @remarks
                    * Valid Values: "north", "south", "east", "west"
                    */
                    compass: "east",
                    /**
                    * A value that indicates the orientation of the legend.
                    * @remarks
                    * Vertical orientation generally works better with an east or west compass setting for the
                    * legend, while horizontal is more useful with a north or south compass setting and a small
                    * number of series in the seriesList.
                    * Valid Values:
                    *		"horizontal" Displays series labels and colors in a row.
                    *		"vertical" Displays series labels and colors in a column.
                    */
                    orientation: "vertical",
                    /**
                    * A value that indicates whether to show the legend. Set this value to false to hide the legend.
                    */
                    visible: true,
                    reversed: false,
                    size: {}
                };
                /**
                * A value that contains all of the information to create the X and Y axes of the chart
                */
                this.axis = {
                    /**
                    * An object containing all of the information to create the X axis of the chart.
                    */
                    x: {
                        /**
                        * Sets the alignment of the X axis title text.
                        * @remarks
                        * Options are 'center', 'near', 'far'.
                        */
                        alignment: "center",
                        /**
                        * A value that indicates the style of the X axis.
                        * @remarks
                        * The style is defined in Raphael here is the documentation:http://raphaeljs.com/reference.html#Element.attr.
                        * The style is the “attr” method’s parameters.
                        */
                        style: {
                            stroke: "#999999",
                            "stroke-width": 0.5
                        },
                        /**
                        * A value that indicates the visibility of the X axis.
                        */
                        visible: true,
                        /**
                        * A value that indicates the visibility of the X axis text.
                        */
                        textVisible: true,
                        /**
                        * Sets the text to use for the X axis title.
                        */
                        text: "",
                        /**
                        * A value that indicates the style of text of the X axis.
                        * @remarks
                        * Note: Any style options set in the fallback textStyle option are used for
                        * any style options that are not set explicitly (or set by default) in this option.
                        * The style is defined in Raphael here is the documentation: http://raphaeljs.com/reference.html#Element.attr.
                        * The style is the “attr” method’s parameters.
                        */
                        textStyle: {
                            fill: "#888",
                            "font-size": 15,
                            "font-weight": "bold"
                        },
                        /**
                        * A value that provides information for the labels.
                        */
                        labels: {
                            /**
                            * A value that indicates the style of major text of the X axis.
                            * @remarks
                            * Note: Any style options set in the fallback textStyle option are used for any style
                            * options that are not set explicitly (or set by default) in this option.
                            * The style is defined in Raphael here is the documentation: http://raphaeljs.com/reference.html#Element.attr.
                            * The style is the “attr” method’s parameters.
                            */
                            style: {
                                fill: "#333",
                                "font-size": 11
                            },
                            /**
                            * A value that indicates the alignment of major text of the X axis.
                            * @remarks
                            * Options are 'near', 'center' and 'far'.
                            */
                            textAlign: "near",
                            /**
                            * A value that indicates the width of major text of the X axis.
                            * @remarks
                            * If the value is null, then the width will be calculated automatically.
                            */
                            width: null
                        },
                        /**
                        * A value that indicates where to draw the X axis using the four points of a compass.
                        * @remarks
                        *		"north" Draws the axis along the top edge of the chart.
                        *		"south" Draws the axis along the bottom edge of the chart.
                        *		"east" Draws the axis along the right edge of the chart.
                        *		"west" Draws the axis along the left edge of the chart.
                        */
                        compass: "south",
                        /**
                        * A value that indicates whether to calculate the axis minimum value automatically.
                        * @remarks
                        * If you set this value to false, in order to show major tick marks on the axis, you must
                        * specify a value for the min option.
                        */
                        autoMin: true,
                        /**
                        * A value that indicates whether to calculate the axis maximum value automatically.
                        * @remarks
                        * If you set this value to false, in order to show major tick marks on the axis, you must specify a
                        * value for the max option.
                        */
                        autoMax: true,
                        /**
                        * A value that indicates the minimum value of the axis.
                        @type {?number}
                        */
                        min: null,
                        /**
                        * A value that indicates the maximum value of the axis.
                        * @type {?number}
                        */
                        max: null,
                        /**
                        * A value that indicates the origin value of the X axis.
                        * @type {?number}
                        */
                        origin: null,
                        /**
                        * A value that indicates whether to calculate the major tick mark values automatically.
                        * @remarks
                        * If you set this value to false, in order to show major tick marks on the axis, you must
                        * specify a value for the unitMajor option.
                        */
                        autoMajor: true,
                        /**
                        * A value that indicates whether to calculate the minor tick mark values automatically
                        * @remarks
                        * If you set this value to false, in order to show minor tick marks on the axis, you must
                        * specify a value for the unitMinor option.
                        */
                        autoMinor: true,
                        /**
                        * A value that indicates the units between major tick marks.
                        * @type {?number}
                        */
                        unitMajor: null,
                        /**
                        * A value that indicates the units between minor tick marks.
                        * @type {?number}
                        */
                        unitMinor: null,
                        /**
                        * A value that provides information for the major grid line.
                        */
                        gridMajor: {
                            /**
                            * A value that indicates the visibility of the major grid line.
                            */
                            visible: false,
                            /**
                            * A value that indicates the style of the major grid line
                            * @remarks
                            * The style is defined in Raphael here is the documentation: http://raphaeljs.com/reference.html#Element.attr.
                            * The style is the “attr” method’s parameters.
                            */
                            style: {
                                stroke: "#CACACA",
                                "stroke-dasharray": "- "
                            }
                        },
                        /**
                        *  A value that provides information for the minor grid line.
                        */
                        gridMinor: {
                            /**
                            * A value that indicates the visibility of the minor grid line.
                            */
                            visible: false,
                            /**
                            * A value that indicates the style of the minor grid line.
                            * @remarks
                            * The style is defined in Raphael here is the documentation: http://raphaeljs.com/reference.html#Element.attr.
                            * The style is the “attr” method’s parameters.
                            */
                            style: {
                                stroke: "#CACACA",
                                "stroke-dasharray": "- "
                            }
                        },
                        /**
                        * Creates an object with all of the settings to use in drawing tick marks that appear next to the numeric
                        * labels for major values along the X axis.
                        */
                        tickMajor: {
                            /**
                            * A value that indicates the position of the major tick mark in relation to the axis.
                            * @remarks
                            * Valid Values: none, inside, outside, cross
                            */
                            position: "none",
                            /**
                            * A value that indicates the style of major tick mark
                            * @remarks
                            * The style is defined in Raphael here is the documentation: http://raphaeljs.com/reference.html#Element.attr.
                            * The style is the “attr” method’s parameters.
                            */
                            style: { fill: "black" },
                            /**
                            * A value that indicates an integral factor for major tick mark length.
                            */
                            factor: 1
                        },
                        /**
                        * A value that provides information for the minor tick.
                        */
                        tickMinor: {
                            /**
                            * A value that indicates the type of minor tick mark.
                            * @remarks
                            * Valid Values: none, inside, outside, cross
                            */
                            position: "none",
                            /**
                            * A value that indicates the style of minor tick mark
                            * @remarks
                            * The style is defined in Raphael here is the documentation: http://raphaeljs.com/reference.html#Element.attr.
                            * The style is the “attr” method’s parameters.
                            */
                            style: { fill: "black" },
                            /**
                            * A value that indicates an integral factor for minor tick mark length.
                            */
                            factor: 1
                        },
                        /**
                        * The annoMethod option indicates how to label values along the axis.
                        * @remarks
                        * Valid Values:
                        *		"values" Uses numeric seriesList data values to annotate the axis.
                        *		"valueLabels" Uses the array of string values that you provide in the valueLabels option to
                        *			annotate the axis.
                        */
                        annoMethod: "values",
                        /**
                        * The annoFormatString option uses Standard Numeric Format Strings to provide formatting for numeric
                        * values in axis labels.
                        */
                        annoFormatString: "",
                        /**
                        * The valueLabels option shows a collection of valueLabels for the X axis.
                        * @remarks
                        * If the annoMethod is "values", this option will lost effect, If the annoMethod is "valueLabels",
                        * the axis's label will set to this option's value.
                        */
                        valueLabels: []
                    },
                    /**
                    * An object containing all of the information to create the Y axis of the chart.
                    */
                    y: {
                        /**
                        * A value that indicates the alignment of the Y axis text.
                        * @remarks
                        * Options are 'center', 'near', 'far'.
                        */
                        alignment: "center",
                        /**
                        * A value that indicates the style of the Y axis.
                        * @remarks
                        * The style is defined in Raphael here is the documentation: http://raphaeljs.com/reference.html#Element.attr.
                        * The style is the “attr” method’s parameters.
                        */
                        style: {
                            stroke: "#999999",
                            "stroke-width": 0.5
                        },
                        /**
                        * A value that indicates the visibility of the Y axis.
                        */
                        visible: false,
                        /**
                        * A value that indicates the visibility of the Y axis text.
                        */
                        textVisible: true,
                        /**
                        * Sets the text to use for the Y axis title.
                        */
                        text: "",
                        /**
                        * A value that indicates the style of text of the Y axis.
                        * @remarks
                        * Note: Any style options set in the fallback textStyle option are used for any style options that are not
                        * set explicitly (or set by default) in this option.
                        * The style is defined in Raphael here is the documentation: http://raphaeljs.com/reference.html#Element.attr.
                        * The style is the “attr” method’s parameters.
                        */
                        textStyle: {
                            fill: "#888",
                            "font-size": 15,
                            "font-weight": "bold"
                        },
                        /**
                        * A value that provides information for the labels.
                        */
                        labels: {
                            /**
                            * A value that indicates the style of major text of the Y axis.
                            * @remarks
                            * Note: Any style options set in the fallback textStyle option are used for any style options
                            * that are not set explicitly (or set by default) in this option.
                            * The style is defined in Raphael here is the documentation: http://raphaeljs.com/reference.html#Element.attr.
                            * The style is the “attr” method’s parameters.
                            */
                            style: {
                                fill: "#333",
                                "font-size": 11
                            },
                            /**
                            * A value that indicates the alignment of major text of the Y axis.
                            * @remarks
                            * Options are 'near', 'center' and 'far'.
                            */
                            textAlign: "center",
                            /**
                            * A value that indicates the width major text of the Y axis.
                            * @remarks
                            * If the value is null, then the width will be calculated automatically.
                            * @type {?number}
                            */
                            width: null
                        },
                        /**
                        * A value that indicates the compass position of the Y axis.
                        * @remarks
                        * Options are 'north', 'south', 'east' and 'west'.
                        */
                        compass: "west",
                        /**
                        * A value that indicates whether the axis minimum value is calculated automatically.
                        */
                        autoMin: true,
                        /**
                        * A value that indicates whether the axis maximum value is calculated automatically.
                        */
                        autoMax: true,
                        /**
                        * A value that indicates the minimum value of the axis.
                        * @type {?number}
                        */
                        min: null,
                        /**
                        * A value that indicates the maximum value of the axis.
                        * @type {?number}
                        */
                        max: null,
                        /**
                        * A value that indicates the origin value of the Y axis.
                        * @type {?number}
                        */
                        origin: null,
                        /**
                        * A value that indicates whether the major tick mark values are calculated automatically.
                        */
                        autoMajor: true,
                        /**
                        * A value that indicates whether the minor tick mark values are calculated automatically.
                        */
                        autoMinor: true,
                        /**
                        * A value that indicates the units between major tick marks.
                        * @type {?number}
                        */
                        unitMajor: null,
                        /**
                        * A value that indicates the units between minor tick marks.
                        * @type {?number}
                        */
                        unitMinor: null,
                        /**
                        * A value that provides information for the major grid line.
                        */
                        gridMajor: {
                            /**
                            * A value that indicates the visibility of the major grid line.
                            */
                            visible: true,
                            /**
                            * A value that indicates the style of the major grid line.
                            * @remarks
                            * The style is defined in Raphael here is the documentation: http://raphaeljs.com/reference.html#Element.attr.
                            * The style is the “attr” method’s parameters.
                            */
                            style: {
                                stroke: "#999999",
                                "stroke-width": 0.5,
                                "stroke-dasharray": "none"
                            }
                        },
                        /**
                        * A value that provides information for the minor grid line.
                        */
                        gridMinor: {
                            /**
                            * A value that indicates the visibility of the minor grid line.
                            */
                            visible: false,
                            /**
                            * A value that indicates the style of the minor grid line.
                            * @remarks
                            * The style is defined in Raphael here is the documentation: http://raphaeljs.com/reference.html#Element.attr.
                            * The style is the “attr” method’s parameters.
                            */
                            style: {
                                stroke: "#CACACA",
                                "stroke-dasharray": "- "
                            }
                        },
                        /**
                        * A value that provides information for the major tick.
                        */
                        tickMajor: {
                            /**
                            * A value that indicates the type of major tick mark.
                            * @remarks
                            * Options are 'none', 'inside', 'outside' and 'cross'.
                            */
                            position: "none",
                            /**
                            * A value that indicates the style of major tick mark.
                            * The style is defined in Raphael here is the documentation: http://raphaeljs.com/reference.html#Element.attr.
                            * The style is the “attr” method’s parameters.
                            */
                            style: { fill: "black" },
                            /**
                            * A value that indicates an integral factor for major tick mark length.
                            */
                            factor: 1
                        },
                        /**
                        * A value that provides information for the minor tick.
                        */
                        tickMinor: {
                            /**
                            * A value that indicates the type of minor tick mark.
                            * @remarks
                            * Options are 'none', 'inside', 'outside' and 'cross'.
                            */
                            position: "none",
                            /**
                            * A value that indicates the style of minor tick mark.
                            * @remarks
                            * The style is defined in Raphael here is the documentation: http://raphaeljs.com/reference.html#Element.attr.
                            * The style is the “attr” method’s parameters.
                            */
                            style: { fill: "black" },
                            /**
                            * A value that indicates an integral factor for minor tick mark length.
                            */
                            factor: 1
                        },
                        /**
                        * A value that indicates the method of annotation.
                        * @remarks
                        * Options are 'values', 'valueLabels'. If the value is “values”, when paint axis,
                        * the axis’s label will set to the data value of the series. If the value is “valueLabels”, when paint
                        * the axis, The axis’s label will set to a value which is set in axis’s valueLabels option.
                        */
                        annoMethod: "values",
                        /**
                        * The annoFormatString option uses Standard Numeric Format Strings to provide formatting for numeric
                        * values in axis labels.
                        */
                        annoFormatString: "",
                        /**
                        * The valueLabels option shows a collection of valueLabels for the X axis.
                        * @remarks
                        * If the annoMethod is "values", this option will lost effect, If the annoMethod is "valueLabels",
                        * the axis's label will set to this option's value.
                        */
                        valueLabels: []
                    }
                };
                /**
                * Creates an object to use as the tooltip, or hint, when the mouse is over a chart element.
                * @remarks
                * By default, it displays the value of the seriesList label and Y data for the chart
                */
                this.hint = {
                    /**
                    * A value that indicates whether to show the tooltip.
                    * @remarks
                    * Set this value to false to hide hints even when the mouse is over a chart element.
                    */
                    enable: true,
                    /**
                    * A value that appears in the content part of the tooltip or a function which is
                    * used to get a value for the tooltip shown.
                    * @remarks
                    * If you do not set the content here, the hint displays content in the following order:
                    *  The hint option's title attribute
                    *  The seriesList option's label attribute, which shows "undefined" if you do not provide a label value
                    *  The seriesList option's data y attribute
                    * You can format the numeric Y data in this attribute using a function
                    */
                    content: null,
                    /**
                    * A value that indicates the style of content text.
                    * @remarks
                    * Note: Any style options set in the fallback textStyle option are used for any style
                    * options that are not set explicitly (or set by default) in this option.
                    * The style is defined in Raphael here is the documentation: http://raphaeljs.com/reference.html#Element.attr.
                    * The style is the 'attr' method's parameters.
                    */
                    contentStyle: {
                        fill: "#d1d1d1",
                        "font-size": 16
                    },
                    /**
                    * A text value (or a function returning a text value) to display in the hint on a line
                    * above the content.
                    */
                    title: null,
                    /**
                    * A value that indicates the style to use for the hint title text.
                    * @remarks
                    * The style is defined in Raphael here is the documentation: http://raphaeljs.com/reference.html#Element.attr.
                    * he style is the 'attr' method's parameters.
                    */
                    titleStyle: {
                        fill: "#d1d1d1",
                        "font-size": 16
                    },
                    /**
                    * A value that indicates the fill color or gradient and outline thickness and color
                    * (stroke) of the rectangle used to display the hint.
                    * @remarks
                    * The style is defined in Raphael here is the documentation: http://raphaeljs.com/reference.html#Element.attr.
                    * The style is the 'attr' method's parameters.
                    */
                    style: {
                        fill: "#000000",
                        "stroke-width": 2
                    },
                    /**
                    * A value that indicates the effect to use when showing or hiding the hint when showAnimated
                    * or hideAnimated is not specified.
                    * @remarks
                    * The only animation style included is "fade." If you want a different one, you can create a custom animation
                    */
                    animated: "fade",
                    /**
                    * A value that indicates the animation effect to use when the hint appears after you mouse into the chart element.
                    * @remarks
                    * This allows you to use a different effect when you mouse out of a bar than when you mouse in. (See also
                    * hideAnimated.) If you set this value to null, the animated property supplies the animation effect to use.
                    * The only animation style included is "fade." If you want a different one, you can create a custom animation
                    */
                    showAnimated: "fade",
                    /**
                    * A value that indicates the animation effect to use when the hint goes away after you mouse out of the chart element.
                    * @remarks
                    * This allows you to use a different effect when you mouse into a chart elemrnt than when you mouse out.
                    * (See also showAnimated.) If you set this value to null, the animated property supplies the animation
                    * effect to use. The only animation style included is "fade." If you want a different one, you can create
                    * a custom animation
                    */
                    hideAnimated: "fade",
                    /**
                    * A value that indicates the number of milliseconds it takes to show or hide the hint when you mouse over
                    * or mouse out of a bar with the showDuration or hideDuration attribute set to null.
                    */
                    duration: 120,
                    /**
                    * A value that indicates the number of milliseconds it takes for the indicated animation effect to completely
                    * show the tooltip.
                    * @remarks
                    * This allows you to use a different number of milliseconds when you mouse out of a bar than when you mouse in.
                    */
                    showDuration: 120,
                    /**
                    * A value that indicates the number of milliseconds it takes for the indicated animation effect to completely
                    * hide the tooltip.
                    * @remarks
                    * This allows you to use a different number of milliseconds when you mouse into a bar than when you mouse out.
                    */
                    hideDuration: 120,
                    /**
                    * A value that indicates the easing animation used to show or hide the hint when you mouse over or mouse out
                    * of a bar with the showEasing or hideEasing attribute set to null.
                    * @remarks
                    * The easing is defined in Raphael, the documentation is:http://raphaeljs.com/reference.html#Raphael.easing_formulas
                    */
                    easing: "",
                    /**
                    * A value that indicates the easing effect to use when the hint appears after you mouse into the chart element.
                    * @remarks
                    * This allows you to use a different effect when you mouse out of a bar than when you mouse in. (See also
                    * hideEasing.) If you set this value to null, the easing property supplies the easing effect to use.
                    */
                    showEasing: "",
                    /**
                    * A value that indicates the easing effect to use when the hint goes away after you mouse out of the chart element.
                    * @remarks
                    * This allows you to use a different effect when you mouse into a bar than when you mouse out. (See also
                    * showEasing.) If you set this value to null, the easing property supplies the easing effect to use.
                    */
                    hideEasing: "",
                    /**
                    * A value that indicates the number of milliseconds to wait before showing the hint after the mouse moves
                    * into the chart element
                    * @remarks
                    * This allows you to use a different number of milliseconds when you mouse out of a bar than when you mouse in.
                    */
                    showDelay: 0,
                    /**
                    * A value that indicates the number of milliseconds to wait before hiding the hint after the mouse leaves
                    * the chart element
                    * @remarks
                    * This allows you to use a different number of milliseconds when you mouse into a bar than when you mouse out.
                    */
                    hideDelay: 150,
                    /**
                    * A value that indicates the compass position of the callout (the small triangle that points from the main
                    * hint box to the bar it describes) in relation to the hint box.
                    * @remarks
                    * Valid Values: west, east, south, southeast, southwest, northeast and northwest
                    */
                    compass: "north",
                    /**
                    * A value that indicates the horizontal distance in pixels from the mouse pointer to the callout triangle
                    * of the hint.
                    * @remarks
                    * The position of the callout triangle depends on the compass setting of the hint callout.
                    */
                    offsetX: 0,
                    /**
                    * A value that indicates the vertical distance in pixels from the mouse pointer to the callout triangle
                    * of the hint.
                    * @remarks
                    * The position of the callout triangle depends on the compass setting of the hint callout.
                    */
                    offsetY: 0,
                    /**
                    * Determines whether to show the callout element, the small triangle that points from the main hint box
                    * to the bar it describes.
                    * @remarks
                    * To change the appearance of the callout, see these other hint attributes: calloutFilled,calloutFilledStyle,
                    * and compass.
                    */
                    showCallout: true,
                    /**
                    * Determines whether to fill the callout (the small triangle that points from the main hint box to the bar
                    * it describes).
                    * @remarks
                    * If you set it to true, the callout triangle uses the colors you specify in the calloutFilledStyle
                    * attribute. Otherwise, it takes on the colors of the style attribute of the hint.
                    */
                    calloutFilled: false,
                    /**
                    * A value that indicates the style to use in rendering the callout (the small triangle that points from the
                    * main hint box to the bar it describes).
                    * @remarks
                    * In order for this attribute of the callout to take effect, you must also set the calloutFilled attribute
                    * to true. Otherwise, it takes on the colors of the style attribute of the hint.
                    * The style is defined in Raphael here is the documentation: http://raphaeljs.com/reference.html#Element.attr.
                    * The style is the “attr” method’s parameters.
                    */
                    calloutFilledStyle: {
                        fill: "#000"
                    },
                    /** @ignore*/
                    beforeShowing: null,
                    /** Determines how to close the tooltip. Behaviors include auto or sticky.
                    * @remarks Options: "auto", "none" and "sticky".
                    */
                    closeBehavior: "auto",
                    /** Determines tooltip should related to mouse or element.
                    * @remarks Options: "mouse" and "element".
                    */
                    relativeTo: "mouse",
                    //bounds: null
                    /**
                    * Determine whether to use a tooltip in html style.
                    * @remarks
                    * If you want display the tooltip with html style, set this property as true.
                    * Note that: This property must work with wijtooltip, if wijmo.wijtooltip is not included,
                    * the tooltip will display as SVG whatever this property is.
                    */
                    isContentHtml: false
                };
                /**
                * Sets up an object that can display an indicator line running horizontally/vertically through the center
                * of each chart element in the chart when the user clicks the chart element.
                */
                this.indicator = {
                    /**
                    * A value that indicates whether to show indicator lines when the user clicks a chart element in the chart.
                    */
                    visible: false,
                    /**
                    * A value that contains the fill color and outline color (stroke) of the indicator lines.
                    * @remarks
                    * Note that when you set the stroke color of the indicator line, it extends this color to the outline
                    * of the #hint:hint for the duration of the click.
                    */
                    style: {
                        stroke: "#000000"
                    }
                };
                /**
                * A value that indicates whether to show default chart labels.
                */
                this.showChartLabels = true;
                /**
                * Sets all of the style options of the chart labels that show the value of each chart element.
                * @remarks
                * The style is defined in Raphael here is the documentation: http://raphaeljs.com/reference.html#Element.attr.
                * The style is the “attr” method’s parameters.
                */
                this.chartLabelStyle = {};
                /**
                * Sets the numeric format of the chart labels that show the value of each chart element. You can use Standard
                * Numeric Format Strings.
                */
                this.chartLabelFormatString = "";
                /**
                * A value that indicates a function which is used to obtain the content part of the chart label for each chart element.
                * @type {function}
                */
                this.chartLabelFormatter = null;
                /**
                * Sets a value indicating whether you can set the font-family of the text using a class instead of options.
                * @remarks
                * Note: This applies only to the font-family in the current version.
                */
                this.disableDefaultTextStyle = false;
                /**
                * A value that indicates whether to show a shadow around the edge of the chart.
                */
                this.shadow = true;
                /**
                * Sets the array to use as a source for data that you can bind to the axes in your seriesList.
                * @remarks
                * Use the data option, and bind values to your X and Y axes. For more information please see the datasource demo:
                * http://wijmo.com/demo/explore/?widget=BarChartsample=Array%20as%20datasource.
                */
                this.dataSource = null;
                /**
                * Bind a field to each series's data x array
                */
                this.data = null;
                /**
                * This event fires before the series changes. This event can be cancelled. "return false;" to cancel the event.
                * @event
                * @dataKey {array} oldSeriesList The old series list before changes.
                * @dataKey {array} newSeriesList The new series list that will replace the old one.
                */
                this.beforeSeriesChange = null;
                /**
                * This event fires when the series changes.
                * @event
                * @dataKey {object} data An object that contains new series values.
                */
                this.seriesChanged = null;
                /**
                * This event fires before the canvas is painted. This event can be cancelled. "return false;" to cancel the event.
                * @event
                */
                this.beforePaint = null;
                /**
                * This event fires after the canvas is painted.
                * @event
                */
                this.painted = null;
                /**
                * Creates the animation object to use when the seriesList data changes.
                * @remarks
                * This allows you to visually show changes in data for the same series.
                * Note: This animation does not appear when you first load or reload the page--it only occurs when data changes.
                * @example
                * // This code creates a chart with random data that regenerates when you click the button created in the
                * second code snippet below
                *  $(document).ready(function () {
                * $("#wijbarchart").wijbarchart({
                *	seriesList: [createRandomSeriesList("2013")],
                *	seriesTransition: {
                *		duration: 800,
                *		easing: "easeOutBounce"
                *	}
                * });
                *	} );
                *	function reload() {
                *		$("#wijbarchart").wijbarchart("option", "seriesList", [createRandomSeriesList("2013")]);
                *	}
                
                *	function createRandomSeriesList(label) {
                *		var data = [],
                *			randomDataValuesCount = 12,
                *			labels = ["January", "February", "March", "April", "May", "June",
                *				"July", "August", "September", "October", "November", "December"],
                *			idx;
                *		for (idx = 0; idx < randomDataValuesCount; idx++) {
                *			data.push(Math.round(Math.random() * 100));
                *		}
                *		return {
                *			label: label,
                *			legendEntry: false,
                *			data: { x: labels, y: data }
                *		};
                *	}
                */
                this.seriesTransition = {
                    /**
                    * A value that determines whether to show animation in redrawing bars when the seriesList data changes.
                    * Set this option to false to disable this animation.
                    */
                    enabled: true,
                    /**
                    * A value that indicates how long to display the series transition animation in milliseconds.
                    */
                    duration: 400,
                    /**
                    * Sets the type of animation easing effect to use in redrawing bars when the seriesList data changes.
                    * @remarks
                    * The easing is defined in Raphael, the documentation is:http://raphaeljs.com/reference.html#Raphael.easing_formulas
                    */
                    easing: ">"
                };
            }
            return wijchartcore_options;
        })();
        chart.wijchartcore_options = wijchartcore_options;

        var wijchartcore_css = (function (_super) {
            __extends(wijchartcore_css, _super);
            function wijchartcore_css() {
                _super.apply(this, arguments);
                this.headerText = "wijchart-header-text";
                this.headerContainer = "wijchart-header-container";
                this.footerText = "wijchart-footer-text";
                this.footerContainer = "wijchart-footer-container";
                this.legendTitle = "wijchart-legend-title";
                this.legendText = "wijchart-legend-text";
                this.legend = "wijchart-legend";
                this.legendDot = "chart-legend-dot";
                this.legendIcon = "wijchart-legend-icon";
                this.legendContainer = "wijchart-legend-container";
                this.legendTextCover = "wijchart-legend-textCover";
                this.axis = "wijchart-axis";
                this.axisText = "wijchart-axis-text";
                this.axisGridLine = "wijchart-axis-gridline";
                this.axisTick = "wijchart-axis-tick";
                this.axisLabel = "wijchart-axis-label";
                this.labelText = "wijchart-label-text";
                this.labelConnect = "wijchart-label-connect";
                this.canvasObject = "wijchart-canvas-object";
                this.stateDisabled = "ui-state-disabled";
                this.trendlineElement = "trendlineElement";
                this.trendlineTracker = "trendlinetracker";
            }
            return wijchartcore_css;
        })(wijmo.wijmo_css);
        chart.wijchartcore_css = wijchartcore_css;

        wijchartcore.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijchartcore_options());

        

        

        //export class StrokeStyle
        //{
        //    constructor(stroke: string, width: number = 0.5, dasharray: string = "- ")
        //    {
        //        this.stroke = stroke;
        //        this["stroke-width"] = width;
        //        this["stroke-dasharray"] = dasharray;
        //    }
        //    stroke: string;
        //    "stroke-width": number;
        //    "stroke-dasharray": string;
        //}
        //export class TextStyle {
        //    constructor(fill : string, fontSize : number = 14, fontWeight: string = "normal") {
        //        this.fill = fill;
        //        this["font-size"] = fontSize;
        //        this["font-weight"] = fontWeight;
        //    }
        //    fill: string;
        //    "font-size": number;
        //    "font-weight": string;
        //}
        var ChartRendererUtil = (function () {
            function ChartRendererUtil() {
            }
            ChartRendererUtil._text = function (canvas, x, y, text, disableDefaultTextStyle) {
                var textElement = canvas.text(x, y, text);

                if (disableDefaultTextStyle) {
                    textElement.node["style"].cssText = "";
                }

                return textElement;
            };

            ChartRendererUtil._calculateRectPositionByCompass = function (bounds, compass, width, height) {
                var point = { x: 0, y: 0 }, marginX = 5, marginY = 5, canvasBounds = bounds;
                switch (compass) {
                    case "north":
                        point.x = (canvasBounds.endX - canvasBounds.startX) / 2;
                        point.y = canvasBounds.startY + height / 2 + marginY;
                        break;
                    case "south":
                        point.x = (canvasBounds.endX - canvasBounds.startX) / 2;
                        point.y = canvasBounds.endY - height / 2 - marginY;
                        break;
                    case "east":
                        point.x = canvasBounds.endX - width / 2 - marginX;
                        point.y = (canvasBounds.endY - canvasBounds.startY) / 2;
                        break;
                    case "west":
                        point.x = canvasBounds.startX + width / 2 + marginX;
                        point.y = (canvasBounds.endY - canvasBounds.startY) / 2;
                        break;
                }
                return point;
            };

            ChartRendererUtil._updateCanvasBoundsByCompass = function (bounds, compass, width, height) {
                var marginX = 5, marginY = 5, canvasBounds = bounds;
                switch (compass) {
                    case "north":
                        canvasBounds.startY = canvasBounds.startY + marginY * 2 + height;
                        break;
                    case "south":
                        canvasBounds.endY = canvasBounds.endY - marginY * 2 - height;
                        break;
                    case "east":
                        canvasBounds.endX = canvasBounds.endX - marginX * 2 - width;
                        break;
                    case "west":
                        canvasBounds.startX = canvasBounds.startX + marginX * 2 + width;
                        break;
                }
                return canvasBounds;
            };

            ChartRendererUtil._removeRaphaelEle = function (element) {
                if (element) {
                    var node = $(element.node);
                    node.unbind().removeData();
                    element.wijRemove();
                    node.remove();
                    node = null;
                }
                element = null;
            };

            ChartRendererUtil._getCulture = function (culture, cultureCalendar) {
                return $.wijGetCulture(culture, cultureCalendar);
            };
            return ChartRendererUtil;
        })();

        // ** ChartRenderers **
        /** @ignore */
        // ** BaseRendererOption **
        var BaseRendererOptions = (function () {
            function BaseRendererOptions() {
            }
            return BaseRendererOptions;
        })();
        chart.BaseRendererOptions = BaseRendererOptions;

        /** @ignore */
        // ** Base **
        var BaseRenderer = (function () {
            function BaseRenderer(canvas, options) {
                this.canvas = canvas;
                this._initData(options);
            }
            BaseRenderer.prototype.render = function () {
                this._clearElements();

                this._paint();
                this._bindLiveEvents();
            };

            BaseRenderer.prototype.redraw = function (newOpitons) {
                this._initData(newOpitons);
                this.render();
            };

            BaseRenderer.prototype.destroy = function () {
                this._clearElements();
                this.options = null;
                this.canvas = null;
            };

            BaseRenderer.prototype._initData = function (opts) {
                this.options = $.extend(false, {}, this.options, opts);
            };

            BaseRenderer.prototype._paint = function () {
            };

            BaseRenderer.prototype._bindLiveEvents = function () {
            };

            BaseRenderer.prototype._unbindLiveEvents = function () {
            };

            BaseRenderer.prototype._clearElements = function () {
                this._unbindLiveEvents();
            };

            BaseRenderer.prototype._text = function (x, y, text) {
                return ChartRendererUtil._text(this.canvas, x, y, text, this.options.disableDefaultTextStyle);
            };
            return BaseRenderer;
        })();
        chart.BaseRenderer = BaseRenderer;

        /** @ignore */
        // ** EdgeElement : Base of Title, Legend **
        // This element will be located at the edge of canvas,
        // rendering this element will make canvasBounds changed.
        var EdgeElement = (function (_super) {
            __extends(EdgeElement, _super);
            function EdgeElement() {
                _super.apply(this, arguments);
            }
            EdgeElement.prototype._initData = function (opts) {
                _super.prototype._initData.call(this, opts);

                this.updatedCanvasBounds = this.options.canvasBounds;
            };

            EdgeElement.prototype.render = function () {
                _super.prototype.render.call(this);
                this._getUpdatedCanvasBounds();
            };

            EdgeElement.prototype._getUpdatedCanvasBounds = function () {
                var o = this.options, bounds = o.canvasBounds, compass = o.compass, textBBox;

                if (this.container) {
                    textBBox = this.container.wijGetBBox();
                    this.updatedCanvasBounds = ChartRendererUtil._updateCanvasBoundsByCompass(bounds, compass, textBBox.width, textBBox.height);
                }
            };
            return EdgeElement;
        })(BaseRenderer);
        chart.EdgeElement = EdgeElement;

        /** @ignore */
        // ** Title **
        /*
        Options for title:
        text,
        visible,
        
        compass,
        canvasBounds,
        position,
        offset,
        
        textCSS,
        textStyle,
        containerCSS,
        containerStyle
        */
        var Title = (function (_super) {
            __extends(Title, _super);
            function Title(canvas, options) {
                _super.call(this, canvas, options);
                this.titleMargin = 2;
            }
            Title.prototype._paint = function () {
                this._paintTitle();
            };

            Title.prototype._paintTitle = function () {
                var o = this.options, text = o.text, visible = o.visible, compass = o.compass, rotation, titleTextClass = o.textCSS, titleTextStyle = o.textStyle, titleClass = o.containerCSS, titleStyle = o.containerStyle, textBox, rectBox, bounds = o.canvasBounds, position = o.position, offset = $.extend(offset, { x: 0, y: 0 }, o.offset);

                if (text && text.length > 0 && visible) {
                    this.titleTextEle = this._text(0, 0, text);
                    $.wijraphael.addClass($(this.titleTextEle.node), titleTextClass);

                    rotation = this._getTitleRotationByCompass(compass);

                    this.titleTextEle.attr(titleTextStyle);
                    this.titleTextEle.transform("...R" + rotation);
                    textBox = this.titleTextEle.wijGetBBox();

                    rectBox = {
                        width: textBox.width + 2 * this.titleMargin,
                        height: textBox.height + 2 * this.titleMargin
                    };
                    this.container = this.canvas.rect(0, 0, rectBox.width, rectBox.height);

                    if (compass && !position) {
                        position = ChartRendererUtil._calculateRectPositionByCompass(bounds, compass, textBox.width, textBox.height);
                    }
                    if (position) {
                        this._setTitlePosition(position);
                    }

                    $.wijraphael.addClass($(this.container.node), titleClass);
                    this.container.attr(titleStyle);
                    this.container.toBack();
                }
            };

            Title.prototype._getTitleRotationByCompass = function (compass) {
                var rotation = 0;

                if (compass === "east") {
                    rotation = 90;
                } else if (compass === "west") {
                    rotation = -90;
                }

                return rotation;
            };

            Title.prototype._setTitlePosition = function (position) {
                var offset = $.extend(offset, { x: 0, y: 0 }, this.options.offset), newPosition = {
                    x: position.x += offset.x,
                    y: position.y += offset.y
                }, containerSize = this.container.wijGetBBox();

                this.titleTextEle.transform(Raphael.format("...T{0},{1}", newPosition.x, newPosition.y));
                this.container.transform(Raphael.format("...T{0},{1}", newPosition.x - containerSize.width / 2, newPosition.y - containerSize.height / 2));
            };

            Title.prototype._clearElements = function () {
                _super.prototype._clearElements.call(this);
                var txtNode, retNode;

                ChartRendererUtil._removeRaphaelEle(this.titleTextEle);
                ChartRendererUtil._removeRaphaelEle(this.container);

                this.titleTextEle = null;
                this.container = null;
            };
            return Title;
        })(EdgeElement);
        chart.Title = Title;

        

        /** @ignore */
        // ** LegendOptions **
        var LegendRendererOptions = (function (_super) {
            __extends(LegendRendererOptions, _super);
            function LegendRendererOptions() {
                _super.apply(this, arguments);
            }
            return LegendRendererOptions;
        })(BaseRendererOptions);
        chart.LegendRendererOptions = LegendRendererOptions;

        

        

        /** @ignore */
        // ** Legend **
        var Legend = (function (_super) {
            __extends(Legend, _super);
            function Legend(canvas, options) {
                this.nodeSetList = [];
                this.nodeClass = "wijlegend-node";
                _super.call(this, canvas, options);
            }
            Legend.prototype._initData = function (opts) {
                if (this.options && opts.legendInfoList) {
                    this.options.legendInfoList = [];
                }
                _super.prototype._initData.call(this, opts);
            };

            Legend.prototype._paint = function () {
                this._paintLegend();
            };

            Legend.prototype._paintLegend = function () {
                var self = this, o = self.options, labelSet, iconSet, position;

                this.titleEle = this._paintTitle();

                $.each(o.legendInfoList, function (idx, legendInfo) {
                    labelSet = self._paintLabelSet(legendInfo);
                    iconSet = self._paintIconSet(legendInfo);

                    self.nodeSetList[idx] = $.extend(true, {}, self.nodeSetList[idx], {
                        label: labelSet.label,
                        labelCover: labelSet.labelCover,
                        icon: iconSet.icon,
                        marker: iconSet.marker
                    });
                });

                // Calculate layout informations
                self.layoutInfo = self._calculateLayout();
                position = self.layoutInfo.position;

                self.container = self._paintContainer(position.x, position.y, self.layoutInfo.width, self.layoutInfo.height);

                self._setElementsPosition();
            };

            // Position of title will be calculated and set after labels and icons rendered.
            Legend.prototype._paintTitle = function () {
                var o = this.options, titleText = o.title, titleEle;

                if (titleText && titleText.length) {
                    titleEle = this._text(0, 0, titleText);
                    $.wijraphael.addClass($(titleEle.node), o.titleCSS);
                    titleEle.wijAttr(o.titleStyle);
                }

                return titleEle;
            };

            Legend.prototype._paintContainer = function (x, y, width, height) {
                var o = this.options, container;

                container = this.canvas.rect(x, y, width, height);
                $.wijraphael.addClass($(container.node), o.legendCSS);
                container.attr(o.legendStyle);
                container.toBack();

                return container;
            };

            Legend.prototype._paintLabelSet = function (legendInfo) {
                var self = this, o = self.options, labelStyle = o.labelStyle, labelEles, labelEle, labelCover, bBox;

                if (o.labelWidth) {
                    labelEles = self.canvas.wrapText(0, 0, legendInfo.label, o.labelWidth, "far", labelStyle);
                    bBox = labelEles.wijGetBBox();
                } else {
                    labelEle = this._text(0, 0, legendInfo.label);
                    labelEle.wijAttr(labelStyle);
                    bBox = labelEle.wijGetBBox();
                    labelEles = [labelEle];
                }

                $.each(labelEles, function (i, t) {
                    $.wijraphael.addClass($(t.node), o.labelCSS + " " + self.nodeClass);
                    $(t.node).data("vOpacity", t.attr("opacity")).data("legendIndex", legendInfo.legendIdx).data("index", legendInfo.seriesIdx);

                    self._setElementVisibility(t, legendInfo.seriesVisible);
                });

                if (Raphael.vml) {
                    labelCover = self.canvas.rect(0, 0, bBox.width, bBox.height);
                    labelCover.attr({
                        stroke: "none",
                        fill: "#000000",
                        opacity: 0.01
                    });
                    $.wijraphael.addClass($(labelCover.node), o.labelCoverCSS + " " + self.nodeClass);
                    $(labelCover.node).data("legendIndex", legendInfo.legendIdx).data("index", legendInfo.seriesIdx);
                }

                return {
                    label: o.labelWidth ? labelEles : labelEle,
                    labelCover: labelCover
                };
            };

            Legend.prototype._paintIconSet = function (legendInfo) {
                var o = this.options, iconWidth = o.iconSize.width || 0, iconHeight = o.iconSize.height || 0, r, legendIndex = legendInfo.legendIdx, seriesIndex = legendInfo.seriesIdx, iconStyle = legendInfo.iconStyle, strokeWidth = iconStyle["stroke-width"] || 0, iconType = legendInfo.icon, markerType = legendInfo.markers, markerStyle = legendInfo.markerStyle, icon, marker;

                if (iconType === "rect") {
                    icon = this.canvas.rect(0, 0, iconWidth, iconHeight);
                } else if (iconType === "line") {
                    icon = this.canvas.path(Raphael.format("M{0},{1}L{2},{3}", 0, 0, iconWidth, 0));
                } else {
                    if (legendInfo.iconSize) {
                        r = legendInfo.iconSize.r;
                    }
                    if (!r) {
                        r = o.iconSize.r || 0;
                    }
                    icon = icon = this.canvas.paintMarker(iconType, 0, 0, r / 2);
                }
                if (iconStyle) {
                    icon.attr(iconStyle);
                }

                $(icon.node).data("vOpacity", icon.attr("opacity")).data("legendIndex", legendIndex).data("index", seriesIndex);

                $.wijraphael.addClass($(icon.node), o.iconCSS + " " + this.nodeClass);

                this._setElementVisibility(icon, legendInfo.seriesVisible);

                if (markerType && legendInfo.markerVisible) {
                    markerStyle = $.extend({
                        fill: iconStyle.fill,
                        stroke: iconStyle.stroke,
                        opacity: 1
                    }, markerStyle);

                    if (!markerType) {
                        markerType = "circle";
                    }
                    marker = this.canvas.paintMarker(markerType, 0, 0, 3);
                    $.wijraphael.addClass($(marker.node), this.options.markerCSS + " " + this.nodeClass);
                    marker.attr(markerStyle);
                    $(marker.node).data("vOpacity", marker.attr("opacity")).data("index", seriesIndex).data("legendIndex", legendIndex);

                    this._setElementVisibility(marker, legendInfo.seriesVisible);
                }
                return {
                    icon: icon,
                    marker: marker
                };
            };

            Legend.prototype._setElementVisibility = function (legendEle, eleVisible) {
                if (!legendEle) {
                    return;
                }
                var node = $(legendEle.node), vOpacity;
                if (!node || node.length === 0) {
                    return;
                }
                if (!eleVisible) {
                    legendEle.attr("opacity", "0.3");
                    node.data("hidden", true);
                } else {
                    vOpacity = node.data("vOpacity") || 1;
                    legendEle.attr("opacity", vOpacity);
                    node.data("hidden", false);
                }
            };

            Legend.prototype._calculateLayout = function () {
                var self = this, o = self.options, compass = o.compass, orientation = o.orientation, titleBox, titleHeight = 0, titleWidth = 0, bBox, maxLabelWidth = 0, maxLabelHeight = 0, legendLen = self.nodeSetList.length, totalWidth = 0, totalHeight = 0, iconWidth = o.iconSize.width || 0, iconHeight = o.iconSize.height || 0, legendMargin = o.legendMargin || 0, labelMargin = o.labelMargin, canvasBounds = o.canvasBounds, canvasWidth = canvasBounds.endX - canvasBounds.startX, canvasHeight = canvasBounds.endY - canvasBounds.startY, columnNum = 1, rowNum = 1, legendNodeWidth, legendNodeHeight, width, height, position;

                if (this.titleEle) {
                    titleBox = this.titleEle.wijGetBBox();
                    titleHeight = titleBox.height;
                    titleWidth = titleBox.width;
                }

                $.each(self.nodeSetList, function (idx, legendNodeSet) {
                    bBox = legendNodeSet.label.wijGetBBox();
                    if (bBox.width > maxLabelWidth) {
                        maxLabelWidth = bBox.width;
                    }
                    if (bBox.height > maxLabelHeight) {
                        maxLabelHeight = bBox.height;
                    }
                });

                legendNodeWidth = iconWidth + maxLabelWidth + legendMargin + labelMargin.left + labelMargin.right;
                legendNodeHeight = maxLabelHeight + labelMargin.top + labelMargin.bottom;

                totalWidth = legendLen * legendNodeWidth;
                totalHeight = legendLen * legendNodeHeight + titleHeight;
                if (compass === "east" || compass === "west") {
                    if (orientation === "horizontal") {
                        if (totalWidth > canvasWidth / 2) {
                            columnNum = Math.floor(canvasWidth / 2 / legendNodeWidth);
                            if (columnNum < 1) {
                                columnNum = 1;
                            }
                        } else {
                            columnNum = legendLen;
                        }
                    } else if (orientation === "vertical") {
                        if (totalHeight > canvasHeight) {
                            columnNum = Math.ceil(totalHeight / canvasHeight);
                        } else {
                            columnNum = 1;
                        }
                    }
                } else if (compass === "south" || compass === "north") {
                    if (orientation === "horizontal") {
                        if (totalWidth > canvasWidth) {
                            columnNum = Math.floor(legendLen / totalWidth * canvasWidth);
                            if (columnNum < 1) {
                                columnNum = 1;
                            }
                        } else {
                            columnNum = legendLen;
                        }
                    } else if (orientation === "vertical") {
                        if (totalHeight > canvasHeight / 2) {
                            rowNum = Math.floor(canvasHeight - titleHeight) / 2 / maxLabelHeight;
                            columnNum = Math.ceil(legendLen / rowNum);
                        } else {
                            columnNum = 1;
                        }
                    }
                }

                if (columnNum === 0) {
                    columnNum = 1;
                }

                width = columnNum * (maxLabelWidth + iconWidth + legendMargin) + columnNum * (labelMargin.left + labelMargin.right);
                rowNum = Math.ceil(legendLen / columnNum);
                height = maxLabelHeight * rowNum + titleHeight + rowNum * (labelMargin.top + labelMargin.bottom);

                width = width > titleWidth ? width : titleWidth;

                position = ChartRendererUtil._calculateRectPositionByCompass(canvasBounds, compass, width, height);
                position.x -= width / 2;
                position.y -= height / 2;

                return {
                    width: width,
                    height: height,
                    legendNodeWidth: legendNodeWidth,
                    legendNodeHeight: legendNodeHeight,
                    columnNum: columnNum,
                    rowNum: rowNum,
                    position: position
                };
            };

            Legend.prototype._setElementsPosition = function () {
                var self = this, o = self.options, compass = o.compass, legendMargin = o.legendMargin || 0, iconWidth = o.iconSize.width || 0, iconHeight = o.iconSize.height || 0, legendLayout = self.layoutInfo, position = legendLayout.position, width = legendLayout.width, height = legendLayout.height, legendNodeWidth = legendLayout.legendNodeWidth, legendNodeHeight = legendLayout.legendNodeHeight, columnNum = legendLayout.columnNum, columnIndex = 0, centerPoint, left, top, titleHeight = 0, offsetY;

                left = position.x;
                top = position.y;

                if (self.titleEle) {
                    titleHeight = self.titleEle.wijGetBBox().height;
                    self.titleEle.transform(Raphael.format("...T{0},{1}", left + width / 2, top + titleHeight / 2));
                }

                offsetY = titleHeight;

                $.each(self.nodeSetList, function (idx, legendNodeSet) {
                    var legendInfo = self.options.legendInfoList[idx], iconType = legendInfo.icon, label = legendNodeSet.label, labelCover = legendNodeSet.labelCover, icon = legendNodeSet.icon, marker = legendNodeSet.marker, labelBBox, strokeWidth, label0, x, y;

                    strokeWidth = legendInfo.iconStyle["stroke-width"] || 0;

                    x = left + columnIndex * legendNodeWidth + o.labelMargin.left + columnIndex * strokeWidth;
                    y = top + offsetY + legendNodeHeight / 2;

                    labelBBox = label.wijGetBBox();
                    label0 = o.labelWidth ? label[0] : label;

                    if (iconType === "rect") {
                        icon.transform(Raphael.format("...T{0},{1}", x, y - iconHeight / 2 - strokeWidth));
                    } else if (iconType === "line") {
                        icon.transform(Raphael.format("...T{0},{1}", x, y));
                    } else {
                        icon.transform(Raphael.format("...T{0},{1}", x + iconWidth / 2, y));
                    }
                    if (marker) {
                        marker.transform(Raphael.format("...T{0},{1}", x + iconWidth / 2, y));
                    }

                    if (o.labelStyle["text-anchor"] === "start") {
                        x -= labelBBox.width / 2;
                    }

                    if (o.labelWidth) {
                        label.transform(Raphael.format("...T{0},{1}", x + iconWidth + legendMargin, y - labelBBox.height / 2));
                    } else {
                        label.transform(Raphael.format("...T{0},{1}", x + iconWidth + legendMargin + labelBBox.width / 2, y));
                    }
                    if (labelCover) {
                        labelCover.transform(Raphael.format("...T{0},{1}", x + iconWidth + legendMargin, y - labelBBox.height / 2));
                        labelCover.toFront();
                    }
                    label.toFront();

                    columnIndex++;
                    if (columnIndex === columnNum) {
                        columnIndex = 0;
                        offsetY += legendNodeHeight;
                    }
                });
            };

            Legend.prototype._bindLiveEvents = function () {
                var self = this, o = self.options;

                $(self.canvas.canvas).on("click.Legend", "." + this.nodeClass, function (e) {
                    self._triggerNodeClick($(e.currentTarget));
                });
            };

            Legend.prototype._triggerNodeClick = function (node) {
                var legendIdx = node.data("legendIndex"), seriesIdx = node.data("index"), nodeVisible = !node.data("hidden"), clickFunc = this.options.legendClickFunc, eventData, vOpacity, legendNodeSet, labelCover;

                if (this.options.disabled) {
                    return;
                }

                eventData = {
                    seriesIdx: node.data("index"),
                    legendIdx: node.data("legendIndex"),
                    visible: nodeVisible
                };
                legendNodeSet = this.nodeSetList[legendIdx];

                var result = true;
                if (clickFunc && typeof clickFunc === "function") {
                    result = (clickFunc(eventData) !== "false");
                }
                if (result) {
                    this._setElementVisibility(legendNodeSet.label, !nodeVisible);
                    this._setElementVisibility(legendNodeSet.icon, !nodeVisible);
                    this._setElementVisibility(legendNodeSet.marker, !nodeVisible);

                    labelCover = legendNodeSet.labelCover;
                    if (labelCover) {
                        if (nodeVisible) {
                            $(labelCover.node).data("hidden", true);
                        } else {
                            $(labelCover.node).data("hidden", false);
                        }
                    }
                }
            };

            Legend.prototype._unbindLiveEvents = function () {
                _super.prototype._unbindLiveEvents.call(this);

                $(this.canvas.canvas).off("click.Legend");
            };

            Legend.prototype._clearElements = function () {
                _super.prototype._clearElements.call(this);

                ChartRendererUtil._removeRaphaelEle(this.titleEle);
                this.titleEle = null;

                for (var i = 0; i < this.nodeSetList.length; i++) {
                    ChartRendererUtil._removeRaphaelEle(this.nodeSetList[i].label);
                    ChartRendererUtil._removeRaphaelEle(this.nodeSetList[i].labelCover);
                    ChartRendererUtil._removeRaphaelEle(this.nodeSetList[i].icon);
                    ChartRendererUtil._removeRaphaelEle(this.nodeSetList[i].marker);
                    this.nodeSetList[i] = null;
                }
                this.nodeSetList = [];
            };
            return Legend;
        })(EdgeElement);
        chart.Legend = Legend;

        /** @ignore */
        // ** AxisOptions **
        var AxisRendererOptions = (function (_super) {
            __extends(AxisRendererOptions, _super);
            function AxisRendererOptions() {
                _super.apply(this, arguments);
            }
            return AxisRendererOptions;
        })(BaseRendererOptions);
        chart.AxisRendererOptions = AxisRendererOptions;

        /** @ignore */
        // ** Axis **
        var Axis = (function (_super) {
            __extends(Axis, _super);
            function Axis(canvas, options) {
                this.thickness = 2;
                this.majorSizeFactor = 3;
                this.minorSizeFactor = 2;
                this.canvasBounds = options.canvasBounds;
                _super.call(this, canvas, options);

                this.axisDotGroupList = [];
                this.axisElements = [];
            }
            Axis.prototype._initData = function (opts) {
                _super.prototype._initData.call(this, opts);

                this._initStartEndPoints();

                this.majorTickRect = this._getTickRect(true);
                this.minorTickRect = this._getTickRect(false);

                this.majorTickValues = this._getMajorTickValues();
                this.minorTickValues = this._getMinorTickValues();
            };

            Axis.prototype._initStartEndPoints = function () {
                var o = this.options, compass = o.compass, bounds = o.canvasBounds;

                var startPoint = { x: 0, y: 0 }, endPoint = { x: 0, y: 0 }, thickness = this.thickness;

                switch (compass) {
                    case "south":
                        startPoint.x = bounds.startX;
                        startPoint.y = bounds.endY;
                        endPoint.x = bounds.endX;
                        endPoint.y = bounds.endY;
                        break;
                    case "north":
                        startPoint.x = bounds.startX;
                        startPoint.y = bounds.startY - thickness;
                        endPoint.x = bounds.endX;
                        endPoint.y = bounds.startY - thickness;
                        break;
                    case "east":
                        startPoint.x = bounds.endX - thickness;
                        startPoint.y = bounds.endY;
                        endPoint.x = bounds.endX - thickness;
                        endPoint.y = bounds.startY;
                        if (o.axisOffset) {
                            startPoint.x += o.axisOffset;
                            endPoint.x += o.axisOffset;
                        }
                        break;
                    case "west":
                        startPoint.x = bounds.startX;
                        startPoint.y = bounds.endY;
                        endPoint.x = bounds.startX;
                        endPoint.y = bounds.startY;
                        if (o.axisOffset) {
                            startPoint.x -= o.axisOffset;
                            endPoint.x -= o.axisOffset;
                        }
                        break;
                }

                this.startPoint = startPoint;
                this.endPoint = endPoint;
            };

            Axis.prototype._paint = function () {
                var self = this;
                self.axisElements = [];
                self._paintAxis();

                if (self.axisMainLineEle) {
                    self.axisElements.push(self.axisMainLineEle);
                }

                $.each(self.axisDotGroupList, function (idx, dotGroup) {
                    if (dotGroup.tick) {
                        self.axisElements.push(dotGroup.tick);
                    }
                    if (dotGroup.label) {
                        self.axisElements.push(dotGroup.label);
                    }
                    if (dotGroup.gridSet) {
                        if (dotGroup.gridSet.gridLine) {
                            self.axisElements.push(dotGroup.gridSet.gridLine);
                        }
                        if (dotGroup.gridSet.vlGridLine) {
                            self.axisElements.push(dotGroup.gridSet.vlGridLine);
                        }
                    }
                });

                if (self.axisTitleEle) {
                    self.axisElements.push(self.axisTitleEle);
                }
            };

            Axis.prototype._paintAxis = function () {
                var self = this, o = self.options, canvasBounds = o.canvasBounds, startPoint = self.startPoint, endPoint = self.endPoint, compass = o.compass, isVertical = (compass === "east" || compass === "west"), max = o.max, min = o.min, labelInfo = o.labelOptions, maxLen = 0, index = 0, formatString = o.annoFormatString, labelObjs = [], labelEle, labelEleBox, len, labelOffset;

                self.axisMainLineEle = self._paintMainAxisLine();

                $.each(this.majorTickValues, function (idx, val) {
                    var text = val, isTime = o.isTime, is100Percent = o.is100Percent, vlGridLine = false, vlGridLineStyle = {}, singleDotGroup;

                    if (val < min || val > max) {
                        index++;
                        return true;
                    }

                    if (o.annoMethod === "valueLabels") {
                        if (index >= o.valueLabels.length) {
                            return false;
                        }
                        text = o.valueLabels[index];
                        vlGridLine = text.gridLine;
                        vlGridLineStyle = text.gridLineStyle;
                        if (text.text !== null && text.text !== undefined) {
                            text = text.text;
                        } else if (typeof text.value !== "undefined") {
                            text = text.value;
                            if (o.annoFormatString && o.annoFormatString.length) {
                                text = Globalize.format(text, o.annoFormatString, ChartRendererUtil._getCulture(o.culture, o.cultureCalendar));
                            }
                        }
                    } else if (o.annoMethod === "values") {
                        if (o.annoFormatString && o.annoFormatString.length) {
                            if (isTime) {
                                text = $.fromOADate(val);
                            }
                            text = Globalize.format(text, o.annoFormatString, ChartRendererUtil._getCulture(o.culture, o.cultureCalendar));
                        } else if (is100Percent) {
                            text = Globalize.format(val, "p0", ChartRendererUtil._getCulture(o.culture, o.cultureCalendar));
                        }
                    }
                    singleDotGroup = self._paintSingleDotGroup(val, text, true, vlGridLine, vlGridLineStyle);

                    self.axisDotGroupList.push(singleDotGroup);

                    labelEle = singleDotGroup.label;
                    if (labelEle) {
                        labelEleBox = labelEle.getBBox();
                        len = isVertical ? labelEleBox.width : labelEleBox.height;
                        if (maxLen < len) {
                            maxLen = len;
                        }
                        labelObjs.push({
                            label: labelEle,
                            length: len
                        });
                    }

                    index++;
                });

                if (!labelInfo.width && labelInfo.textAlign !== "center") {
                    $.each(labelObjs, function (idx, labelObj) {
                        labelEle = labelObj.label;
                        if (labelEle) {
                            len = labelObj.length;
                            labelOffset = (len - maxLen) / 2;
                            labelOffset = labelInfo.textAlign === "near" ? labelOffset * -1 : labelOffset;
                            if (isVertical) {
                                labelEle.transform(Raphael.format("...T{0},{1}", labelOffset, 0));
                            } else {
                                labelEle.transform(Raphael.format("...T{0},{1}", 0, labelOffset));
                            }
                        }
                    });
                }

                $.each(this.minorTickValues, function (idx, val) {
                    self.axisDotGroupList.push(self._paintSingleDotGroup(val, null, false));
                });

                self.axisTitleEle = this._paintAxisTitle();
            };

            Axis.prototype._paintMainAxisLine = function () {
                var axisMainLineEle, o = this.options, startPoint = this.startPoint, endPoint = this.endPoint;

                if (o.visible) {
                    axisMainLineEle = this.canvas.line(startPoint.x, startPoint.y, endPoint.x, endPoint.y).attr(o.axisStyle);
                    $.wijraphael.addClass($(axisMainLineEle.node), o.axisCSS);
                }

                return axisMainLineEle;
            };

            Axis.prototype._paintSingleDotGroup = function (tickValue, text, isMajor, vlGridLine, vlGridLineStyle) {
                var tickElement, singleGridSet, labelElement, self = this, o = self.options, tickInfo = (isMajor ? o.tickMajor : o.tickMinor), tickRect = (isMajor ? this.majorTickRect : this.minorTickRect), grid = (isMajor ? o.gridMajor : o.gridMinor), positionInfo;

                positionInfo = self._getSingleDotPositionInfo(tickValue, tickInfo, tickRect);

                singleGridSet = this._paintGridLine(positionInfo.x, positionInfo.y, grid, vlGridLine, vlGridLineStyle);
                tickElement = this._paintTick(positionInfo.x, positionInfo.y, tickInfo, tickRect);

                if (text != null && text !== undefined) {
                    labelElement = this._paintLabel(positionInfo.labelX, positionInfo.labelY, text.toString());
                }
                return {
                    tick: tickElement,
                    label: labelElement,
                    gridSet: singleGridSet
                };
            };

            Axis.prototype._getSingleDotPositionInfo = function (tickValue, tickInfo, tickRect) {
                var x, y, labelX = -1, labelY = -1, o = this.options, max = o.max, min = o.min, tick = tickInfo.position, tHeight = tickRect.height, tWidth = tickRect.width, labelWidth = o.labelOptions.width, axisMaxLabelSize = o.axisMaxLabelSize, axisLabelOffset = o.axisLabelOffset, startPoint = this.startPoint, endPoint = this.endPoint, compass = o.compass, isVertical = (compass === "east" || compass === "west");

                x = startPoint.x;
                y = startPoint.y;

                switch (compass) {
                    case "south":
                        if (tick === "inside") {
                            y -= tHeight;
                        } else if (tick === "cross") {
                            y -= tHeight / 2;
                        }
                        if (labelWidth) {
                            labelY = y + axisLabelOffset + tHeight;
                        } else {
                            labelY = y + axisLabelOffset + tHeight + axisMaxLabelSize / 2;
                        }
                        break;
                    case "north":
                        if (tick === "outside") {
                            y -= tHeight;
                        } else if (tick === "cross") {
                            y -= tHeight / 2;
                        }
                        if (labelWidth) {
                            labelY = y - (axisLabelOffset + axisMaxLabelSize);
                        } else {
                            labelY = y - (axisLabelOffset + axisMaxLabelSize / 2);
                        }
                        break;
                    case "west":
                        if (tick === "outside") {
                            x -= tWidth;
                        } else if (tick === "cross") {
                            x -= tWidth / 2;
                        }
                        if (labelWidth) {
                            labelX = x - (axisLabelOffset + axisMaxLabelSize);
                        } else {
                            labelX = x - (axisLabelOffset + axisMaxLabelSize / 2);
                        }
                        break;
                    case "east":
                        if (tick === "inside") {
                            x -= tWidth;
                        } else if (tick === "cross") {
                            x -= tWidth / 2;
                        }
                        if (labelWidth) {
                            labelX = x + axisLabelOffset + tWidth;
                        } else {
                            labelX = x + axisLabelOffset + tWidth + axisMaxLabelSize / 2;
                        }
                        break;
                }

                if (isVertical) {
                    y += (tickValue - min) / (max - min) * (endPoint.y - startPoint.y);
                    labelY = y;
                } else {
                    x += (tickValue - min) / (max - min) * (endPoint.x - startPoint.x);
                    if (labelWidth) {
                        labelX = x - labelWidth / 2;
                    } else {
                        labelX = x;
                    }
                }

                return {
                    x: x, y: y,
                    labelX: labelX, labelY: labelY
                };
            };

            Axis.prototype._paintGridLine = function (x, y, gridInfo, vGridLine, vlGridLineStyle) {
                var o = this.options, bs = o.canvasBounds, isVertical = (o.compass === "east" || o.compass === "west"), arrPath, gridEle, vlGridEle;

                if (isVertical) {
                    arrPath = ["M", bs.startX, y, "H", bs.endX];
                } else {
                    arrPath = ["M", x, bs.startY, "V", bs.endY];
                }

                if (gridInfo.visible) {
                    gridEle = this.canvas.path(arrPath.join(" "));
                    $.wijraphael.addClass($(gridEle.node), o.gridCSS);
                    gridEle.attr(gridInfo.style);
                }
                if (vGridLine) {
                    vlGridEle = this.canvas.path(arrPath.join(" "));
                    $.wijraphael.addClass($(vlGridEle.node), o.gridCSS);
                    vlGridEle.attr($.extend(true, {}, gridInfo.style, vlGridLineStyle));
                }

                return {
                    gridLine: gridEle,
                    vlGridLine: vlGridEle
                };
                // TODO in chartcore: Hide or remove the gridLine which has same position with other "Axis Main Line".
            };

            Axis.prototype._paintTick = function (x, y, tickInfo, tickRect) {
                var o = this.options, tickPosition = tickInfo.position, tickStyle = tickInfo.style, isVertical = (o.compass === "east" || o.compass === "west"), style = { "stroke-width": 2 }, pathArr, tickElement;

                if (isVertical) {
                    if (tickPosition !== "none") {
                        pathArr = ["M", x, y, "h", tickRect.width];
                        tickStyle["stroke-width"] = tickRect.height;
                    }
                } else {
                    if (tickPosition !== "none") {
                        pathArr = ["M", x, y, "v", tickRect.height];
                        tickStyle["stroke-width"] = tickRect.width;
                    }
                }

                if (tickPosition !== "none") {
                    tickElement = this.canvas.path(pathArr.join(" "));
                    $.wijraphael.addClass($(tickElement.node), o.tickCSS);
                    style = $.extend(style, tickStyle);
                    tickElement.attr(style);
                }

                return tickElement;
            };

            Axis.prototype._paintLabel = function (x, y, text) {
                var self = this, o = self.options, textVisible = o.titleVisible, textStyle = o.labelStyle, textAlign = o.labelOptions.textAlign, labelWidth = o.labelOptions.width, txt, textBounds, textEle, isVertical = o.compass === "east" || o.compass === "west";

                if (text !== null && textVisible) {
                    if (labelWidth) {
                        txt = self.canvas.wrapText(x, y, text.toString(), labelWidth, textAlign, textStyle);
                        $.wijraphael.addClass($(txt.node), o.labelCSS);
                    } else {
                        txt = this._text(x, y, text.toString());
                        $.wijraphael.addClass($(txt.node), o.labelCSS);
                        txt.attr(textStyle);
                    }
                }
                return txt;
            };

            Axis.prototype._paintAxisTitle = function () {
                var axisTitleElement, self = this, o = self.options, canvasBounds = o.canvasBounds, titleText = o.titleText, titleTextStyle = o.titleStyle, compass = o.compass, align = o.titleAlignment, isVertical = (compass === "east" || compass === "west"), axisOffset = o.axisOffset, axisLabelOffset = o.axisLabelOffset, tickRectMajor = this.majorTickRect, tickPosition = o.tickMajor.position, tickLength = isVertical ? tickRectMajor.width : tickRectMajor.height, startX = canvasBounds.startX, startY = canvasBounds.startY, endX = canvasBounds.endX, endY = canvasBounds.endY, x = startX, y = startY, margin = { top: 0, bottom: 0, left: 0, right: 0 }, titleBounds;

                if (!(titleText && titleText.length)) {
                    return null;
                }
                axisTitleElement = this._text(0, 0, titleText.toString());
                axisTitleElement.attr(titleTextStyle);
                $.wijraphael.addClass($(axisTitleElement.node), o.titleCSS);

                titleBounds = axisTitleElement.wijGetBBox();

                $.each(["top", "bottom", "left", "right"], function (idx, marginKey) {
                    var value = titleTextStyle["margin-" + marginKey];
                    if (value) {
                        margin[marginKey] = parseFloat(value);
                    }
                });

                if (tickPosition === "cross") {
                    tickLength = tickLength / 2;
                } else if (tickPosition === "inside") {
                    tickLength = 0;
                }

                if (isVertical) {
                    switch (align) {
                        case "near":
                            y = endY - titleBounds.width / 2;
                            break;
                        case "center":
                            y = (startY + endY) / 2;
                            break;
                        case "far":
                            y = startY + titleBounds.width / 2;
                            break;
                    }
                    if (compass === "west") {
                        x = startX - (o.axisMaxLabelSize + axisOffset + axisLabelOffset + tickLength + titleBounds.height / 2 + margin["right"]);
                    } else {
                        x = endX + o.axisMaxLabelSize + axisOffset + axisLabelOffset + tickLength + titleBounds.height / 2 + margin["left"];
                    }
                } else {
                    switch (align) {
                        case "near":
                            x = startX + titleBounds.width / 2;
                            break;
                        case "center":
                            x = (startX + endX) / 2;
                            break;
                        case "far":
                            x = endX - titleBounds.width / 2;
                            break;
                    }
                    if (compass === "north") {
                        y = startY - (o.axisMaxLabelSize + axisLabelOffset + tickLength + titleBounds.height / 2 + margin["bottom"]);
                    } else {
                        y = endY + o.axisMaxLabelSize + axisLabelOffset + tickLength + titleBounds.height / 2 + margin["top"];
                    }
                }

                axisTitleElement.attr({ x: x, y: y });

                if (isVertical) {
                    axisTitleElement.transform("...R-90");
                }

                return axisTitleElement;
            };

            Axis.prototype._getTickRect = function (isMajor) {
                var o = this.options, compass = o.compass, sizeFactor = 0, tickInfo = isMajor ? o.tickMajor : o.tickMinor, factor = tickInfo.factor, position = tickInfo.position, tickSizeFactor = isMajor ? this.majorSizeFactor : this.minorSizeFactor, r = { x: 0, y: 0, width: 0, height: 0 };

                factor = factor > 0 ? factor : 1;
                sizeFactor = (tickSizeFactor * factor);

                if (position === "none") {
                    sizeFactor = 0;
                }
                if (compass === "east" || compass === "west") {
                    r = { x: 0, y: -1, width: sizeFactor * this.thickness, height: this.thickness };
                    if ((compass === "east" && position === "outside") || (compass === "west" && position === "inside")) {
                        r.width += 2; // TODO: make sure what the "2" is for.
                    } else {
                        if (position === "cross") {
                            r.width <<= 1;
                        }
                        r.width += 2;
                    }
                } else {
                    r = { x: -1, y: 0, width: this.thickness, height: sizeFactor * this.thickness };
                    if ((compass === "south" && position === "outside") || (compass === "north" && position === "inside")) {
                        r.height += 2;
                    } else {
                        if (position === "cross") {
                            r.height <<= 1;
                        }
                        r.height += 2;
                    }
                }

                return r;
            };

            Axis.prototype._getMajorTickValues = function () {
                var o = this.options, rc = [], autoTick = o.autoMajor, unitTick = o.unitMajor, max, min, valueLabels = o.valueLabels;

                if (o.annoMethod === "valueLabels") {
                    if (valueLabels && valueLabels.length > 0) {
                        $.each(valueLabels, function (idx, valueLabel) {
                            if (typeof valueLabel.text !== "undefined" || typeof valueLabel.value !== "undefined") {
                                return false;
                            }
                            if (typeof valueLabel === "string") {
                                valueLabels[idx] = {
                                    text: valueLabel,
                                    gridLine: false
                                };
                            } else {
                                valueLabels[idx] = {
                                    value: valueLabel,
                                    gridLine: false
                                };
                            }
                        });

                        if (typeof valueLabels[0].value !== "undefined") {
                            rc = this._getSortedDataValues();
                            return rc;
                        }
                    }
                }

                max = autoTick ? o.max : o.originalMax;
                min = autoTick ? o.min : o.originalMin;

                rc = this._getTickValues(max, min, unitTick, o.tprec, !o.isTime, autoTick);

                return rc;
            };

            Axis.prototype._getMinorTickValues = function () {
                var o = this.options, rc = [], autoTick = o.autoMinor, unitTick = o.unitMinor, max, min, i = 0, j = 0, minorTickValue = null, majorTickValue = null;

                max = autoTick ? o.max : o.originalMax;
                min = autoTick ? o.min : o.originalMin;

                rc = this._getTickValues(max, min, unitTick, o.tprec, !o.isTime, autoTick);

                for (i = rc.length - 1; i >= 0; i--) {
                    minorTickValue = rc[i];
                    for (j = this.majorTickValues.length - 1; j >= 0; j--) {
                        majorTickValue = this.majorTickValues[j];
                        if (minorTickValue === majorTickValue) {
                            rc.splice(i, 1);
                        }
                    }
                }
                return rc;
            };

            Axis.prototype._getSortedDataValues = function () {
                var self = this, o = this.options, rc = [], valueLabels = o.valueLabels;
                $.each(valueLabels, function (idx, label) {
                    var val = label.value;
                    if (ChartUtil.isDate(val)) {
                        rc.push($.toOADate(val));
                    } else if (typeof val === 'number') {
                        rc.push(val);
                    } else {
                        rc.push(idx);
                    }
                });

                // TODO: ignore blank labels.
                return rc;
            };

            Axis.prototype._getTickValues = function (smax, smin, unit, tickprec, round, autoTick) {
                var self = this, vals = [], value, sminOriginal = smin, smaxOriginal = smax, i = 0, xs = 0, imax = 0, imin = 0, n = 0, smin2 = 0;

                try  {
                    if (unit === 0) {
                        vals = [smax, smin];
                    } else {
                        if (autoTick) {
                            if (tickprec + 1 < 0) {
                                tickprec = -1;
                            } else if (tickprec + 1 > 15) {
                                tickprec = 14;
                            }
                            smin2 = $.round(ChartDataUtil.signedCeiling(smin / unit) * unit, tickprec + 1);
                            if (smin2 < smax) {
                                smin = smin2;
                            }
                            imax = parseInt($.round(smax / unit, 5).toString(), 10);
                            imin = parseInt($.round(smin / unit, 5).toString(), 10);
                            n = parseInt((imax - imin + 1).toString(), 10);
                            if (n > 1) {
                                xs = imin * unit;
                                if (xs < smin) {
                                    n--;
                                    smin += unit;
                                }
                                xs = smin + (n - 1) * unit;
                                if (xs > smax) {
                                    n--;
                                }
                            }
                            if (n < 1) {
                                n = 2;
                                smin = sminOriginal;
                                unit = smax - smin;
                            }
                        } else {
                            n = parseInt(((smax - smin) / unit + 1).toString(), 10);
                            if (n > 1) {
                                xs = smin + (n - 1) * unit;
                                if (xs > smax) {
                                    n--;
                                }
                            }
                            if (n < 1) {
                                n = 2;
                                unit = smax - smin;
                            }
                        }

                        for (i = 0; i < n; i++) {
                            if (round) {
                                // vals[i] = $.round(smin + i * unit, tickprec + 1);
                                if (autoTick) {
                                    value = $.round(smin + i * unit, tickprec + 1);
                                } else {
                                    value = smin + i * unit;
                                }
                            } else {
                                value = smin + i * unit;
                            }
                            if (value <= smaxOriginal && value >= sminOriginal) {
                                vals.push(value);
                            }
                        }
                    }
                } catch (error) {
                }

                return vals;
            };

            Axis.prototype._clearElements = function () {
                _super.prototype._clearElements.call(this);

                for (var i = 0; i < this.axisElements.length; i++) {
                    ChartRendererUtil._removeRaphaelEle(this.axisElements[i]);
                    this.axisElements[i] = null;
                }

                this.axisMainLineEle = null;
                this.axisTitleEle = null;
                this.axisDotGroupList = [];
                this.axisElements = [];
            };
            return Axis;
        })(BaseRenderer);
        chart.Axis = Axis;

        /** @ignore */
        // ** Series **
        var Series = (function (_super) {
            __extends(Series, _super);
            function Series(canvas, options) {
                _super.call(this, canvas, options);
            }
            Series.prototype.render = function () {
                _super.prototype.render.call(this);
            };
            return Series;
        })(BaseRenderer);
        chart.Series = Series;

        /** @ignore */
        var BaseChartRender = (function () {
            function BaseChartRender(element, options) {
                var self = this;
                self.options = options;
                self.element = element;
                self._init();
            }
            BaseChartRender.prototype._init = function () {
                var self = this, o = self.options, bounds = o.bounds;
                self.fields = self.element.data("fields") || {};
                self.chartElements = self.fields.chartElements || {};
                self.canvas = o.canvas;
                self.annoTooltip = new ChartTooltip(self.canvas, null, {
                    contentStyle: {
                        fill: "#d1d1d1",
                        "font-size": 16
                    },
                    style: {
                        fill: "#000000",
                        "stroke-width": 2
                    },
                    compass: "north",
                    offsetX: 0,
                    offsetY: 0,
                    relativeTo: "mouse",
                    mouseTrailing: true,
                    showDelay: 0,
                    hideDelay: 0,
                    isContentHtml: (o.widget.options.hint ? o.widget.options.hint.isContentHtml : false),
                    beforeShowing: function (e, d) {
                        var tooltip = o.widget.tooltip;
                        if (tooltip && !tooltip.isContentHtml) {
                            tooltip.hide(true);
                        }

                        self.annoTooltip.setOptions({ content: $(this.target).data("tooltip") });
                    }
                });
                if (bounds) {
                    self.width = bounds.endX - bounds.startX;
                    self.height = bounds.endY - bounds.startY;
                }
            };

            /**Gets the position of the chart element specified by the series index and point index.
            * @ignore
            */
            BaseChartRender.prototype.getChartElementPosition = function (seriesIndex, pointIndex) {
                var self = this, widget = self.options.widget, series, loc, valuesX, valuesY;
                if (!self.annoPoints[seriesIndex] || !self.annoPoints[seriesIndex][pointIndex]) {
                    // trendLine
                    series = (widget.options.seriesList)[seriesIndex];
                    if (series.isTrendline) {
                        valuesX = ChartUtil.getNumberValues(series.data.x);
                        valuesY = ChartUtil.getNumberValues(series.data.y);
                        return self.getDataPosition(valuesX[pointIndex], valuesY[pointIndex]);
                    }
                    return;
                }
                loc = self.annoPoints[seriesIndex][pointIndex];
                return { x: loc.x, y: loc.y };
            };

            /**
            * Gets the position of the data specified by x data and y data.
            * @param {any} x The data value for axis x.
            * @param {any} y The data value for axis y.
            * @returns {Point} a Point object which indicates the position of the data.
            */
            BaseChartRender.prototype.getDataPosition = function (x, y) {
                return BaseChartRender.calculateDataPosition(x, y, this);
            };

            BaseChartRender.calculateDataPosition = function (x, y, chartRender, inverted) {
                if (typeof inverted === "undefined") { inverted = false; }
                var _x, _y, o = chartRender.options, axisX = o.axis.x, axisY = $.isArray(o.axis.y) ? o.axis.y[0] : o.axis.y;

                if (x instanceof Date) {
                    x = $.toOADate(x);
                }
                if (y instanceof Date) {
                    y = $.toOADate(y);
                }
                _x = BaseChartRender._convertDataToLen(chartRender.width, inverted ? axisY : axisX, inverted ? y : x) + o.bounds.startX;
                _y = BaseChartRender._convertDataToLen(chartRender.height, inverted ? axisX : axisY, inverted ? x : y, true) + o.bounds.startY;
                return { x: _x, y: _y };
            };

            BaseChartRender._convertDataToLen = function (total, axis, val, converted) {
                if (typeof converted === "undefined") { converted = false; }
                var min = axis.min == null ? axis.actualMin : axis.min, max = axis.max == null ? axis.actualMax : axis.max;
                if (converted) {
                    return total * (1 - (val - min) / (max - min));
                } else {
                    return total * (val - min) / (max - min);
                }
            };

            /**
            * Render the chart.
            */
            BaseChartRender.prototype.render = function () {
                this.paintAnnotations();
            };

            BaseChartRender.prototype.paintAnnotations = function () {
                var self = this, annotations = self.options.annotations;
                if (!$.isArray(annotations) || annotations.length === 0) {
                    return;
                }

                if (self.fields.annotationTrackers) {
                    self.fields.annotationTrackers = null;
                }

                $.each(annotations, function (i, annotation) {
                    // add the codes to render annotation.
                    // build the relationship for the annotation which attachment is DataIndex.
                    self._paintAnnotation(annotation);
                });
                if (annotations.length && self.fields.annotationTrackers) {
                    self.annoTooltip.setOptions({ relatedElement: self.fields.annotationTrackers[0] });
                }
            };

            BaseChartRender.prototype._changeFirstCharUpper = function (val) {
                var tmp = val;
                tmp = val[0].toUpperCase();
                tmp += val.substr(1);
                return tmp;
            };

            // draw the annotation and build/manage the relationship.
            BaseChartRender.prototype._paintAnnotation = function (annotationOpt) {
                var self = this, annotation, annotationCtor = wijmo.chart[self._changeFirstCharUpper(annotationOpt.type)], seriesList = self.options.seriesList;

                if (annotationCtor == null) {
                    return;
                }
                annotation = new annotationCtor(annotationOpt);
                annotation.render(self);
                if (annotation.attachment == "dataIndex") {
                    self._updateBoundAnnotations(annotation);
                }
                return annotation;
            };

            //build/manage the relationship.
            BaseChartRender.prototype._updateBoundAnnotations = function (annotation) {
                var self = this, seriesIndex = annotation.seriesIndex, pointIndex = annotation.pointIndex;

                if (seriesIndex == null || pointIndex == null) {
                    return;
                }
                if (self.fields.boundAnnotations == null) {
                    self.fields.boundAnnotations = {};
                }
                if (self.fields.boundAnnotations[seriesIndex] == null) {
                    self.fields.boundAnnotations[seriesIndex] = {};
                }
                self.fields.boundAnnotations[seriesIndex][pointIndex] = annotation;
            };
            return BaseChartRender;
        })();
        chart.BaseChartRender = BaseChartRender;

        

        /** @ignore */
        var AnnotationBase = (function () {
            /**
            * Initializes a new instance of an @see:AnnotationBase object.
            * @param options A JavaScript object containing initialization data
            * for @see:AnnotationBase.
            */
            function AnnotationBase(options) {
                this.attachment = "absolute";
                this.point = { x: 0, y: 0 };
                this.seriesIndex = 0;
                this.pointIndex = 0;
                this.position = "center";
                this.offset = { x: 0, y: 0 };
                this.style = {};
                this.isVisible = true;
                this.tooltip = "";
            }
            //only copy properties
            AnnotationBase.prototype._setOptions = function (options) {
                var self = this;
                $.each(options, function (key, value) {
                    self[key] = value;
                });
            };

            /**
            * Render the annotation.
            * @param {BaseChartRender} engine The engine used to render the annotation.
            */
            AnnotationBase.prototype.render = function (engine) {
                var self = this, position;

                // calculate the location of the annotation.
                position = self._getPosition(engine);
                if (position == null) {
                    // don't paint annotation for piechart and unexisted series.
                    return;
                }

                // draw the annotation.
                self.paintAnnotation(engine, position);
                if (!self.isVisible) {
                    self.toggleVisibility(false);
                }
            };

            /**
            * Toggle the visibility of the annotation.
            * @param {boolean} visible A boolean value indicates whether to show the annotation.
            */
            AnnotationBase.prototype.toggleVisibility = function (visible) {
                // show/hide the annotation.
                var self = this;
                if (!self._annoText) {
                    return;
                }
                if (visible && self.isVisible) {
                    self._annoText.show();
                } else {
                    self._annoText.hide();
                }
            };

            // draw the annotation in the specified position.
            AnnotationBase.prototype.paintAnnotation = function (engine, position) {
                //Todo: override this method to render the annotation for every type of annotation.
            };

            // get the size of the annotation.
            AnnotationBase.prototype.getSize = function (engine) {
                return { width: 0, height: 0 };
            };

            // Get the position of the annotation.
            AnnotationBase.prototype._getPosition = function (engine) {
                //Todo add the codes to calculate the location of the annotation.
                var self = this, position = self._getAttachmentPosition(engine), offset = self._getOffset(engine);

                if (position) {
                    position.x += offset.x;
                    position.y += offset.y;
                }
                return position;
            };

            AnnotationBase.prototype._getPlotAreaXY = function (engine, point) {
                var bounds = engine.options.bounds;
                var point = { x: point.x + bounds.startX, y: point.y + bounds.startY };
                return point;
            };

            // get the base position.
            AnnotationBase.prototype._getAttachmentPosition = function (engine) {
                var self = this, position;
                switch (self.attachment) {
                    case "dataIndex":
                        position = engine.getChartElementPosition(self.seriesIndex, self.pointIndex);
                        break;
                    case "dataCoordinate":
                        position = engine.getDataPosition(self.point.x, self.point.y);
                        break;
                    case "relative":
                        position = self._getPlotAreaXY(engine, { x: self.point.x * engine.width, y: self.point.y * engine.height });
                        break;
                    case "absolute":
                    default:
                        position = self._getPlotAreaXY(engine, { x: self.point.x, y: self.point.y });
                        break;
                }
                return position;
            };

            // get the offset.
            AnnotationBase.prototype._getOffset = function (engine) {
                var self = this, posOffset = { x: 0, y: 0 }, pos = self.position, size = self.getSize(engine);

                if (pos.indexOf("top") > -1) {
                    //top
                    posOffset.y -= size.height / 2;
                } else if (pos.indexOf("bottom") > -1) {
                    //bottom
                    posOffset.y += size.height / 2;
                }
                if (pos.indexOf("left") > -1) {
                    //left
                    posOffset.x -= size.width / 2;
                } else if (pos.indexOf("right") > -1) {
                    //right
                    posOffset.x += size.width / 2;
                }
                posOffset.x += self.offset.x;
                posOffset.y += self.offset.y;

                return posOffset;
            };

            AnnotationBase.prototype._paintAnnotation = function (engine, elements) {
                var self = this, tracker, annoTooltip = engine.annoTooltip, firstTracker;
                if (!self.isVisible) {
                    return;
                }
                if (elements && elements.length && elements[0].node) {
                    tracker = elements[0].clone();
                    if ($.browser.msie && parseInt($.browser.version) < 9) {
                        tracker.attr({
                            opacity: 0.01, fill: "white",
                            "stroke-width": 0, "fill-opacity": 0.01
                        });
                    } else {
                        tracker.attr({
                            opacity: 0.01, fill: "white",
                            "fill-opacity": 0.01
                        });
                    }
                    if (self.tooltip) {
                        $(tracker).data("tooltip", self.tooltip);
                    }
                    if (engine.fields.annotationTrackers == null) {
                        engine.fields.annotationTrackers = engine.canvas.set();
                    }
                    engine.fields.annotationTrackers.push(tracker);
                }
                if (!engine.fields.annotationTrackers) {
                    return;
                }
                firstTracker = engine.fields.trackers ? engine.fields.trackers[0] : engine.fields.annotationTrackers[0];
                $.each(elements, function (i, annoObj) {
                    annoObj.insertBefore(firstTracker);
                });
                if (self.tooltip) {
                    self._bindTooltip(engine, tracker);
                }
            };

            AnnotationBase.prototype._bindTooltip = function (engine, tracker) {
                engine.annoTooltip.setTargets(tracker);
            };
            return AnnotationBase;
        })();
        chart.AnnotationBase = AnnotationBase;

        /** @ignore */
        var Shape = (function (_super) {
            __extends(Shape, _super);
            function Shape() {
                _super.apply(this, arguments);
            }
            Shape.prototype.toggleVisibility = function (visible) {
                // show/hide the annotation.
                _super.prototype.toggleVisibility.call(this, visible);
                var self = this;
                if (!self._annoShape) {
                    return;
                }
                if (visible && self.isVisible) {
                    self._annoShape.show();
                } else {
                    self._annoShape.hide();
                }
            };
            Shape.prototype.paintAnnotation = function (engine, position) {
                var self = this;
                self._paintAnnotation(engine, [self._annoShape, self._annoText]);
            };
            return Shape;
        })(AnnotationBase);
        chart.Shape = Shape;

        /** @ignore */
        var Circle = (function (_super) {
            __extends(Circle, _super);
            /**
            * Initializes a new instance of an @see:Circle object.
            * @param options A JavaScript object containing initialization data
            * for @see:AnnotationBase.
            */
            function Circle(options) {
                _super.call(this, options);
                this.radius = 25;
                this._setOptions(options);
            }
            // draw the annotation in the specified position.
            Circle.prototype.paintAnnotation = function (engine, position) {
                //Todo: override this method to render the annotation for every type of annotation.
                this._annoShape = engine.canvas.circle(position.x, position.y, this.radius);
                this._annoText = engine.canvas.text(position.x, position.y, this.content);
                this._annoShape.wijAttr(this.style);
                _super.prototype.paintAnnotation.call(this, engine, position);
            };

            // get the size of the annotation.
            Circle.prototype.getSize = function (engine) {
                return { width: this.radius * 2, height: this.radius * 2 };
            };
            return Circle;
        })(Shape);
        chart.Circle = Circle;

        /** @ignore */
        var Square = (function (_super) {
            __extends(Square, _super);
            /**
            * Initializes a new instance of an @see:Square object.
            * @param options A JavaScript object containing initialization data
            * for @see:AnnotationBase.
            */
            function Square(options) {
                _super.call(this, options);
                this.width = 50;
                this._setOptions(options);
            }
            // draw the annotation in the specified position.
            Square.prototype.paintAnnotation = function (engine, position) {
                //Todo: override this method to render the annotation for every type of annotation.
                var self = this;
                self._annoShape = engine.canvas.box(position.x, position.y, self.width);
                self._annoText = engine.canvas.text(position.x, position.y, self.content);
                self._annoShape.wijAttr(self.style);
                _super.prototype.paintAnnotation.call(this, engine, position);
            };

            // get the size of the annotation.
            Square.prototype.getSize = function (engine) {
                return { width: this.width, height: this.width };
            };
            return Square;
        })(Shape);
        chart.Square = Square;

        /** @ignore */
        var Rect = (function (_super) {
            __extends(Rect, _super);
            /**
            * Initializes a new instance of an @see:Rect object.
            * @param options A JavaScript object containing initialization data
            * for @see:AnnotationBase.
            */
            function Rect(options) {
                _super.call(this, options);
                this.width = 60;
                this.height = 30;
                this.r = 2;
                this._setOptions(options);
            }
            // draw the annotation in the specified position.
            Rect.prototype.paintAnnotation = function (engine, position) {
                //Todo: override this method to render the annotation for every type of annotation.
                var self = this, _x = position.x - self.width / 2, _y = position.y - self.height / 2;
                self._annoShape = engine.canvas.rect(_x, _y, self.width, self.height, self.r);
                self._annoText = engine.canvas.text(position.x, position.y, self.content);
                self._annoShape.wijAttr(self.style);
                _super.prototype.paintAnnotation.call(this, engine, position);
            };

            // get the size of the annotation.
            Rect.prototype.getSize = function (engine) {
                return { width: this.width, height: this.height };
            };
            return Rect;
        })(Shape);
        chart.Rect = Rect;

        /** @ignore */
        var Ellipse = (function (_super) {
            __extends(Ellipse, _super);
            /**
            * Initializes a new instance of an @see:Ellipse object.
            * @param options A JavaScript object containing initialization data
            * for @see:AnnotationBase.
            */
            function Ellipse(options) {
                _super.call(this, options);
                this.width = 60;
                this.height = 30;
                this._setOptions(options);
            }
            // draw the annotation in the specified position.
            Ellipse.prototype.paintAnnotation = function (engine, position) {
                //Todo: override this method to render the annotation for every type of annotation.
                var self = this;
                self._annoShape = engine.canvas.ellipse(position.x, position.y, self.width / 2, self.height / 2);
                self._annoText = engine.canvas.text(position.x, position.y, self.content);
                self._annoShape.wijAttr(self.style);
                _super.prototype.paintAnnotation.call(this, engine, position);
            };

            // get the size of the annotation.
            Ellipse.prototype.getSize = function (engine) {
                return { width: this.width, height: this.height };
            };
            return Ellipse;
        })(Shape);
        chart.Ellipse = Ellipse;

        /** @ignore */
        var Line = (function (_super) {
            __extends(Line, _super);
            /**
            * Initializes a new instance of an @see:Line object.
            * @param options A JavaScript object containing initialization data
            * for @see:AnnotationBase.
            */
            function Line(options) {
                _super.call(this, options);
                this._setOptions(options);
            }
            Line.prototype._getContentCenter = function () {
                var start = this.start, end = this.end;

                return {
                    x: (start.x + end.x) / 2,
                    y: (start.y + end.y) / 2
                };
            };

            // draw the annotation in the specified position.
            Line.prototype.paintAnnotation = function (engine, position) {
                //Todo: override this method to render the annotation for every type of annotation.
                var self = this, x = engine.options.bounds.startX, y = engine.options.bounds.startY, centerPos, start = self.start, end = self.end, offsetX, offsetY, len, strokeWidth, radian, pos;

                if (!start || !end) {
                    return;
                }

                pos = self._getOffset(engine);

                start.x += pos.x;
                start.y += pos.y;
                end.x += pos.x;
                end.y += pos.y;
                centerPos = self._getContentCenter();

                self._annoShape = engine.canvas.path("M" + (start.x + x) + "," + (start.y + y) + "L" + (end.x + x) + "," + (end.y + y));
                var angle = Math.atan2((end.y - start.y), (end.x - start.x)) * 180 / Math.PI;
                angle = angle < -90 ? angle + 180 : (angle > 90 ? angle - 180 : angle);
                self._annoText = engine.canvas.text(centerPos.x, centerPos.y, self.content);
                self._annoShape.wijAttr(self.style);

                //Move the string above the line
                strokeWidth = self.style["stroke-width"] || 1;
                len = self._annoText.getBBox().height / 2 + strokeWidth;
                radian = angle * Math.PI / 180;
                offsetX = len * Math.sin(radian);
                offsetY = len * Math.cos(radian);

                self._annoText.attr({
                    x: centerPos.x + x + offsetX,
                    y: centerPos.y + y - offsetY,
                    transform: "r" + angle
                });
                _super.prototype.paintAnnotation.call(this, engine, position);
            };

            // get the size of the annotation.
            Line.prototype.getSize = function (engine) {
                var self = this;
                if (!self.start || !self.end) {
                    return { width: 0, height: 0 };
                }
                return { width: self.end.x - self.start.x, height: self.end.y - self.start.x };
            };
            return Line;
        })(Shape);
        chart.Line = Line;

        /** @ignore */
        var Polygon = (function (_super) {
            __extends(Polygon, _super);
            /**
            * Initializes a new instance of an @see:Polygon object.
            * @param options A JavaScript object containing initialization data
            * for @see:AnnotationBase.
            */
            function Polygon(options) {
                _super.call(this, options);
                this._setOptions(options);
            }
            // draw the annotation in the specified position.
            Polygon.prototype.paintAnnotation = function (engine, position) {
                //Todo: override this method to render the annotation for every type of annotation.
                var self = this, points = self.points, path, bounds = engine.options.bounds, x, y, centerPoint, pos;

                if (!points || points.length == 0) {
                    return;
                }
                pos = self._getOffset(engine);

                $.each(points, function (i, point) {
                    point.x += pos.x;
                    point.y += pos.y;
                });

                //Calculate the points to draw the polygon
                x = bounds.startX, y = bounds.startY;
                path = "M" + (points[0].x + x) + " " + (points[0].y + y);
                for (var i = 1; i < points.length; i++) {
                    path += "L" + (points[i].x + x) + " " + (points[i].y + y);
                }
                path += "Z";
                centerPoint = self._getContentCenter();

                self._annoShape = engine.canvas.path(path);
                self._annoText = engine.canvas.text(centerPoint.x + x, centerPoint.y + y, self.content);
                self._annoShape.wijAttr(self.style);
                _super.prototype.paintAnnotation.call(this, engine, position);
            };

            Polygon.prototype._getContentCenter = function () {
                var pts = this.points, len = pts.length, x = 0, y = 0, i;

                for (i = 0; i < len; i++) {
                    x += pts[i].x;
                    y += pts[i].y;
                }
                return { x: x / len, y: y / len };
            };

            // get the size of the annotation.
            Polygon.prototype.getSize = function (engine) {
                var self = this, xMin, xMax, yMin, yMax, i, pt, len, pts = self.points;

                if (!pts || pts.length == 0) {
                    return { width: 0, height: 0 };
                }
                len = pts.length;

                for (i = 0; i < len; i++) {
                    pt = pts[i];
                    if (i === 0) {
                        xMin = xMax = pt.x;
                        yMin = yMax = pt.y;
                        continue;
                    }
                    if (pt.x < xMin) {
                        xMin = pt.x;
                    } else if (pt.x > xMax) {
                        xMax = pt.x;
                    }
                    if (pt.y < yMin) {
                        yMin = pt.y;
                    } else if (pt.y > yMax) {
                        yMax = pt.y;
                    }
                }
                return { width: xMax - xMin, height: yMax - yMin };
            };
            return Polygon;
        })(Shape);
        chart.Polygon = Polygon;

        /** @ignore */
        var Image = (function (_super) {
            __extends(Image, _super);
            /**
            * Initializes a new instance of an @see:Image object.
            * @param options A JavaScript object containing initialization data
            * for @see:AnnotationBase.
            */
            function Image(options) {
                _super.call(this, options);
                this.width = 60;
                this.height = 60;
                this._setOptions(options);
            }
            // draw the annotation in the specified position.
            Image.prototype.paintAnnotation = function (engine, position) {
                //Todo: override this method to render the annotation for every type of annotation.
                var self = this;
                self._annoShape = engine.canvas.image(self.href, position.x - (self.width / 2), position.y - (self.height / 2), self.width, self.height);
                self._annoText = engine.canvas.text(position.x, position.y, self.content);
                self._annoShape.wijAttr(self.style);
                _super.prototype.paintAnnotation.call(this, engine, position);
            };

            // get the size of the annotation.
            Image.prototype.getSize = function (engine) {
                return { width: this.width, height: this.height };
            };
            return Image;
        })(Shape);
        chart.Image = Image;

        /** @ignore */
        var Text = (function (_super) {
            __extends(Text, _super);
            /**
            * Initializes a new instance of an @see:Text object.
            * @param options A JavaScript object containing initialization data
            * for @see:AnnotationBase.
            */
            function Text(options) {
                _super.call(this, options);
                this.text = "Text";
                this._setOptions(options);
            }
            // draw the annotation in the specified position.
            Text.prototype.paintAnnotation = function (engine, position) {
                //Todo: override this method to render the annotation for every type of annotation.
                var self = this;
                self._annoText = engine.canvas.text(position.x, position.y, self.text);
                self._annoText.wijAttr(self.style);
                self._paintAnnotation(engine, [self._annoText]);
            };

            // get the size of the annotation.
            Text.prototype.getSize = function (engine) {
                var tmp = engine.canvas.text(0, 0, this.text);
                var size = { width: tmp.getBBox().width, height: tmp.getBBox().height };
                tmp.remove();
                return size;
            };
            return Text;
        })(AnnotationBase);
        chart.Text = Text;
    })(wijmo.chart || (wijmo.chart = {}));
    var chart = wijmo.chart;
})(wijmo || (wijmo = {}));


;
/// <reference path="../wijchart/jquery.wijmo.wijchartcore.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*globals jQuery, Globalize*/
    /*
    * Depends:
    *  raphael.js
    *  globalize.js
    *  jquery.ui.widget.js
    *  jquery.wijmo.wijchartcore.js
    *
    */
    (function (chart) {
        /**
        * @widget
        */
        var wijbarchart = (function (_super) {
            __extends(wijbarchart, _super);
            function wijbarchart() {
                _super.apply(this, arguments);
            }
            wijbarchart.prototype._create = function () {
                var self = this, o = self.options, defFill = self._getDefFill(), compass;

                //			if (o.horizontal) {
                //				$.extend(true, o.axis, {
                //					x: {
                //						compass: "west"
                //					},
                //					y: {
                //						compass: "south"
                //					}
                //				});
                //			}
                if (o.horizontal) {
                    compass = o.axis.y.compass || "south";
                    o.axis.y.compass = o.axis.x.compass || "west";
                    o.axis.x.compass = compass;
                }

                $.extend(true, {
                    compass: "east"
                }, o.hint);

                self._handleChartStyles();

                defFill = null;

                _super.prototype._create.call(this);

                self.chartElement.addClass(o.wijCSS.barChart);
            };

            wijbarchart.prototype._setOption = function (key, value) {
                if (key === "horizontal") {
                    var axis = this.options.axis;
                    axis.x.compass = value ? "west" : "south";
                    axis.y.compass = value ? "south" : "west";
                    //$.extend(true, this.options.axis, {
                    //	x: {
                    //		compass: value ? "west" : "south"
                    //	},
                    //	y: {
                    //		compass: value ? "south" : "west"
                    //	}
                    //});
                }
                _super.prototype._setOption.call(this, key, value);
            };

            /**
            * Remove the functionality completely. This will return the element back to its pre-init state.
            */
            wijbarchart.prototype.destroy = function () {
                var self = this, o = self.options, element = self.chartElement, fields = element.data("fields"), aniBarsAttr = fields && fields.bars;

                element.removeClass(o.wijCSS.barChart);
                _super.prototype.destroy.call(this);

                if (aniBarsAttr && aniBarsAttr.length) {
                    $.each(aniBarsAttr, function (idx, barAttr) {
                        barAttr = null;
                    });
                }

                element.data("fields", null);
            };

            wijbarchart.prototype._clearChartElement = function () {
                var self = this, o = self.options, fields = self.chartElement.data("fields");

                _super.prototype._clearChartElement.call(this);
                self.element.removeData("plotInfos");

                if (!o.seriesTransition.enabled) {
                    if (fields && fields.aniBarsAttr) {
                        fields.aniBarsAttr = null;
                    }
                }
            };

            wijbarchart.prototype._isBarChart = function () {
                return true;
            };

            /**
            * This method returns the bar, which has a set of Raphaël objects (rects) that represent bars for the
            * series data, from the specified index.
            * @param {number} index The zero-based index of the bar to return.
            * @returns {Raphael element} Bar object.
            */
            wijbarchart.prototype.getBar = function (index) {
                var element = this.chartElement, fields = element.data("fields");

                return fields.chartElements.bars[index];
            };

            /** end of public methods */
            wijbarchart.prototype._paintTooltip = function () {
                var self = this, element = self.chartElement, fields = element.data("fields");

                _super.prototype._paintTooltip.call(this);

                if (self.tooltip) {
                    if (fields && fields.trackers && fields.trackers.length) {
                        self.tooltip.setTargets(fields.trackers);
                        self.tooltip.setOptions({ relatedElement: fields.trackers[0] });
                    }
                }
            };

            wijbarchart.prototype._getTooltipText = function (fmt, target) {
                var tar = $(target.node), dataObj, obj;
                if (tar.data("owner")) {
                    tar = tar.data("owner");
                }
                dataObj = tar.data("wijchartDataObj");
                obj = {
                    data: dataObj,
                    value: dataObj.value,
                    label: dataObj.label,
                    total: dataObj.total,
                    target: target,
                    fmt: fmt,
                    x: dataObj.x,
                    y: dataObj.y
                };
                return $.proxy(fmt, obj)();
            };

            wijbarchart.prototype._preHandleSeriesData = function () {
                _super.prototype._preHandleSeriesData.call(this);
                var self = this, o = self.options, seriesList = o.seriesList;

                $.each(seriesList, function (i, n) {
                    var data = n.data;
                    if (data.y) {
                        $.each(data.y, function (j, y) {
                            try  {
                                if (!self._isDate(y)) {
                                    data.y[j] = parseFloat(y);
                                }
                            } catch (e) {
                                data.y[j] = 1;
                            }
                        });
                    }
                });
            };

            wijbarchart.prototype._paintPlotArea = function () {
                var self = this, o = self.options;
                this.barchartRender = new BarChartRender(this.chartElement, {
                    annotations: o.annotations,
                    canvas: self.canvas,
                    bounds: self.canvasBounds,
                    hint: o.hint,
                    tooltip: self.tooltip,
                    widgetName: self.widgetName,
                    horizontal: o.horizontal,
                    stacked: o.stacked,
                    axis: o.axis,
                    seriesList: o.seriesList,
                    seriesStyles: o.seriesStyles,
                    seriesHoverStyles: o.seriesHoverStyles,
                    seriesTransition: o.seriesTransition,
                    showChartLabels: o.showChartLabels,
                    textStyle: o.textStyle,
                    chartLabelStyle: o.chartLabelStyle,
                    chartLabelFormatString: o.chartLabelFormatString,
                    chartLabelFormatter: o.chartLabelFormatter,
                    shadow: o.shadow,
                    disabled: self._isDisabled(),
                    clusterOverlap: o.clusterOverlap,
                    clusterWidth: o.clusterWidth,
                    clusterSpacing: o.clusterSpacing,
                    is100Percent: o.is100Percent,
                    clusterRadius: o.clusterRadius,
                    animation: o.animation,
                    culture: self._getCulture(),
                    isYTime: self.axisInfo.y[0].isTime,
                    isXTime: self.axisInfo.x.isTime,
                    mouseDown: $.proxy(self._mouseDown, self),
                    mouseUp: $.proxy(self._mouseUp, self),
                    mouseOver: $.proxy(self._mouseOver, self),
                    mouseOut: $.proxy(self._mouseOut, self),
                    mouseMove: $.proxy(self._mouseMove, self),
                    click: $.proxy(self._click, self),
                    wijCSS: o.wijCSS,
                    widget: this
                });

                this.barchartRender.render();
            };
            wijbarchart.prototype._showSerieEles = function (seriesEle) {
                var stacked = this.options.stacked;
                if (seriesEle.isTrendline) {
                    chart.TrendlineRender.showSerieEles(seriesEle);
                    return;
                }
                $.each(seriesEle, function (i, bar) {
                    if (bar && bar.bar) {
                        bar.bar.show();
                        if (bar.bar.shadow) {
                            bar.bar.shadow.show();
                        }
                        if (bar.bar.tracker) {
                            bar.bar.tracker.show();
                        }
                        if ($(bar.bar.node).data("wijchartDataObj")) {
                            $(bar.bar.node).data("wijchartDataObj").visible = true;
                        }
                    }
                    if (bar && bar.dcl) {
                        bar.dcl.show();
                    }

                    if (bar && bar.animatedBar && !bar.animatedBar.removed) {
                        bar.animatedBar.show();
                    }
                });

                //handle stacked
                if (stacked && this.stackedSeriesObjs) {
                    this._handleStackedVisible(seriesEle.length);
                }
            };

            wijbarchart.prototype._hideSerieEles = function (seriesEle) {
                var stacked = this.options.stacked, totalLength = seriesEle.length;
                if (seriesEle.isTrendline) {
                    chart.TrendlineRender.hideSerieEles(seriesEle);
                    return;
                }
                $.each(seriesEle, function (i, bar) {
                    if (bar && bar.bar) {
                        bar.bar.hide();
                        if (bar.bar.shadow) {
                            bar.bar.shadow.hide();
                        }
                        if (bar.bar.tracker) {
                            bar.bar.tracker.hide();
                        }
                        if ($(bar.bar.node).data("wijchartDataObj")) {
                            $(bar.bar.node).data("wijchartDataObj").visible = false;
                        }
                    }
                    if (bar && bar.dcl) {
                        bar.dcl.hide();
                    }

                    if (bar && bar.animatedBar && !bar.animatedBar.removed) {
                        bar.animatedBar.hide();
                    }
                });

                //handle stacked
                if (stacked && this.stackedSeriesObjs) {
                    this._handleStackedVisible(seriesEle.length);
                }
            };

            wijbarchart.prototype._handleStackedVisible = function (sCount) {
                var _this = this;
                function getVisible(ele) {
                    return $(ele.bar.node).data("wijchartDataObj").visible !== false;
                }

                function adjustBarH(ele, x, width) {
                    if (ele) {
                        if (ele.bar) {
                            ele.bar.attr("x", x);
                            ele.bar.attr("width", width);
                        }
                        if (ele.bar.shadow) {
                            ele.bar.shadow.attr("x", x);
                            ele.bar.shadow.attr("width", width);
                        }
                        if (ele.bar.tracker) {
                            ele.bar.tracker.attr("x", x);
                            ele.bar.tracker.attr("width", width);
                        }
                    }
                }

                function adjustBarV(ele, y, height) {
                    if (ele) {
                        if (ele.bar) {
                            ele.bar.attr("y", y);
                            ele.bar.attr("height", height);
                        }
                        if (ele.bar.shadow) {
                            ele.bar.shadow.attr("y", y);
                            ele.bar.shadow.attr("height", height);
                        }
                        if (ele.bar.tracker) {
                            ele.bar.tracker.attr("y", y);
                            ele.bar.tracker.attr("height", height);
                        }
                    }
                }

                function resetBarH(ele) {
                    if (ele) {
                        var x = ele.rect.x, width = ele.rect.width;
                        if (ele.bar) {
                            ele.bar.attr("x", x);
                            ele.bar.attr("width", width);
                        }
                        if (ele.bar.shadow) {
                            ele.bar.shadow.attr("x", x);
                            ele.bar.shadow.attr("width", width);
                        }
                        if (ele.bar.tracker) {
                            ele.bar.tracker.attr("x", x);
                            ele.bar.tracker.attr("width", width);
                        }
                    }
                }

                function resetBarV(ele) {
                    if (ele) {
                        var y = ele.rect.y, height = ele.rect.height;
                        if (ele.bar) {
                            ele.bar.attr("y", y);
                            ele.bar.attr("height", height);
                        }
                        if (ele.bar.shadow) {
                            ele.bar.shadow.attr("y", y);
                            ele.bar.shadow.attr("height", height);
                        }
                        if (ele.bar.tracker) {
                            ele.bar.tracker.attr("y", y);
                            ele.bar.tracker.attr("height", height);
                        }
                    }
                }

                if (this.stackedSeriesObjs) {
                    $.each(this.stackedSeriesObjs, function (i, ele) {
                        if (_this.options.horizontal) {
                            resetBarH(ele);
                        } else {
                            resetBarV(ele);
                        }
                    });

                    var eleVisibles = [], stackCount = this.stackedSeriesCount;
                    for (var i = 0; i < stackCount; i++) {
                        eleVisibles.push(getVisible(this.stackedSeriesObjs[i + "0"]));
                    }

                    var adjusts = [], start = -1, end = -1, lastVisibleIndex = -1;
                    for (var i = eleVisibles.length - 1; i >= 0; i--) {
                        if (eleVisibles[i]) {
                            if (lastVisibleIndex - i > 1) {
                                adjusts.push({
                                    start: lastVisibleIndex,
                                    end: i + 1
                                });
                            }
                            lastVisibleIndex = i;
                        }
                    }
                    if (lastVisibleIndex > 0) {
                        adjusts.push({
                            start: lastVisibleIndex,
                            end: 0
                        });
                    }

                    $.each(adjusts, function (i, adjust) {
                        var sIndex = adjust.start, eIndex = adjust.end, sEl, eEl, nx, ny, nw, wh;

                        for (var index = 0; index < sCount; index++) {
                            sEl = _this.stackedSeriesObjs[sIndex + "" + index];
                            eEl = _this.stackedSeriesObjs[eIndex + "" + index];
                            if (_this.options.horizontal) {
                                nx = eEl.rect.x;
                                nw = sEl.rect.width + sEl.rect.x - eEl.rect.x;
                                adjustBarH(sEl, nx, nw);
                            } else {
                                nx = sEl.rect.y;
                                nw = eEl.rect.height + eEl.rect.y - sEl.rect.y;
                                adjustBarV(sEl, nx, nw);
                            }
                        }
                    });
                }
            };

            wijbarchart.prototype._indicatorLineShowing = function (objs) {
                _super.prototype._indicatorLineShowing.call(this, objs);
                $.each(objs, function (i, obj) {
                    if (obj.bar) {
                        obj.bar.attr(obj.hoverStyle);
                    }
                });
            };

            wijbarchart.prototype._removeIndicatorStyles = function (objs) {
                $.each(objs, function (i, obj) {
                    if (obj.bar) {
                        obj.bar.attr(obj.style);
                    }
                });
            };

            wijbarchart.prototype._supportStacked = function () {
                return true;
            };

            wijbarchart.prototype._calculateParameters = function (axisInfo, options) {
                _super.prototype._calculateParameters.call(this, axisInfo, options);

                // check for bar chart and x axis expansion
                if (axisInfo.id === "x") {
                    var minor = options.unitMinor, adj = this._getBarAdjustment(axisInfo);

                    if (adj === 0) {
                        adj = minor;
                    } else {
                        if (minor < adj && minor !== 0) {
                            adj = Math.floor(adj / minor) * minor;
                        }
                    }

                    /*if (autoMin) {
                    axisInfo.min -= adj;
                    }
                    
                    if (autoMax) {
                    axisInfo.max += adj;
                    }*/
                    axisInfo.min -= adj;
                    axisInfo.max += adj;

                    this._calculateMajorMinor(options, axisInfo);
                }
            };

            wijbarchart.prototype._getBarAdjustment = function (axisInfo) {
                var len = 0, o = this.options, max = axisInfo.max, min = axisInfo.min, seriesList = o.seriesList, i = 0, xLen = 0;

                for (i = 0; i < seriesList.length && seriesList[i].data.x; i++) {
                    xLen = seriesList[i].data.x.length;

                    if (len < xLen) {
                        len = xLen;
                    }
                }

                if (len > 1) {
                    var clusterRelativeWidth = (max - min) / (len - 1) * (o.clusterWidth / 100);

                    // Make a "0.25" offset to avoid the column being too close to axis.
                    return (clusterRelativeWidth * 1.25) / 2;
                } else if (len === 1) {
                    if (min === 0.0 && max === 1.0) {
                        min = -1.0;
                        axisInfo.min = min;
                    }

                    return (max - min) * 0.0125;
                } else {
                    return 0;
                }
            };
            return wijbarchart;
        })(chart.wijchartcore);
        chart.wijbarchart = wijbarchart;

        var wijbarchart_css = (function (_super) {
            __extends(wijbarchart_css, _super);
            function wijbarchart_css() {
                _super.apply(this, arguments);
                this.barChart = "wijmo-wijbarchart";
                this.barLabel = "wijbarchart-label";
                this.barElement = "wijbarchart";
                this.barTracker = "bartracker";
            }
            return wijbarchart_css;
        })(chart.wijchartcore_css);
        chart.wijbarchart_css = wijbarchart_css;

        var wijbarchart_options = (function (_super) {
            __extends(wijbarchart_options, _super);
            function wijbarchart_options() {
                _super.apply(this, arguments);
                /**
                * Selector option for auto self initialization. This option is internal.
                * @ignore
                */
                this.initSelector = ":jqmData(role='wijbarchart')";
                /**
                * @ignore
                */
                this.wijCSS = new wijmo.chart.wijbarchart_css();
                /**
                * A value that determines whether the bar chart renders horizontally or vertically.
                * @remarks
                * If set to false, the numeric Y axis renders to the left, and the X axis labels render below the bars.
                * @example
                * // set the bar as column chart.
                $("#wijbarchart").wijbarchart({
                *		horizontal: false,
                *		seriesList: [{
                *			legendEntry: false,
                *			data: {
                *				x: ['Ford', 'GM', 'Chrysler', 'Toyota', 'Nissan', 'Honda'],
                *				y: [.05, .04, .21, .27, .1, .24]
                *			}
                *		}]
                *	});
                */
                this.horizontal = true;
                /**
                * Sets a value that determines whether to stack bars in the chart to show how each value in a series
                * contributes to the total.
                * @remarks
                * If you want each bar to fill up 100 percet of the chart area, you can also set the is100Percent option to true.
                * See Clustering Data for more information on the concept of using the same X values with multiple Y series.
                * @example
                * // set the chart to stacked bar chart.
                *  $("#wijbarchart").wijbarchart({
                *		stacked: true,
                *		seriesList: [{
                *			label: "US",
                *			data: { x: ['PS3', 'XBOX360', 'Wii'], y: [12.35, 21.50, 30.56] }
                *		}, {
                *			label: "Japan",
                *			data: { x: ['PS3', 'XBOX360', 'Wii'], y: [4.58, 1.23, 9.67] }
                *		}, {
                *			label: "Other",
                *			data: { x: ['PS3', 'XBOX360', 'Wii'], y: [31.59, 37.14, 65.32] }
                *		}]
                *	});
                */
                this.stacked = false;
                /**
                * Sets a value that determines whether to present stacked bars as a total value of 100 percent, illustrating
                * how each value contributes to the total.
                * @remarks
                * See Clustering Data for more information on the concept of using the same X values with multiple Y series.
                * Note: This value has no effect if you do not set the stacked option to true.
                * @example
                * // This code results in bars with data for three countries stacked to fill 100% of the chart area, with each
                * // series in a different color representing its percentage of the total.
                * $("#wijbarchart").wijbarchart({
                *		stacked: true,
                *		is100Percent: true,
                *		seriesList: [{
                *			label: "US",
                *			legendEntry: true,
                *			data: { x: ['PS3', 'XBOX360', 'Wii'], y: [12.35, 21.50, 30.56] }
                *		}, {
                *			label: "Japan",
                *			legendEntry: true,
                *			data: { x: ['PS3', 'XBOX360', 'Wii'], y: [4.58, 1.23, 9.67] }
                *		}, {
                *			label: "Other",
                *			legendEntry: true,
                *			data: { x: ['PS3', 'XBOX360', 'Wii'], y: [31.59, 37.14, 65.32] }
                *		}],
                *	});
                */
                this.is100Percent = false;
                /**
                * Sets the amount of each bar to render over the edge of the next bar in the same cluster,as a percentage of
                * the bar width.
                * @remarks
                * Note: A cluster occurs when you have two or more series in your seriesList that have the same x data,
                * but have different y data and different labels
                */
                this.clusterOverlap = 0;
                /**
                * Sets the percentage of each cluster's allocated plot area that the bars in each cluster occupy.
                * @remarks
                * By default, the bars occupy 85% of the cluster's plot area, leaving a small gap between clusters. A setting
                * of 100% removes the gap, or you can make the gap more dramatic with a setting of 50%.
                * This setting may affect your clusterSpacing option setting.
                */
                this.clusterWidth = 85;
                /**
                * Sets the number of pixels by which to round the corner-radius for the bars in the chart.
                * @remarks
                * The amount of rounding this produces depends on the size of the bar.For example, with a clusterRadius
                * of 3, a small bar might look like a ball on the end, while a very large bar might only show a slight
                * rounding of the corners.
                */
                this.clusterRadius = 0;
                /**
                * Sets the amount of space in pixels between the bars in each cluster.
                * @remarks
                * This space may also be affected by the clusterOverlap and clusterWidth option settings.
                */
                this.clusterSpacing = 0;
                /**
                * The animation option determines whether and how the animation is shown.
                * @remarks
                * It defines the animation effect and controls other aspects of the widget's animation, such as
                * duration and easing. Set this option to false in order to disable the animation effect.
                */
                this.animation = {
                    /**
                    * A value that determines whether to show animation. Set this option to false in order to disable easing.
                    */
                    enabled: true,
                    /**
                    * The duration option defines the length of the animation effect in milliseconds.
                    */
                    duration: 400,
                    /**
                    * Sets the type of animation easing effect that users experience when the wijbarchart series loads on the page
                    * @remarks
                    * For example, the wijbarchart series can bounce several times as it loads.
                    * The easing is defined in Raphael, the documentation is: http://raphaeljs.com/reference.html#Raphael.easing_formulas
                    */
                    easing: ">"
                };
                /**
                * Creates the animation object to use when the seriesList data changes.
                * @remarks
                * This allows you to visually show changes in data for the same series.
                * Note: This animation does not appear when you first load or reload the page--it only occurs when data changes.
                * @example
                * // This code creates a chart with random data that regenerates when you click the button created in the
                * second code snippet below
                *  $(document).ready(function () {
                * $("#wijbarchart").wijbarchart({
                *	seriesList: [createRandomSeriesList("2013")],
                *	seriesTransition: {
                *		duration: 800,
                *		easing: "easeOutBounce"
                *	}
                * });
                *	} );
                *	function reload() {
                *		$("#wijbarchart").wijbarchart("option", "seriesList", [createRandomSeriesList("2013")]);
                *	}
                
                *	function createRandomSeriesList(label) {
                *		var data = [],
                *			randomDataValuesCount = 12,
                *			labels = ["January", "February", "March", "April", "May", "June",
                *				"July", "August", "September", "October", "November", "December"],
                *			idx;
                *		for (idx = 0; idx < randomDataValuesCount; idx++) {
                *			data.push(Math.round(Math.random() * 100));
                *		}
                *		return {
                *			label: label,
                *			legendEntry: false,
                *			data: { x: labels, y: data }
                *		};
                *	}
                */
                this.seriesTransition = {
                    /**
                    * A value that determines whether to show animation in redrawing bars when the seriesList data changes.
                    * Set this option to false to disable this animation.
                    */
                    enabled: true,
                    /**
                    * A value that indicates how long to display the series transition animation in milliseconds.
                    */
                    duration: 400,
                    /**
                    * Sets the type of animation easing effect to use in redrawing bars when the seriesList data changes.
                    * @remarks
                    * The easing is defined in Raphael, the documentation is:http://raphaeljs.com/reference.html#Raphael.easing_formulas
                    */
                    easing: ">"
                };
                /**
                * This event fires when the user clicks a mouse button.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {IBarChartEventArgs} data Information about an event
                */
                this.mouseDown = null;
                /**
                * Fires when the user releases a mouse button while the pointer is over the chart element.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {IBarChartEventArgs} data Information about an event
                */
                this.mouseUp = null;
                /**
                * Fires when the user first places the pointer over the chart element.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {IBarChartEventArgs} data Information about an event
                */
                this.mouseOver = null;
                /**
                * Fires when the user moves the pointer off of the chart element.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {IBarChartEventArgs} data Information about an event
                */
                this.mouseOut = null;
                /**
                * Fires when the user moves the mouse pointer while it is over a chart element.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {IBarChartEventArgs} data Information about an event
                */
                this.mouseMove = null;
                /**
                * Fires when the user clicks the chart element.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {IBarChartEventArgs} data Information about an event
                */
                this.click = null;
            }
            return wijbarchart_options;
        })(chart.wijchartcore_options);

        wijbarchart.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijbarchart_options());

        wijbarchart.prototype.widgetEventPrefix = "wijbarchart";

        //$.widget("wijmo.wijbarchart", WijBarChart.prototype);
        $.wijmo.registerWidget("wijbarchart", wijbarchart.prototype);

        var XSpec = (function () {
            function XSpec(nx) {
                this.x = nx;
                this.paSpec = [];
            }
            XSpec.prototype.stackValues = function () {
                var self = this, len = self.paSpec.length, ps0;

                if (len > 1) {
                    ps0 = self.paSpec[0];
                    $.each(self.paSpec, function (idx, ps) {
                        if (idx === 0) {
                            return true;
                        }

                        ps.y += ps0.y;
                        ps0 = ps;
                    });
                }
            };
            return XSpec;
        })();

        // render the bar chart.
        /** @ignore */
        var BarChartRender = (function (_super) {
            __extends(BarChartRender, _super);
            function BarChartRender(element, options) {
                _super.call(this, element, options);
            }
            BarChartRender.prototype._init = function () {
                _super.prototype._init.call(this);
                var o = this.options, inverted = o.horizontal, xaxis = o.axis.x, bounds = o.bounds;

                this.startLocation = { x: bounds.startX, y: bounds.startY };
                this.nSeries = o.seriesList.length, this.seriesList = $.arrayClone(o.seriesList);
                this.seriesStyles = [].concat(o.seriesStyles.slice(0, this.nSeries));
                this.seriesHoverStyles = [].concat(o.seriesHoverStyles.slice(0, this.nSeries));

                this.xscale = chart.ChartUtil.getScaling(inverted, xaxis.max, xaxis.min, inverted ? this.height : this.width);
                this.xlate = chart.ChartUtil.getTranslation(inverted, this.startLocation, xaxis.max, xaxis.min, this.xscale);

                this.aniBarsAttr = this.fields.aniBarsAttr;
                this.canvas = o.canvas;
                this.animationSet = this.canvas.set();
                this.fieldsAniPathAttr = [];
                this.paths = [];
                this.aniPathsAttr = [];
            };

            BarChartRender.prototype._paintShadow = function (element, offset, stroke) {
                if (this.options.shadow) {
                    chart.ChartUtil.paintShadow(element, offset, stroke);
                }
            };

            BarChartRender.prototype.getMinDX = function (x) {
                var minDx = Number.MAX_VALUE, len = x.length, idx, dx;

                if (len == 1) {
                    minDx = Math.min(x[0].x - this.options.axis.x.min, this.options.axis.x.max - x[0].x);
                }

                for (idx = 1; idx < len; idx++) {
                    dx = x[idx].x - x[idx - 1].x;

                    if (dx < minDx && dx > 0) {
                        minDx = dx;
                    }
                }

                if (minDx === Number.MAX_VALUE) {
                    return 2;
                }

                return minDx;
            };

            BarChartRender.prototype.getChartElementPosition = function (seriesIndex, pointIndex) {
                var self = this, o = self.options, widget = o.widget, seriesList = widget.options.seriesList, series = seriesList[seriesIndex];

                if (!series.isTrendline && o.horizontal && !o.stacked) {
                    seriesIndex = seriesList.length - 1 - seriesIndex;
                }

                return _super.prototype.getChartElementPosition.call(this, seriesIndex, pointIndex);
            };

            BarChartRender.prototype.getDataPosition = function (x, y) {
                return chart.BaseChartRender.calculateDataPosition(x, y, this, this.options.horizontal);
            };

            BarChartRender.prototype.stackValues = function (x) {
                $.each(x, function (idx, xSpec) {
                    xSpec.stackValues();
                });
                return x;
            };

            BarChartRender.prototype.barPointList = function (seriesList, seriesEles, paths, inverted) {
                var x = [], shadowPaths = [], self = this, animationSet = self.options.canvas.set(), getXSortedPoints = chart.ChartUtil.getXSortedPoints;

                function addSeriesData(idx, series) {
                    var points = getXSortedPoints(series), nSeries = series.length, xs = null, lim = 0, j = 0, jlim = 0, first_point = true, xprev = 0, dupl = false;

                    if (points) {
                        lim = points.length;
                    }

                    if (x) {
                        jlim = x.length;
                    }

                    if (points === undefined) {
                        return;
                    }

                    $.each(points, function (p, point) {
                        if (first_point) {
                            first_point = false;
                            xprev = point.x;
                        } else {
                            if (xprev === point.x) {
                                dupl = true;
                            } else {
                                dupl = false;
                            }
                            xprev = point.x;
                        }

                        while (j < jlim && x[j].x < point.x) {
                            j++;
                        }

                        if (j < jlim) {
                            // use or insert before the existing item
                            if (x[j].x !== point.x) {
                                xs = new XSpec(point.x);
                                x.splice(j, 0, xs);
                                jlim = x.length;
                            } else {
                                xs = x[j];
                            }
                        } else {
                            // add a new item
                            xs = new XSpec(point.x);
                            x.push(xs);
                            jlim = x.length;
                        }

                        xs.paSpec.push({ y: point.y, sIdx: idx, pIdx: p, dupl: dupl });
                    });
                }

                $.each(seriesList, function (idx, series) {
                    var trendLineEles;
                    if (series.isTrendline) {
                        trendLineEles = [];
                        chart.TrendlineRender.renderSingleTrendLine(series, self.seriesStyles[idx], self.seriesHoverStyles[idx], self.options.axis, null, self.fieldsAniPathAttr, self.options.animation, self.options.seriesTransition, idx, self.options.bounds, self.canvas, self.paths, shadowPaths, self.animationSet, self.aniPathsAttr, self.options.wijCSS, trendLineEles, inverted, self.options.shadow);
                        if (trendLineEles.length) {
                            seriesEles[idx] = trendLineEles[0];
                            paths.push(trendLineEles[0].path);
                        }
                    } else {
                        addSeriesData(idx, series);
                    }
                });

                return x;
            };

            BarChartRender.prototype.adjustToLimits = function (val, min, max) {
                if (val < min) {
                    return min;
                }

                if (val > max) {
                    return max;
                }

                return val;
            };

            BarChartRender.prototype.transformPoints = function (inverted, xscale, yscale, xlate, ylate, points) {
                $.each(points, function (idx, point) {
                    var x = point.x, y = point.y, temp = 0;
                    point.x = xscale * x + xlate;
                    point.y = yscale * y + ylate;

                    if (inverted) {
                        temp = point.x;
                        point.x = point.y;
                        point.y = temp;
                    }
                });

                return points;
            };

            BarChartRender.prototype.paintDefaultChartLabel = function (rf, points, isTime, seriesTextStyle) {
                var options = this.options, inverted = options.horizontal, canvas = options.canvas, wijCSS = options.wijCSS, culture = options.culture, textStyle = $.extend(true, {}, options.textStyle, options.chartLabelStyle), pos = inverted ? { x: rf.x + rf.width, y: rf.y + rf.height / 2 } : { x: rf.x + rf.width / 2, y: rf.y }, chartLabelFormatString = options.chartLabelFormatString, chartLabelFormatter = options.chartLabelFormatter, dclBox, defaultChartLabel, widget = this.options.widget, text = points.y, processedChartLabel;

                if (seriesTextStyle) {
                    textStyle = $.extend(true, textStyle, seriesTextStyle);
                }

                /*if (isTime) {
                text = $.wijchart.fromOADate(y);
                } else {
                text = $.wijchart.round(y, 2);
                }*/
                if (isTime) {
                    text = $.fromOADate(text);
                }
                processedChartLabel = chart.ChartUtil.getChartLabel(chartLabelFormatString, text, culture, {
                    index: points.sIdx,
                    data: { x: points.x, y: points.y },
                    value: points.y,
                    chartLabelFormatter: chartLabelFormatter
                });
                if (processedChartLabel.processed) {
                    text = processedChartLabel.text;
                } else if (!isTime) {
                    text = $.round(text, 2);
                }

                defaultChartLabel = widget._text.call(widget, pos.x, pos.y, text);
                defaultChartLabel.wijAttr(textStyle);
                $.wijraphael.addClass($(defaultChartLabel.node), wijCSS.barLabel);
                dclBox = defaultChartLabel.getBBox();
                if (inverted) {
                    defaultChartLabel.attr({ x: pos.x + dclBox.width / 2 });
                } else {
                    defaultChartLabel.attr({ y: pos.y - dclBox.height / 2 });
                }

                return defaultChartLabel;
            };

            BarChartRender.prototype.getSeriesItemPosition = function (rf) {
                var options = this.options, inverted = options.horizontal, pos = inverted ? { x: rf.x + rf.width, y: rf.y + rf.height / 2 } : { x: rf.x + rf.width / 2, y: rf.y };

                return { x: pos.x, y: pos.y };
            };

            BarChartRender.prototype.paintBar = function (rp, points, height, xAxisInfo, yAxisInfo, seriesStyle, animated, shadowOffset, startLocation, clusterOverlap, preY, lastY, isYTime, seriesTextStyle, yaxis) {
                var o = this.options, stacked = o.stacked, inverted = o.horizontal, is100Percent = o.is100Percent, xmin = xAxisInfo.min, xmax = xAxisInfo.max, ymin = yAxisInfo.min, ymax = yAxisInfo.max, xscale = xAxisInfo.scale, xlate = xAxisInfo.late, yscale = yAxisInfo.scale, ylate = yAxisInfo.late, hold, x, inPlotArea, rf, defaultChartLabel = null, r, style = seriesStyle, strokeWidth = seriesStyle["stroke-width"], stroke = seriesStyle.stroke, bar, barWidth, barHeight, animatedBar, start = -1, y = points.y, annotation;

                if (yaxis.origin !== null) {
                    start = yscale * yaxis.origin + ylate;
                }

                if (stacked) {
                    if (is100Percent) {
                        if (lastY > 0) {
                            rp.height = y / lastY;
                        }

                        if (preY || preY === 0) {
                            rp.y = preY / lastY;
                            rp.height -= rp.y;
                        }
                    } else {
                        rp.height = y;

                        if (preY || preY === 0) {
                            rp.height -= preY;
                            rp.y = preY;
                        }
                    }
                } else {
                    if (preY || preY === 0) {
                        // 1 bar over less overlap and 1 pixel
                        rp.x += rp.width * (1 - clusterOverlap);
                        rp.height = y - yaxis.origin || 0;
                    }
                }

                x = [{ x: rp.x, y: rp.y }, { x: rp.x + rp.width, y: rp.y + rp.height }];
                inPlotArea = ((xmin <= x[0].x && x[0].x <= xmax) || (xmin <= x[1].x && x[1].x <= xmax)) && ((ymin <= x[0].y && x[0].y <= ymax) || (ymin <= x[1].y && x[1].y <= ymax));

                x[0].x = this.adjustToLimits(x[0].x, xmin, xmax);
                x[0].y = this.adjustToLimits(x[0].y, ymin, ymax);
                x[1].x = this.adjustToLimits(x[1].x, xmin, xmax);
                x[1].y = this.adjustToLimits(x[1].y, ymin, ymax);

                x = this.transformPoints(inverted, xscale, yscale, xlate, ylate, x);

                if (x[0].x > x[1].x) {
                    hold = x[0].x;
                    x[0].x = x[1].x;
                    x[1].x = hold;
                }

                if (x[0].y > x[1].y) {
                    hold = x[0].y;
                    x[0].y = x[1].y;
                    x[1].y = hold;
                }

                rf = {
                    x: x[0].x,
                    y: x[0].y,
                    width: x[1].x - x[0].x,
                    height: x[1].y - x[0].y
                };

                if (inPlotArea && !stacked) {
                    if (rf.width === 0) {
                        rf.width = 1;
                    }

                    if (rf.height === 0) {
                        rf.height = 1;
                        rf.y -= 1;
                    }
                }

                if (o.showChartLabels) {
                    defaultChartLabel = this.paintDefaultChartLabel(rf, points, isYTime, seriesTextStyle);
                }

                annotation = this.getSeriesItemPosition(rf);

                r = seriesStyle.r ? seriesStyle.r : o.clusterRadius;

                if (r) {
                    style = $.extend(true, {}, seriesStyle, {
                        r: 0
                    });
                }

                if (stroke !== "none" && strokeWidth) {
                    strokeWidth = parseInt(strokeWidth, 10);
                }

                if (!strokeWidth || isNaN(strokeWidth)) {
                    strokeWidth = 0;
                }

                barWidth = rf.width;
                barHeight = rf.height;
                if (strokeWidth > 1) {
                    strokeWidth--;
                    barWidth = rf.width - strokeWidth;
                    barHeight = rf.height - strokeWidth / 2;
                    rf.x += strokeWidth / 2;
                }

                if (barWidth < 0) {
                    barWidth = 0;
                }
                if (barHeight < 0) {
                    barHeight = 0;
                }

                if (animated) {
                    if (start === -1) {
                        if (inverted) {
                            start = startLocation.x + strokeWidth / 2;
                        } else {
                            start = startLocation.y + height - strokeWidth / 2;
                        }
                    }

                    if (r) {
                        if (inverted) {
                            if (y > yaxis.origin) {
                                bar = this.canvas.roundRect(rf.x, rf.y, barWidth, barHeight, 0, 0, r, r).hide();
                            } else {
                                bar = this.canvas.roundRect(rf.x, rf.y, barWidth, barHeight, r, r, 0, 0).hide();
                            }
                            animatedBar = this.canvas.rect(start, rf.y, rf.width, rf.height);
                        } else {
                            if (y > yaxis.origin) {
                                bar = this.canvas.roundRect(rf.x, rf.y, barWidth, barHeight, r, 0, 0, r).hide();
                            } else {
                                bar = this.canvas.roundRect(rf.x, rf.y, barWidth, barHeight, 0, r, r, 0).hide();
                            }

                            animatedBar = this.canvas.rect(rf.x, start, rf.width, rf.height);
                        }

                        this._paintShadow(animatedBar, shadowOffset);
                        animatedBar.wijAttr(style);
                        animatedBar.bar = bar;
                    } else {
                        if (inverted) {
                            bar = this.canvas.rect(start, rf.y, rf.width, barHeight);
                        } else {
                            bar = this.canvas.rect(rf.x, start, barWidth, rf.height);
                        }
                        animatedBar = bar;
                    }

                    if (defaultChartLabel) {
                        defaultChartLabel.attr({ opacity: 0 });
                        animatedBar.chartLabel = defaultChartLabel;
                    }

                    animatedBar.left = rf.x;
                    animatedBar.top = rf.y;
                    animatedBar.width = barWidth;
                    animatedBar.height = barHeight;
                    animatedBar.r = r;
                } else {
                    if (r) {
                        if (inverted) {
                            if (y > yaxis.origin) {
                                bar = this.canvas.roundRect(rf.x, rf.y, barWidth, barHeight, 0, 0, r, r);
                            } else {
                                bar = this.canvas.roundRect(rf.x, rf.y, barWidth, barHeight, r, r, 0, 0);
                            }
                        } else {
                            if (y > yaxis.origin) {
                                bar = this.canvas.roundRect(rf.x, rf.y, barWidth, barHeight, r, 0, 0, r);
                            } else {
                                bar = this.canvas.roundRect(rf.x, rf.y, barWidth, barHeight, 0, r, r, 0);
                            }
                        }
                    } else {
                        bar = this.canvas.rect(rf.x, rf.y, barWidth, barHeight);
                    }
                }

                this._paintShadow(bar, shadowOffset);
                if (animated && r) {
                    if (bar.shadow) {
                        bar.shadow.hide();
                    }
                }
                bar.wijAttr(seriesStyle);

                return {
                    rect: rf,
                    dcl: defaultChartLabel,
                    animatedBar: animatedBar,
                    bar: bar,
                    annotation: annotation
                };
            };

            BarChartRender.prototype.paintClusters = function (seriesList, seriesStyles, seriesHoverStyles, xAxisInfo, yAxisInfo, width, height, startLocation, isYTime, isXTime) {
                var self = this, o = self.options, clusterOverlap = o.clusterOverlap / 100, clusterWidth = o.clusterWidth / 100, shadowOffset = 1, clusterSpacing = o.clusterSpacing + shadowOffset, nSeries = seriesList.length, canvas = o.canvas, stacked = o.stacked, inverted = o.horizontal, yaxis = o.axis.y, widget = o.widget, wijCSS = o.wijCSS, animated = o.animation && o.animation.enabled, bpl, bw, pointX, chartLabels = [], bars = [], animatedBars = [], rects = [], sList = [], seriesEles = [], trackers = canvas.set(), trendLines = [], tooltipObj, strokeWidth = 0;

                if (isYTime || isXTime) {
                    $.each(seriesList, function (i, s) {
                        var se = $.extend(true, {}, s);
                        if (se.data && se.data.y && se.data.y.length && isYTime) {
                            $.each(se.data.y, function (idx, data) {
                                se.data.y[idx] = $.toOADate(data);
                            });
                        }
                        if (se.data && se.data.x && se.data.x.length && isXTime) {
                            $.each(se.data.x, function (idx, data) {
                                se.data.x[idx] = $.toOADate(data);
                            });
                        }
                        sList.push(se);
                    });
                    bpl = self.barPointList(sList, seriesEles, trendLines, inverted);
                } else {
                    bpl = self.barPointList(seriesList, seriesEles, trendLines, inverted);
                }

                if (stacked) {
                    bpl = self.stackValues(bpl);
                }

                bw = self.getMinDX(bpl) * clusterWidth;

                // fixed an issue that if the stroke-width is not 0, if set the clusterSpacing to small,
                // some bars are shows too close.
                $.each(seriesStyles, function (i, st) {
                    if (st["stroke-width"] && !isNaN(st["stroke-width"])) {
                        if (strokeWidth !== 0) {
                            strokeWidth = Math.min(parseFloat(st["stroke-width"]), strokeWidth);
                        } else {
                            strokeWidth = parseFloat(st["stroke-width"]);
                        }
                    }
                });
                nSeries = nSeries - trendLines.length;

                // adjust the bar width (bw) to account for overlap
                if (nSeries > 1 && !stacked) {
                    clusterOverlap -= (bpl.length * (nSeries - 1) * (clusterSpacing + strokeWidth * 2)) / (inverted ? height : width);
                    bw /= (nSeries * (1 - clusterOverlap) + clusterOverlap);
                }

                self.annoPoints = {};
                $.each(bpl, function (bplIdx, xs) {
                    var ps = xs.paSpec, ns = ps.length, sx, rp, bar, barInfo;

                    if (stacked) {
                        sx = bw;
                    } else {
                        sx = (bw * (ns * (1 - clusterOverlap) + clusterOverlap));
                    }

                    // calculate the first series rectangle
                    rp = { x: xs.x - sx / 2, y: 0, width: bw, height: ps[0].y };

                    $.each(ps, function (psIndex, points) {
                        // if the array data.x's length is more than the data.y's,
                        // the rp.height is undefined. it will cause wrong.
                        if (rp.height === undefined) {
                            return true;
                        }

                        var sIdx = points.sIdx, pIdx = points.pIdx, seriesStyle = seriesStyles[sIdx], series = seriesList[sIdx], tracker, yAxisIndex = series.yAxis || 0, axisY = yaxis[yAxisIndex] || yaxis, axisInfoY = yAxisInfo[yAxisIndex] || yAxisInfo;

                        if (!stacked) {
                            rp.y = axisY.origin || 0;
                            rp.height -= rp.y;
                        }
                        if (!rects[sIdx]) {
                            rects[sIdx] = [];
                        }

                        if (!seriesEles[sIdx]) {
                            seriesEles[sIdx] = [];
                        }

                        self.yscale = chart.ChartUtil.getScaling(!inverted, axisY.max, axisY.min, inverted ? width : height);
                        self.ylate = chart.ChartUtil.getTranslation(!inverted, startLocation, axisY.max, axisY.min, self.yscale);

                        axisInfoY.late = self.ylate;
                        axisInfoY.scale = self.yscale;

                        barInfo = self.paintBar(rp, points, height, xAxisInfo, axisInfoY, seriesStyle, animated, shadowOffset, startLocation, clusterOverlap, psIndex > 0 ? ps[psIndex - 1].y : null, ps[ps.length - 1].y, isYTime, series.textStyle, axisY);

                        bar = barInfo.bar;
                        tracker = bar.clone().attr({
                            opacity: 0.01, fill: "white", "stroke-width": 0,
                            "fill-opacity": 0.01
                        });
                        if (series.visible === false) {
                            bar.hide();
                            if (barInfo.dcl) {
                                barInfo.dcl.hide();
                            }
                            tracker.hide();
                            if (bar.shadow) {
                                bar.shadow.hide();
                            }
                        }
                        $.wijraphael.addClass($(bar.node), wijCSS.canvasObject + " " + wijCSS.barElement);

                        tooltipObj = $.extend(false, {
                            index: pIdx,
                            bar: bar,
                            type: "bar",
                            style: seriesStyle,
                            hoverStyle: seriesHoverStyles[sIdx],
                            x: series.data.x[pIdx],
                            y: series.data.y[pIdx],
                            visible: true
                        }, series);

                        if (isXTime) {
                            tooltipObj.x = $.fromOADate(xs.x);
                        } else if (typeof series.data.x[pIdx] === "number") {
                            tooltipObj.x = xs.x;
                        }

                        if (isYTime) {
                            tooltipObj.y = $.fromOADate(points.y);
                        } else if (typeof series.data.y[pIdx] === "number") {
                            tooltipObj.y = points.y;
                        }

                        $(bar.node).data("wijchartDataObj", tooltipObj);

                        // cache the bar position to show indicator line.
                        //if()
                        widget.dataPoints = widget.dataPoints || {};
                        widget.pointXs = widget.pointXs || [];

                        if (o.horizontal) {
                            pointX = $.round(barInfo.rect.y + barInfo.rect.height / 2, 2);
                        } else {
                            pointX = $.round(barInfo.rect.x + barInfo.rect.width / 2, 2);
                        }
                        if (!widget.dataPoints[pointX.toString()]) {
                            widget.dataPoints[pointX.toString()] = [];
                            widget.pointXs.push(pointX);
                        }

                        widget.dataPoints[pointX.toString()].push(tooltipObj);

                        $(tracker.node).data("owner", $(bar.node));
                        $.wijraphael.addClass($(tracker.node), wijCSS.barElement + " " + wijCSS.barTracker);
                        barInfo.bar.tracker = tracker;
                        trackers.push(tracker);
                        bars.push(bar);

                        if (barInfo.animatedBar) {
                            animatedBars.push(barInfo.animatedBar);
                        }

                        if (barInfo.dcl) {
                            chartLabels.push(barInfo.dcl);
                        }
                        rects[sIdx][pIdx] = barInfo.rect;
                        seriesEles[sIdx][pIdx] = barInfo;
                        bar = null;
                        tracker = null;
                        if (self.annoPoints[sIdx] == null)
                            self.annoPoints[sIdx] = {};
                        self.annoPoints[sIdx][pIdx] = barInfo.annotation;
                    });
                });

                //set default chart label to front.
                $.each(chartLabels, function (sIdx, chartLabel) {
                    chartLabel.toFront();
                });

                trackers.toFront();

                return {
                    bars: bars, animatedBars: animatedBars,
                    rects: rects, chartLabels: chartLabels,
                    seriesEles: seriesEles,
                    trackers: trackers,
                    trendLines: trendLines
                };
            };

            BarChartRender.prototype.processStackedElement = function (seriesEles) {
                var eles = {}, newIndex = 0;
                $.each(seriesEles, function (i, seriesEle) {
                    if (!$.isArray(seriesEle)) {
                        return true;
                    }
                    if (seriesEle.isTrendline) {
                        return true;
                    }
                    $.each(seriesEle, function (j, ele) {
                        ele.sIndex = newIndex;
                        ele.stackIndex = j;
                        eles[newIndex + "" + j] = ele;
                    });
                    newIndex = newIndex + 1;
                });
                this.options.widget.stackedSeriesObjs = eles;
                this.options.widget.stackedSeriesCount = newIndex;
            };

            BarChartRender.prototype.playAnimation = function (animatedBars) {
                var self = this, o = self.options, animation = o.animation, animated = animation && animation.enabled, inverted = o.horizontal, seriesTransition = o.seriesTransition, duration, easing, barsAttr = [], diffAttr, chartLabelStyle = o.chartLabelStyle;

                if (animated) {
                    duration = animation.duration || 2000;
                    easing = animation.easing || "linear";
                    if (animatedBars) {
                        $.each(animatedBars, function (idx, animatedBar) {
                            var params;
                            if (inverted) {
                                animatedBar.wijAttr({ width: 0 });
                                params = { width: animatedBar.width, x: animatedBar.left };
                            } else {
                                animatedBar.wijAttr({ height: 0 });
                                params = { height: animatedBar.height, y: animatedBar.top };
                            }

                            if (self.aniBarsAttr && seriesTransition.enabled) {
                                if (self.aniBarsAttr.length > idx) {
                                    diffAttr = chart.ChartUtil.getDiffAttrs(self.aniBarsAttr[idx], animatedBar.attr());

                                    if (inverted) {
                                        diffAttr.x = self.aniBarsAttr[idx].x;
                                        diffAttr.width = self.aniBarsAttr[idx].width;
                                    } else {
                                        diffAttr.y = self.aniBarsAttr[idx].y;
                                        diffAttr.height = self.aniBarsAttr[idx].height;
                                    }

                                    if (diffAttr.path) {
                                        delete diffAttr.path;
                                    }
                                    animatedBar.attr(diffAttr);
                                    duration = seriesTransition.duration;
                                    easing = seriesTransition.easing;
                                }
                            }
                            barsAttr.push($.extend(true, {}, animatedBar.attr(), params));
                            if (animatedBar.tracker) {
                                animatedBar.tracker.hide();
                            }

                            //return;
                            animatedBar.stop().wijAnimate(params, duration, easing, function () {
                                var b = this, r = b.r, bar = b;

                                if (b.chartLabel) {
                                    // fixed an issue that if the chart label's opacity is not 1,
                                    // this code will change the opacity.
                                    if (chartLabelStyle && chartLabelStyle.opacity) {
                                        b.chartLabel.wijAnimate({ opacity: chartLabelStyle.opacity }, 250);
                                    } else {
                                        b.chartLabel.wijAnimate({ opacity: 1 }, 250);
                                    }
                                }

                                if (b.tracker) {
                                    b.tracker.show();
                                    b.tracker.attr({
                                        width: b.width,
                                        height: b.height,
                                        x: b.attr("x"),
                                        y: b.attr("y")
                                    });
                                }

                                if (r) {
                                    bar = b.bar;
                                    bar.show();
                                    if (bar.shadow) {
                                        bar.shadow.show();
                                    }

                                    if (b.shadow) {
                                        b.shadow.wijRemove();
                                        b.shadow = null;
                                    }
                                    b.wijRemove();

                                    //bar.animatedBar = null;
                                    b = null;
                                }
                            });
                        });
                    }

                    self.aniBarsAttr = barsAttr;
                }
            };

            BarChartRender.prototype.playTrendLineAnimation = function () {
                var self = this, o = self.options, animation = o.animation, animated = animation && animation.enabled, seriesTransition = o.seriesTransition, trendLines = self.fields.trendLines, duration, easing;

                if (animated) {
                    duration = animation.duration || 2000;
                    easing = animation.easing || "linear";
                    if (trendLines && trendLines.length) {
                        chart.TrendlineRender.playAnimation(animated, duration, easing, seriesTransition, o.bounds, trendLines, self.fieldsAniPathAttr, o.axis, o.widget.extremeValue);
                    }
                }
            };

            BarChartRender.prototype.bindLiveEvents = function () {
                var o = this.options, wijCSS = o.wijCSS, widgetName = o.widgetName, disabled = o.disabled, mouseDown = o.mouseDown, mouseUp = o.mouseUp, mouseOver = o.mouseOver, mouseOut = o.mouseOut, mouseMove = o.mouseMove, click = o.click, element = this.element, isFunction = $.isFunction, touchEventPrefix = "";

                if ($.support.isTouchEnabled && $.support.isTouchEnabled()) {
                    touchEventPrefix = "wij";
                }

                //				if (hintEnable && !tooltip) {
                //					hint = $.extend(true, {}, options.hint);
                //					hint.offsetY = hint.offsetY || -2;
                //					title = hint.title;
                //					content = hint.content;
                //					if ($.isFunction(title)) {
                //						hint.title = function () {
                //							return getTooltipText(title, this.target);
                //						};
                //					}
                //					if ($.isFunction(content)) {
                //						hint.content = function () {
                //							return getTooltipText(content, this.target);
                //						};
                //					}
                //					hint.beforeShowing = function () {
                //						if (this.target) {
                //						this.options.style.stroke =
                //							this.target.attrs.stroke ||
                //								this.target.attrs.fill;
                //						}
                //					};
                //					tooltip = canvas.tooltip(bars, hint);
                //				}
                $("." + wijCSS.barElement, element[0]).on(touchEventPrefix + "mousedown." + widgetName, function (e) {
                    if (disabled) {
                        return;
                    }

                    if (isFunction(mouseDown)) {
                        var target = $(e.target), dataObj;
                        if (target.data("owner")) {
                            target = target.data("owner");
                        }
                        dataObj = target.data("wijchartDataObj");
                        mouseDown.call(element, e, dataObj);
                        dataObj = null;
                    }
                }).on(touchEventPrefix + "mouseup." + widgetName, function (e) {
                    if (disabled) {
                        return;
                    }
                    if (isFunction(mouseUp)) {
                        var target = $(e.target), dataObj;
                        if (target.data("owner")) {
                            target = target.data("owner");
                        }
                        dataObj = target.data("wijchartDataObj");
                        mouseUp.call(element, e, dataObj);
                        dataObj = null;
                    }
                }).on(touchEventPrefix + "mouseover." + widgetName, function (e) {
                    if (disabled) {
                        return;
                    }
                    if (isFunction(mouseOver)) {
                        var target = $(e.target), dataObj, bar;
                        if (target.data("owner")) {
                            target = target.data("owner");
                        }
                        dataObj = target.data("wijchartDataObj");
                        bar = dataObj.bar;
                        if (!dataObj.hoverStyle) {
                            if (bar) {
                                bar.wijAttr({ opacity: "0.8" });
                            }
                        } else {
                            dataObj.initTransform = bar.matrix.toTransformString();

                            //bar.transform("");
                            bar.wijAttr(dataObj.hoverStyle);
                        }

                        mouseOver.call(element, e, dataObj);
                        dataObj = null;
                    }
                }).on(touchEventPrefix + "mouseout." + widgetName, function (e) {
                    if (disabled) {
                        return;
                    }
                    var target = $(e.target), dataObj, bar;
                    if (target.data("owner")) {
                        target = target.data("owner");
                    }
                    dataObj = target.data("wijchartDataObj");
                    bar = dataObj.bar;

                    if (!dataObj.hoverStyle) {
                        if (bar) {
                            bar.wijAttr({ opacity: "1" });
                        }
                    } else {
                        // when set the seriesStyle init the transform of the element.
                        bar.transform("");
                        if (bar.shadow) {
                            bar.shadow.transform("");
                        }
                        bar.wijAttr(dataObj.style);
                    }

                    if (isFunction(mouseOut)) {
                        mouseOut.call(element, e, dataObj);
                    }
                    dataObj = null;
                    //if (tooltip) {
                    //	tooltip.hide();
                    //}
                }).on(touchEventPrefix + "mousemove." + widgetName, function (e) {
                    if (disabled) {
                        return;
                    }

                    var target = $(e.target), dataObj, bar;
                    if (target.data("owner")) {
                        target = target.data("owner");
                    }
                    dataObj = target.data("wijchartDataObj");
                    bar = dataObj.bar;

                    if (isFunction(mouseMove)) {
                        mouseMove.call(element, e, dataObj);
                    }
                    dataObj = null;
                    //end of code for adding hover state effect.
                }).on(touchEventPrefix + "click." + widgetName, function (e) {
                    if (disabled) {
                        return;
                    }

                    if (isFunction(click)) {
                        var target = $(e.target), dataObj;
                        if (target.data("owner")) {
                            target = target.data("owner");
                        }
                        dataObj = target.data("wijchartDataObj");
                        click.call(element, e, dataObj);
                    }
                    if ($.support.isTouchEnabled && $.support.isTouchEnabled()) {
                        e.preventDefault();
                        e.stopPropagation();
                        return false;
                    }
                });

                chart.TrendlineRender.bindLiveEvents(element, widgetName, mouseDown, mouseUp, mouseOver, mouseOut, mouseMove, click, disabled, wijCSS, false);
            };

            BarChartRender.prototype.unbindLiveEvents = function () {
                var o = this.options, widgetName = o.widgetName, wijCSS = o.wijCSS, element = this.element;

                // TO DO
                $("." + wijCSS.barElement, element[0]).off(widgetName).off("." + widgetName);
                chart.TrendlineRender.unbindLiveEvents(element, widgetName, wijCSS);
            };

            BarChartRender.prototype.render = function () {
                var o = this.options, inverted = o.horizontal, stacked = o.stacked, seriesList = this.seriesList, seriesStyles = this.seriesStyles, seriesHoverStyles = this.seriesHoverStyles, xaxis = o.axis.x, yaxis = o.axis.y, isYTime = o.isYTime, isXTime = o.isXTime, clusterInfos;
                this.unbindLiveEvents();
                if (inverted && !stacked) {
                    seriesList.reverse();
                    seriesStyles.reverse();
                    seriesHoverStyles.reverse();
                }
                if (this.nSeries === 0) {
                    return;
                }

                clusterInfos = this.paintClusters(seriesList, seriesStyles, seriesHoverStyles, {
                    min: xaxis.min,
                    max: xaxis.max,
                    late: this.xlate,
                    scale: this.xscale
                }, yaxis, this.width, this.height, this.startLocation, isYTime, isXTime);

                this.element.data("plotInfos", {
                    xscale: this.xscale,
                    xlate: this.xlate,
                    yscale: this.yscale,
                    ylate: this.ylate,
                    rects: clusterInfos.rects
                });

                this.fields.trendLines = clusterInfos.trendLines;
                this.playAnimation(clusterInfos.animatedBars);
                this.playTrendLineAnimation();

                //bars = clusterInfos.bars;
                this.chartElements.bars = clusterInfos.bars;
                this.chartElements.animatedBars = clusterInfos.animatedBars;
                this.chartElements.chartLabels = clusterInfos.chartLabels;
                this.fields.seriesEles = clusterInfos.seriesEles;
                this.fields.trackers = clusterInfos.trackers;

                //fields.chartElements = chartElements;
                if (!this.fields.chartElements) {
                    this.fields.chartElements = {};
                }

                if (inverted && !stacked) {
                    this.fields.seriesEles.reverse();
                }

                if (stacked) {
                    this.processStackedElement(this.fields.seriesEles);
                }

                $.extend(true, this.fields.chartElements, this.chartElements);
                this.fields.aniBarsAttr = this.aniBarsAttr;
                this.element.data("fields", this.fields);
                this.bindLiveEvents();
                _super.prototype.render.call(this);
            };
            return BarChartRender;
        })(chart.BaseChartRender);
        chart.BarChartRender = BarChartRender;
    })(wijmo.chart || (wijmo.chart = {}));
    var chart = wijmo.chart;
})(wijmo || (wijmo = {}));

;
/// <reference path="../wijchart/jquery.wijmo.wijchartcore.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*globals $, Raphael, jQuery, document, window, Globalize*/
    /*
    * Depends:
    *	jquery.js
    *	jquery.ui.widget.js
    *	raphael.js
    *	globalize.js
    *	jquery.wijmo.raphael.js
    *	jquery.wijmo.wijchartcore.js
    *
    */
    (function (chart) {
        /**
        * @widget
        */
        var wijlinechart = (function (_super) {
            __extends(wijlinechart, _super);
            function wijlinechart() {
                _super.apply(this, arguments);
            }
            wijlinechart.prototype._create = function () {
                var o = this.options;
                this._handleChartStyles();
                _super.prototype._create.call(this);
                this.chartElement.addClass(o.wijCSS.lineChart);
                if (o.type === "area") {
                    this.chartElement.addClass(o.wijCSS.areaChart);
                }
            };

            /** Remove the functionality completely.
            *This will return the element back to its pre-init state.
            */
            wijlinechart.prototype.destroy = function () {
                var o = this.options;
                this.chartElement.removeClass(o.wijCSS.lineChart);
                if (o.type === "area") {
                    this.chartElement.removeClass(o.wijCSS.areaChart);
                }

                _super.prototype.destroy.call(this);

                if (this.aniPathsAttr && this.aniPathsAttr.length) {
                    $.each(this.aniPathsAttr, function (idx, pathAttr) {
                        pathAttr = null;
                    });
                    this.aniPathsAttr = null;
                }
            };

            /** Returns reference to raphael's path object for the line data with given index.
            * @param {number} lineIndex The index of the series data for which to return lines.
            * @returns {Raphael Element} Reference to raphael element object.
            * @example
            * //Get the first line.
            * $("#linechart").wijlinechart("getLinePath", 0);
            */
            wijlinechart.prototype.getLinePath = function (lineIndex) {
                var fields = this.chartElement.data("fields"), chartEles, und;
                if (fields && fields.chartElements) {
                    chartEles = fields.chartElements;
                    if (chartEles.paths && chartEles.paths.length) {
                        return chartEles.paths[lineIndex];
                    }
                }
                return und;
            };

            /** Returns reference to set of the raphael's objects
            * what represents markers for the line data with given index.
            * @param {number} lineIndex The index of the series data for which to return markers.
            * @returns {Raphael Element} Reference to raphael element object.
            * @example
            * //Get the markers of the first line.
            * $("#linechart").wijlinechart("getLineMarkers", 0);
            */
            wijlinechart.prototype.getLineMarkers = function (lineIndex) {
                var o = this.options, fields = this.chartElement.data("fields"), chartEles, und;
                if (o.seriesList && o.seriesList[lineIndex].markers && o.seriesList[lineIndex].markers.visible) {
                    if (fields && fields.chartElements) {
                        chartEles = fields.chartElements;
                        if (chartEles.markersSet && chartEles.markersSet.length) {
                            return chartEles.markersSet[lineIndex];
                        }
                    }
                }
                return und;
            };

            wijlinechart.prototype._showSerieEles = function (seriesEle) {
                var o = this.options, obj;
                if (seriesEle.markers) {
                    $.each(seriesEle.markers, function (i, marker) {
                        var dataObj = $(marker.node).data("wijchartDataObj");
                        if (dataObj && dataObj.lineSeries && dataObj.lineSeries.markers) {
                            if (!dataObj.lineSeries.markers.visible) {
                                return true;
                            }
                        }
                        marker.show();
                    });
                }

                if (seriesEle.dcl) {
                    $.each(seriesEle.dcl, function (i, dcl) {
                        if (o.showChartLabels) {
                            dcl.show();
                        }
                    });
                }

                if (seriesEle.path) {
                    obj = $(seriesEle.path.node).data("wijchartDataObj");

                    // If line is invisible and markers are visible, in this case, do not show the line. Otherwise, show the line.
                    if (!(!obj.visible && obj.markers && obj.markers.visible)) {
                        seriesEle.path.show();
                        if (seriesEle.path.shadow) {
                            seriesEle.path.shadow.show();
                        }
                        if (seriesEle.path.area) {
                            seriesEle.path.area.show();
                        }
                        if (seriesEle.path.tracker) {
                            seriesEle.path.tracker.show();
                        }
                    }

                    // mark the mark is not visible
                    if ($(seriesEle.path.node).data("wijchartDataObj") && $(seriesEle.path.node).data("wijchartDataObj").virtualMarkers) {
                        $.each($(seriesEle.path.node).data("wijchartDataObj").virtualMarkers, function (i, markerObj) {
                            markerObj.visible = true;
                        });
                    }
                }
            };

            wijlinechart.prototype._hideSerieEles = function (seriesEle) {
                if (seriesEle.markers) {
                    $.each(seriesEle.markers, function (i, marker) {
                        marker.hide();
                    });
                }

                if (seriesEle.dcl) {
                    $.each(seriesEle.dcl, function (i, dcl) {
                        dcl.hide();
                    });
                }

                if (seriesEle.path) {
                    seriesEle.path.hide();
                    if (seriesEle.path.shadow) {
                        seriesEle.path.shadow.hide();
                    }
                    if (seriesEle.path.area) {
                        seriesEle.path.area.hide();
                    }
                    if (seriesEle.path.tracker) {
                        seriesEle.path.tracker.hide();
                    }

                    if ($(seriesEle.path.node).data("wijchartDataObj") && $(seriesEle.path.node).data("wijchartDataObj").virtualMarkers) {
                        $.each($(seriesEle.path.node).data("wijchartDataObj").virtualMarkers, function (i, markerObj) {
                            markerObj.visible = false;
                        });
                    }
                }
            };

            wijlinechart.prototype._supportStacked = function () {
                return true;
            };

            // when showing the indicator line, hover the line marker.
            wijlinechart.prototype._indicatorLineShowing = function (objs) {
                _super.prototype._indicatorLineShowing.call(this, objs);
                $.each(objs, function (i, obj) {
                    if (obj.marker) {
                        obj.marker.attr(obj.markerHoverStyle);
                    }
                });
            };

            wijlinechart.prototype._removeIndicatorStyles = function (objs) {
                $.each(objs, function (i, obj) {
                    if (obj.marker) {
                        obj.marker.attr(obj.markerStyle);
                        obj.marker.transform("s1");
                    }
                });
            };

            wijlinechart.prototype._mouseDownInsidePlotArea = function (e, mousePos) {
                _super.prototype._mouseDownInsidePlotArea.call(this, e, mousePos);
                this._clearHoverState(true);
            };

            wijlinechart.prototype._mouseDown = function (e, args) {
                _super.prototype._mouseDown.call(this, e, args);
            };

            wijlinechart.prototype._mouseUp = function (e, args) {
                _super.prototype._mouseUp.call(this, e, args);
            };

            wijlinechart.prototype._mouseOver = function (e, lineSeries) {
                if (!lineSeries || !(lineSeries.type === "line" || lineSeries.type === "marker" || lineSeries.type === chart.ChartConsts.strTrendline)) {
                    return;
                }
                if (this.indicatorLine) {
                    return;
                }

                _super.prototype._mouseOver.call(this, e, lineSeries);

                if (lineSeries.type === "marker") {
                    lineSeries = lineSeries.lineSeries;
                }

                if (lineSeries.path.removed) {
                    return;
                }
                if (this.hoverLine !== lineSeries || this.hoverLine === null) {
                    this.isNewLine = true;
                    if (this.hoverLine) {
                        if (!this.hoverLine.path.removed) {
                            // fixed the issue jQuery 1.9.
                            // the options will set on the prototype,
                            // so the seriesStyles will effect by other chart.
                            // if the chart type is not area, remove the style's fill.
                            if ((this.options.type === "line" || lineSeries.type === chart.ChartConsts.strTrendline) && this.hoverLine.lineStyle.fill) {
                                delete this.hoverLine.lineStyle.fill;
                            }
                            this.hoverLine.path.wijAttr(this.hoverLine.lineStyle);
                            if (this.hoverPoint && !this.hoverPoint.isSymbol) {
                                this.hoverPoint.marker.wijAttr(this.hoverPoint.markerStyle);
                                this.hoverPoint.marker.transform("s1");
                            }
                        }
                    }

                    if (lineSeries.lineHoverStyle) {
                        lineSeries.path.wijAttr(lineSeries.lineHoverStyle);
                    }

                    this.hoverLine = lineSeries;
                    this.hoverPoint = null;
                    this.hoverVirtualPoint = null;
                }
            };

            wijlinechart.prototype._mouseOut = function (e, args) {
                _super.prototype._mouseOut.call(this, e, args);
            };

            wijlinechart.prototype._mouseMove = function (e, args) {
                _super.prototype._mouseMove.call(this, e, args);
            };

            wijlinechart.prototype._click = function (e, args) {
                _super.prototype._click.call(this, e, args);
            };

            wijlinechart.prototype._mouseMoveInsidePlotArea = function (e, mousePos) {
                var _this = this;
                var tooltip = this.tooltip, hint = this.options.hint, markers, virtualMarkers, idx = 0, p, point, valueX, valueY, s = null, dataObj = null, op = null, title = hint.title, content = hint.content, isTitleFunc = $.isFunction(title), isContentFunc = $.isFunction(content), distance = 0;

                if (tooltip) {
                    op = tooltip.getOptions();
                }
                if (this.hoverLine && !this.indicatorLine) {
                    if (this.isNewLine) {
                        if (hint.enable && tooltip) {
                            tooltip.hide();
                        }
                        this.isNewLine = false;
                    }
                    if (this.hoverLine.type !== chart.ChartConsts.strTrendline) {
                        markers = this.hoverLine.lineMarkers;
                        virtualMarkers = this.hoverLine.virtualMarkers;
                        idx = -1;
                        p = { x: 0, y: 0 };
                        if (markers && markers.length) {
                            $.each(markers, function (i, marker) {
                                if (marker.removed) {
                                    return true;
                                }
                                var box = marker.wijGetBBox(), pos = box.x + box.width / 2, dis = Math.abs(pos - mousePos.left);
                                if (i === 0 || dis < distance) {
                                    distance = dis;
                                    idx = i;
                                    p = {
                                        x: pos,
                                        y: box.y + box.height / 2
                                    };
                                }
                            });
                            if (this.hoverPoint && this.hoverPoint.index === idx) {
                                return;
                            }
                            if (idx > -1) {
                                if (markers[idx].removed) {
                                    return;
                                }
                                point = $(markers[idx].node).data("wijchartDataObj");

                                if (point) {
                                    if (this.hoverPoint && !this.hoverPoint.isSymbol) {
                                        if (!this.hoverPoint.removed) {
                                            this.hoverPoint.marker.wijAttr(this.hoverPoint.markerStyle);
                                            this.hoverPoint.marker.transform("s1");
                                        }
                                    }
                                    if (!point.isSymbol) {
                                        if (!point.marker.removed) {
                                            point.marker.wijAttr(point.markerHoverStyle);
                                        }
                                    }
                                }

                                this.hoverPoint = point;
                                this.hoverVirtualPoint = virtualMarkers[idx];
                            }
                        } else {
                            $.each(virtualMarkers, function (i, marker) {
                                var dis = Math.abs(marker.x - mousePos.left);
                                if (i === 0 || dis < distance) {
                                    distance = dis;
                                    idx = i;
                                    p = {
                                        x: marker.x,
                                        y: marker.y
                                    };
                                }
                            });
                            if (this.hoverVirtualPoint && this.hoverVirtualPoint.index === idx) {
                                return;
                            }
                            if (idx > -1) {
                                this.hoverPoint = null;
                                this.hoverVirtualPoint = virtualMarkers[idx];
                            }
                        }
                        if (tooltip) {
                            dataObj = this.hoverVirtualPoint;
                            valueX = dataObj.valX;
                            valueY = dataObj.valY;
                            if (isTitleFunc || isContentFunc) {
                                if (isTitleFunc) {
                                    op.title = function () {
                                        var obj = {
                                            pointIndex: idx,
                                            lineIndex: _this.hoverLine.index,
                                            x: valueX,
                                            y: valueY,
                                            label: _this.hoverLine.label,
                                            data: dataObj,
                                            fmt: title
                                        }, fmt = $.proxy(obj.fmt, obj), tit = fmt();
                                        return tit;
                                    };
                                }
                                if (isContentFunc) {
                                    op.content = function () {
                                        var obj = {
                                            pointIndex: idx,
                                            lineIndex: _this.hoverLine.index,
                                            x: valueX,
                                            y: valueY,
                                            label: _this.hoverLine.label,
                                            data: dataObj,
                                            fmt: content
                                        }, fmt = $.proxy(obj.fmt, obj), con = fmt();
                                        return con;
                                    };
                                }
                            }
                            s = $.extend({
                                stroke: this.hoverLine.path.attr("stroke")
                            }, hint.style);
                            op.style.stroke = s.stroke;
                            tooltip.showAt(p);
                        }
                    }
                }

                _super.prototype._mouseMoveInsidePlotArea.call(this, e, mousePos);
            };

            wijlinechart.prototype._mouseMoveOutsidePlotArea = function (e, mousePos) {
                this._clearHoverState(false);
                _super.prototype._mouseMoveOutsidePlotArea.call(this, e, mousePos);
            };

            wijlinechart.prototype._clearHoverState = function (keepTooltip) {
                var tooltip = this.tooltip, hint = this.options.hint;

                if (hint.enable && tooltip && !keepTooltip) {
                    tooltip.hide();
                }

                if (this.hoverLine) {
                    if (!this.hoverLine.path.removed) {
                        // fixed the issue jQuery 1.9.
                        // the options will set on the prototype,
                        // so the seriesStyles will effect by other chart.
                        // if the chart type is not area, remove the style's fill.
                        if ((this.options.type === "line" || this.hoverLine.type === chart.ChartConsts.strTrendline) && this.hoverLine.lineStyle.fill) {
                            delete this.hoverLine.lineStyle.fill;
                        }

                        this.hoverLine.path.wijAttr(this.hoverLine.lineStyle);
                        if (this.hoverPoint && !this.hoverPoint.isSymbol) {
                            this.hoverPoint.marker.wijAttr(this.hoverPoint.markerStyle);
                            this.hoverPoint.marker.transform("s1");
                        }
                    }
                }
                this.hoverLine = null;
                this.hoverPoint = null;
                this.hoverVirtualPoint = null;
            };

            wijlinechart.prototype._getLegendbasicInfo = function () {
                var o = this.options, legendOptions;
                o.legend.size = $.extend(true, { width: 30, height: 3 }, o.legend.size);

                legendOptions = _super.prototype._getLegendbasicInfo.call(this);

                return legendOptions;
            };

            wijlinechart.prototype._getLegendInfoFromSeries = function (seriesIdx, series, seriesStyle) {
                if (series.legendEntry === false) {
                    return undefined;
                }

                var legendSize = $.extend(true, { width: 30, height: 3 }, this.options.legend.size), iconStyle, markerStyle, legendInfo;

                legendInfo = _super.prototype._getLegendInfoFromSeries.call(this, seriesIdx, series, seriesStyle);
                legendInfo.seriesVisible = (series.visible !== false) || (series.markers && series.markers.visible);

                legendInfo.icon = "line";

                iconStyle = legendInfo.iconStyle;
                if (iconStyle) {
                    var strokeWidth = legendSize.height;
                    iconStyle = $.extend(true, {}, iconStyle, {
                        "stroke-width": strokeWidth
                    });
                    if (iconStyle["stroke-dasharray"]) {
                        iconStyle = $.extend(true, {}, iconStyle, {
                            "stroke-width": 1,
                            "stroke-dasharray": iconStyle["stroke-dasharray"]
                        });
                    }
                }
                legendInfo.iconStyle = iconStyle;

                legendInfo.markers = series.markers ? series.markers.type : undefined;
                legendInfo.markerVisible = series.markers ? series.markers.visible : false;

                markerStyle = $.extend({
                    fill: iconStyle.stroke,
                    stroke: iconStyle.stroke,
                    opacity: 1
                }, series.markerStyle);

                legendInfo.markerStyle = markerStyle;

                return legendInfo;
            };

            wijlinechart.prototype._paintPlotArea = function () {
                var o = this.options, opt;

                if (!this.aniPathsAttr) {
                    this.aniPathsAttr = [];
                }

                this.linechartRender = new LineChartRender(this.chartElement, {
                    annotations: o.annotations,
                    bounds: this.canvasBounds,
                    widgetName: this.widgetName,
                    canvas: this.canvas,
                    tooltip: this.tooltip,
                    wijCSS: o.wijCSS,
                    stacked: o.stacked,
                    hole: o.hole,
                    type: o.type,
                    axis: o.axis,
                    animation: o.animation,
                    seriesTransition: o.seriesTransition,
                    seriesList: o.seriesList,
                    seriesStyles: o.seriesStyles,
                    seriesHoverStyles: o.seriesHoverStyles,
                    showChartLabels: o.showChartLabels,
                    chartLabelStyle: o.chartLabelStyle,
                    chartLabelFormatString: o.chartLabelFormatString,
                    chartLabelFormatter: o.chartLabelFormatter,
                    isXTime: this.axisInfo.x.isTime,
                    isYTime: this.axisInfo.y[0].isTime,
                    disabled: this._isDisabled(),
                    culture: this._getCulture(),
                    hint: o.hint,
                    aniPathsAttr: this.aniPathsAttr,
                    chartLabelEles: this.chartLabelEles,
                    mouseDown: $.proxy(this._mouseDown, this),
                    mouseUp: $.proxy(this._mouseUp, this),
                    mouseOver: $.proxy(this._mouseOver, this),
                    mouseOut: $.proxy(this._mouseOut, this),
                    mouseMove: $.proxy(this._mouseMove, this),
                    click: $.proxy(this._click, this),
                    widget: this,
                    extremeValue: {
                        txx: this.extremeValue.txx,
                        txn: this.extremeValue.txn,
                        tyx: this.extremeValue.y[0].tyx,
                        tyn: this.extremeValue.y[0].tyn
                    },
                    shadow: o.shadow
                });

                this.linechartRender.render();
            };

            wijlinechart.prototype._clearChartElement = function () {
                _super.prototype._clearChartElement.call(this);
                this.hoverLine = null;
                this.hoverPoint = null;
                this.hoverVirtualPoint = null;
            };
            return wijlinechart;
        })(chart.wijchartcore);
        chart.wijlinechart = wijlinechart;

        var wijlinechart_css = (function (_super) {
            __extends(wijlinechart_css, _super);
            function wijlinechart_css() {
                _super.apply(this, arguments);
                this.lineChart = "wijmo-wijlinechart";
                this.areaChart = "wijmo-wijareachart";
                this.lineLabel = "wijlinechart-label";
                this.lineElement = "wijlinechart";
                this.areaElement = "wijlinechart-area";
                this.lineTracker = "linetracker";
                this.canvasMarker = "wijchart-canvas-marker";
            }
            return wijlinechart_css;
        })(chart.wijchartcore_css);
        chart.wijlinechart_css = wijlinechart_css;

        var wijlinechart_options = (function (_super) {
            __extends(wijlinechart_options, _super);
            function wijlinechart_options() {
                _super.apply(this, arguments);
                /**
                * Selector option for auto self initialization. This option is internal.
                * @ignore
                */
                this.initSelector = ":jqmData(role='wijlinechart')";
                /**
                * All CSS classes used in widgets.
                * @ignore
                */
                this.wijCSS = new wijmo.chart.wijlinechart_css();
                /** A value that determines whether to show a stacked chart.*/
                this.stacked = false;
                /** Gets or sets the data hole value.
                * @type {number}
                * @remarks Data holes are used as placeholders for data points
                * that indicate data is normally present but not in this case.
                */
                this.hole = null;
                /** An option that indicates the type of chart to be displayed.
                * @remarks Options are 'line' and 'area'.
                */
                this.type = "line";
                /** The animation option defines the animation effect and controls other aspects of the widget's animation,
                * such as duration and easing.
                */
                this.animation = {
                    /** A value that determines whether to show the animation.
                    * Set this option to false in order to disable easing.
                    */
                    enabled: true,
                    /** A value that determines the effect for the animation.
                    * @remarks Options are 'horizontal' and 'vertical'.
                    */
                    direction: "horizontal",
                    /** A value that indicates the duration for the animation.*/
                    duration: 2000,
                    /** Sets the type of animation easing effect that users experience
                    * when the wijlinechart series is loaded to the page.
                    * For example, a user can have the wijlinechart series bounce several times as it loads.
                    * @remarks Values available for the animation easing effect include the following:
                    * easeInCubic - Cubic easing in. Begins at zero velocity and then accelerates.
                    * easeOutCubic - Cubic easing in and out. Begins at full velocity and then decelerates to zero.
                    * easeInOutCubic - Begins at zero velocity, accelerates until halfway, and then decelerates to zero velocity again.
                    * easeInBack - Begins slowly and then accelerates.
                    * easeOutBack - Begins quickly and then decelerates.
                    * easeOutElastic - Begins at full velocity and then decelerates to zero.
                    * easeOutBounce - Begins quickly and then decelerates. The number of bounces is related to the duration, longer durations produce more bounces.
                    */
                    easing: "easeInCubic"
                };
                /** The seriesTransition option is used to animate series in the chart when just their values change.
                * This is helpful for visually showing changes in data for the same series.
                */
                this.seriesTransition = {
                    /** A value that determines whether to show animation when reload.*/
                    enabled: true,
                    /** A value that indicates the duration for the series transition.*/
                    duration: 2000,
                    /** A value that indicates the easing for the series transition.*/
                    easing: "easeInCubic"
                };
                /** This event fires when the user clicks a mouse button.
                * @event
                * @param {Object} e The jQuery.Event object.
                * @param {IWijLineChartEventArgs} args The data with this event.
                */
                this.mouseDown = null;
                /** This event fires when the user releases a mouse button while the pointer is over the chart element.
                * @event
                * @param {Object} e The jQuery.Event object.
                * @param {IWijLineChartEventArgs} args The data with this event.
                */
                this.mouseUp = null;
                /** This event fires when the user first places the pointer over the chart element.
                * @event
                * @param {Object} e The jQuery.Event object.
                * @param {IWijLineChartEventArgs} args The data with this event.
                */
                this.mouseOver = null;
                /** This event fires when the user moves the pointer off of the chart element.
                * @event
                * @param {Object} e The jQuery.Event object.
                * @param {IWijLineChartEventArgs} args The data with this event.
                */
                this.mouseOut = null;
                /** This event fires when the user moves the mouse pointer while it is over a chart element.
                * @event
                * @param {Object} e The jQuery.Event object.
                * @param {IWijLineChartEventArgs} args The data with this event.
                */
                this.mouseMove = null;
                /** This event fires when the user clicks the chart element.
                * @event
                * @param {Object} e The jQuery.Event object.
                * @param {IWijLineChartEventArgs} args The data with this event.
                */
                this.click = null;
            }
            return wijlinechart_options;
        })(chart.wijchartcore_options);
        ;

        wijlinechart.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijlinechart_options());

        $.wijmo.registerWidget("wijlinechart", wijlinechart.prototype);

        ;

        /** @ignore*/
        var LineChartRender = (function (_super) {
            __extends(LineChartRender, _super);
            function LineChartRender(element, options) {
                _super.call(this, element, options);
            }
            LineChartRender.prototype._init = function () {
                _super.prototype._init.call(this);
                var self = this, o = self.options, inverted = o.horizontal, xaxis = o.axis.x, bounds = o.bounds;

                self.startLocation = { x: bounds.startX, y: bounds.startY };
                self.nSeries = o.seriesList.length, self.seriesList = $.arrayClone(o.seriesList);
                self.seriesStyles = [].concat(o.seriesStyles.slice(0, self.nSeries));
                self.seriesHoverStyles = [].concat(o.seriesHoverStyles.slice(0, self.nSeries));

                self.animationSet = self.canvas.set();
            };

            LineChartRender.prototype.render = function () {
                var element = this.element, options = this.options, wijCSS = options.wijCSS, cBounds = options.bounds, widgetName = options.widgetName, canvas = options.canvas, ani = options.animation, seTrans = options.seriesTransition, hint = options.hint, tooltip = options.tooltip, mouseDown = options.mouseDown, mouseUp = options.mouseUp, mouseOver = options.mouseOver, mouseOut = options.mouseOut, mouseMove = options.mouseMove, click = options.click, markersSet = [], symbols = [], linesStyle = [], paths = [], shadowPaths = [], disabled = options.disabled, animationSet = canvas.set(), fieldsAniPathAttr = options.aniPathsAttr, aniPathsAttr = [], chartEles, fields = element.data("fields") || {}, seriesEles = [], culture = options.culture, widget = options.widget, exVal = options.extremeValue, clipRect = {
                    enable: false,
                    left: -10,
                    top: -10,
                    right: 10,
                    bottom: 10
                };

                this.widget = widget;
                this.renderLineChart(options, aniPathsAttr, fieldsAniPathAttr, paths, shadowPaths, markersSet, animationSet, symbols, linesStyle, seriesEles, culture);

                //fix #35743, #30015
                if (!options.axis.x.autoMax && options.axis.x.max < exVal.txx) {
                    clipRect.enable = true;
                    clipRect.right = 0;
                }
                if (!options.axis.x.autoMin && options.axis.x.min > exVal.txn) {
                    clipRect.enable = true;
                    clipRect.left = 0;
                }
                if (!options.axis.y.autoMax && options.axis.y.max < exVal.tyx) {
                    clipRect.enable = true;
                    clipRect.top = 0;
                }
                if (!options.axis.y.autoMin && options.axis.y.min > exVal.tyn) {
                    clipRect.enable = true;
                    clipRect.bottom = 0;
                }

                if (ani.enabled || seTrans.enabled) {
                    this.playAnimation(ani, seTrans, animationSet, cBounds, paths, fieldsAniPathAttr, clipRect);
                } else if (clipRect.enable) {
                    this.setClipRect(clipRect, animationSet, cBounds);
                }
                fieldsAniPathAttr.length = 0;
                $.each(aniPathsAttr, function (idx, aniPathAttr) {
                    fieldsAniPathAttr.push(aniPathAttr);
                });

                this.unbindLiveEvents(element, widgetName, wijCSS);
                this.bindLiveEvents(element, canvas, cBounds, widgetName, mouseDown, mouseUp, mouseOver, mouseOut, mouseMove, click, disabled, hint, linesStyle, tooltip, wijCSS);
                chartEles = {
                    paths: paths,
                    shadowPaths: shadowPaths,
                    markersSet: markersSet,
                    animationSet: animationSet,
                    symbols: symbols
                };
                if (!fields.chartElements) {
                    fields.chartElements = {};
                }

                fields.seriesEles = seriesEles;

                $.extend(true, fields.chartElements, chartEles);

                this.fields = fields;
                element.data("fields", fields);

                _super.prototype.render.call(this);
            };

            LineChartRender.prototype.setClipRect = function (clipRect, animationSet, cBounds) {
                var width = cBounds.endX - cBounds.startX - clipRect.left + clipRect.right, height = cBounds.endY - cBounds.startY - clipRect.top + clipRect.bottom;
                animationSet.wijAttr("clip-rect", Raphael.format("{0} {1} {2} {3}", (cBounds.startX + clipRect.left), (cBounds.startY + clipRect.top), width, height));
            };

            LineChartRender.prototype.playAnimation = function (ani, seTrans, animationSet, cBounds, paths, fieldsAniPathAttr, clipRect) {
                var _this = this;
                var duration = ani.duration, easing = ani.easing;
                if (ani.direction === "horizontal") {
                    if (fieldsAniPathAttr && fieldsAniPathAttr.length && seTrans.enabled) {
                        duration = seTrans.duration;
                        easing = seTrans.easing;
                    }
                    this.playHAnimation(duration, easing, animationSet, cBounds, paths, clipRect);
                } else {
                    if (clipRect.enable) {
                        this.setClipRect(clipRect, animationSet, cBounds);
                    }
                    $.each(paths, function (idx, path) {
                        if (typeof path === "undefined" || path === null) {
                            return true;
                        }
                        if (fieldsAniPathAttr && fieldsAniPathAttr.length > idx && seTrans.enabled) {
                            duration = seTrans.duration;
                            easing = seTrans.easing;
                            _this.playVAnimation(path, fieldsAniPathAttr, idx, duration, easing);
                        } else {
                            if (path.straight) {
                                _this.playVStraightAnimation(path, duration, easing);
                            }
                        }
                    });
                }
            };

            LineChartRender.prototype.playVAnimation = function (path, fieldsAniPathAttr, idx, duration, easing) {
                var aniPathAttr, diffAttr;
                if (path.shadow) {
                    path.shadow.hide();
                }
                if (path.tracker) {
                    path.tracker.hide();
                }
                aniPathAttr = fieldsAniPathAttr[idx];
                if (aniPathAttr && aniPathAttr.path) {
                    diffAttr = chart.ChartUtil.getDiffAttrs(aniPathAttr.path, path.attr());
                }
                if (!$.isEmptyObject(diffAttr)) {
                    path.attr(aniPathAttr.path);
                    path.wijAnimate(diffAttr, duration, easing, function () {
                        if (path.shadow && path.visible !== false) {
                            path.shadow.show();
                        }

                        // If the path is not visible, not show the tracker.
                        if (path.tracker && path.visible !== false) {
                            path.tracker.show();
                        }
                    });
                }
                $.each(path.markers, function (i, marker) {
                    var diffMarkerAttr = chart.ChartUtil.getDiffAttrs(aniPathAttr.markers[i], marker.attr());
                    if (!$.isEmptyObject(diffMarkerAttr)) {
                        marker.attr(aniPathAttr.markers[i]);
                        marker.wijAnimate(diffMarkerAttr, duration, easing);
                    }
                });
                if (path.labels) {
                    $.each(path.labels, function (i, label) {
                        var diffLabelAttr = chart.ChartUtil.getDiffAttrs(aniPathAttr.labels[i], label.attr()), labelAttr = aniPathAttr.labels[i];
                        if (labelAttr && labelAttr.text) {
                            delete labelAttr.text;
                        }
                        if (!$.isEmptyObject(diffLabelAttr)) {
                            label.attr(labelAttr);
                            label.wijAnimate(diffLabelAttr, duration, easing);
                        }
                    });
                }
                if (path.area) {
                    diffAttr = chart.ChartUtil.getDiffAttrs(aniPathAttr.area, path.area.attr());
                    if (!$.isEmptyObject(diffAttr)) {
                        path.area.attr(aniPathAttr.area);
                        path.area.wijAnimate(diffAttr, duration, easing);
                    }
                }
            };

            LineChartRender.prototype.playVStraightAnimation = function (path, duration, easing) {
                var aniPathAttr, diffPath, area;
                if (path.shadow) {
                    path.shadow.hide();
                }
                if (path.tracker) {
                    path.tracker.hide();
                }

                aniPathAttr = path.straight;
                diffPath = path.attr().path;
                path.attr({ path: aniPathAttr });
                path.wijAnimate({ path: diffPath }, duration, easing, function () {
                    if (path.shadow && path.visible !== false) {
                        path.shadow.show();
                    }

                    // If the path is invisible. not show the trackers.
                    if (path.tracker && path.visible !== false) {
                        path.tracker.show();
                    }
                });
                $.each(path.markers, function (i, marker) {
                    if (marker.straight) {
                        var cy = marker.attr().cy;
                        marker.attr({ cy: marker.straight });
                        marker.wijAnimate({ cy: cy }, duration, easing);
                    }
                });
                if (path.area) {
                    area = path.area;
                    aniPathAttr = area.straight;
                    diffPath = area.attr().path;
                    area.attr({
                        path: aniPathAttr
                    });
                    area.wijAnimate({
                        path: diffPath
                    }, duration, easing);
                }
            };

            LineChartRender.prototype.playHAnimation = function (duration, easing, animationSet, cBounds, paths, clipRect) {
                $.each(paths, function (idx, path) {
                    if (path.tracker) {
                        path.tracker.hide();
                    }
                });
                var clipRectEnable = clipRect.enable, width = cBounds.endX - cBounds.startX - clipRect.left + clipRect.right, height = cBounds.endY - cBounds.startY - clipRect.top + clipRect.bottom;
                animationSet.wijAttr("clip-rect", Raphael.format("{0} {1} 0 {2}", (cBounds.startX + clipRect.left), (cBounds.startY + clipRect.top), height));
                animationSet.wijAnimate({
                    "clip-rect": Raphael.format("{0} {1} {2} {3}", (cBounds.startX + clipRect.left), (cBounds.startY + clipRect.top), width, height)
                }, duration, easing, function () {
                    // If the path is invisible not show the tracker.
                    if (this.tracker && this.visible !== false) {
                        this.tracker.show();
                    }

                    if (Raphael.vml && !clipRectEnable) {
                        //delete clip-rect's div in vml
                        var attrs = null, clipRect = null, node = this.node;
                        if (node && node.clipRect) {
                            attrs = this.attrs;
                            delete attrs["clip-rect"];
                            node.clipRect = null;
                            clipRect = $(node).parent();
                            clipRect.before(node);
                            clipRect.remove();
                            this.attr(attrs);

                            //Add comments to fix tfs issue 19385
                            if (attrs.src && attrs.src.length) {
                                this.attr({ "src": attrs.src });
                            }

                            //end comments.
                            // fixed the issue 42963, I have checked the issue and found when play animation, the gradient color will disapear.
                            // according to the issue 19385 fixing, reset the gradient fill.
                            if (attrs.gradient && attrs.gradient.length && attrs.fill === "none") {
                                this.attr({ "fill": attrs.gradient });
                            }
                        }
                    }
                });
            };

            LineChartRender.prototype.renderLineChart = function (options, aniPathsAttr, fieldsAniPathAttr, paths, shadowPaths, markersSet, animationSet, symbols, linesStyle, seriesEles, culture) {
                var _this = this;
                var wijCSS = options.wijCSS, cBounds = options.bounds, canvas = options.canvas, stacked = options.stacked, hole = options.hole, type = options.type, axis = options.axis, ani = options.animation, seTrans = options.seriesTransition, needAnimated = false, linesSeries = options.seriesList, linesSeriesStyles = options.seriesStyles, linesHoverStyles = options.seriesHoverStyles, showChartLabels = options.showChartLabels, chartLabelStyle = options.chartLabelStyle, chartLabelFormatString = options.chartLabelFormatString, chartLabelFormatter = options.chartLabelFormatter, isXTime = options.isXTime, isYTime = options.isYTime, chartLabelEles = options.chartLabelEles, defaultChartLabels, firstYPoint, lastYPoint, fitType, valuesX, valuesY, lastValuesY = [], lastPathAttr = [], valX, pathArr, markers, paintSymbol, valsY, fields = this.element.data("fields") || {}, trackers = canvas.set();
                this.annoPoints = {};
                $.each(linesSeries, function (k, lineSeries) {
                    var aniMarkersAttr = [], aniLabelsAttr = [], initAniPath = [], lineData, lineStyle, lineHoverStyle, lineMarkerStyle, lineMarkerHoverStyle, lineSeriesStyle, virtualMarkers = [];

                    if (lineSeries.display === "exclude") {
                        return true;
                    }
                    lineSeriesStyle = linesSeriesStyles[k];
                    lineHoverStyle = linesHoverStyles[k];
                    if (lineSeries.isTrendline) {
                        chart.TrendlineRender.renderSingleTrendLine(lineSeries, lineSeriesStyle, lineHoverStyle, axis, hole, fieldsAniPathAttr, ani, seTrans, k, cBounds, canvas, paths, shadowPaths, animationSet, aniPathsAttr, wijCSS, seriesEles, false, options.shadow);
                        return true;
                    }

                    //set default value of line series
                    lineSeries = $.extend(true, {
                        display: "show",
                        fitType: "line",
                        markers: {
                            visible: false,
                            type: "circle"
                        },
                        visible: true
                    }, lineSeries);
                    lineData = lineSeries.data;
                    lineStyle = $.extend({
                        stroke: "black",
                        opacity: 1,
                        fill: "none",
                        "stroke-linejoin": "round",
                        "stroke-linecap": "round"
                    }, lineSeriesStyle);
                    lineMarkerStyle = lineSeries.markerStyle;
                    lineMarkerStyle = $.extend({
                        fill: lineStyle.stroke,
                        stroke: lineStyle.stroke,
                        //Add comments by RyanWu@20110706.
                        //I can't add transform: "s1" here, because if so,
                        //The marker will be disapperaed after animation played
                        //in browsers which support vml(ie6/7/8).  I don't know
                        //why.  So I use the transform("s1") method to recover the
                        //original state of the marker after mouse out.
                        //transform: "s1",
                        //end by RyanWu@20110706.
                        opacity: 1,
                        width: 3
                    }, lineMarkerStyle);

                    lineMarkerHoverStyle = $.extend(true, {}, lineHoverStyle, {
                        transform: "s1.5",
                        "stroke-width": 1
                    }, linesSeries.markerHoverStyle);

                    valuesX = [].concat(lineData.x);
                    valuesY = [].concat(lineData.y);

                    // Lines and markers:
                    markers = canvas.set();
                    pathArr = [];
                    fitType = lineSeries.fitType;
                    paintSymbol = false;
                    if (lineSeries.markers.symbol && lineSeries.markers.symbol.length) {
                        paintSymbol = true;
                    }
                    defaultChartLabels = canvas.set();

                    if (!fieldsAniPathAttr || fieldsAniPathAttr.length <= k || (ani.enabled && !seTrans.enabled)) {
                        needAnimated = true;
                    }
                    if (needAnimated) {
                        if (valuesY.length > 0) {
                            firstYPoint = chart.ChartUtil.getFirstValidListValue(valuesY);
                            if (isYTime) {
                                firstYPoint = $.toOADate(firstYPoint);
                            }
                            lastYPoint = chart.ChartUtil.getLastValidListValue(valuesY);
                            if (isYTime) {
                                lastYPoint = $.toOADate(lastYPoint);
                            }
                        }
                    }

                    valsY = _this.processYValues(valuesY, lineSeries.display, hole, stacked, lastValuesY);
                    $.each(valuesY, function (j, valY) {
                        valX = valuesX[j];
                        if (isXTime) {
                            valX = $.toOADate(valX);
                        }
                        valY = valuesY[j];
                        if (valsY[j].isHole) {
                            if (lineSeries.display === "excludeHole") {
                                return true;
                            }
                            if (!valsY[j].isValue) {
                                return true;
                            }
                        }
                        if (isYTime) {
                            valY = $.toOADate(valY);
                        }
                        if (valX === undefined) {
                            return false;
                        }
                        pathArr = _this.renderPoint(cBounds, canvas, initAniPath, pathArr, markers, aniMarkersAttr, animationSet, defaultChartLabels, aniLabelsAttr, chartLabelEles, chartLabelFormatString, needAnimated, firstYPoint, lastYPoint, valX, valY, lineData.y[j], axis, fitType, isXTime, isYTime, j, lineMarkerStyle, lineMarkerHoverStyle, lineSeries, paintSymbol, showChartLabels, symbols, valuesX, valuesY, valsY, lineSeries.display, stacked, virtualMarkers, culture, wijCSS, k, chartLabelFormatter);
                    });

                    _this.renderPath(canvas, cBounds, lineSeries, paths, shadowPaths, linesStyle, lineHoverStyle, lineMarkerStyle, lineMarkerHoverStyle, markers, markersSet, animationSet, pathArr, aniPathsAttr, initAniPath, lineStyle, chartLabelStyle, aniMarkersAttr, aniLabelsAttr, defaultChartLabels, k, type, lastPathAttr, stacked, virtualMarkers, wijCSS);

                    seriesEles.push({
                        markers: markers, path: paths[paths.length - 1],
                        shadowPath: shadowPaths[shadowPaths.length - 1],
                        dcl: defaultChartLabels
                    });
                });

                //fix #35792
                $.each($.merge([], paths).reverse(), function (idx, path) {
                    path.toFront();
                    if (path.area) {
                        path.area.toFront();
                    }
                });

                //end #35792
                $.each(paths, function (idx, path) {
                    if (path.tracker) {
                        path.tracker.toFront();
                        trackers.push(path.tracker);
                    }
                });
                fields.trackers = trackers;
                this.element.data("fields", fields);

                //markers should always be in front of trackers.
                $.each(paths, function (idx, path) {
                    if (path.markers) {
                        path.markers.toFront();
                    }
                });
            };

            LineChartRender.prototype.renderPath = function (canvas, bounds, lineSeries, paths, shadowPaths, linesStyle, lineHoverStyle, lineMarkerStyle, lineMarkerHoverStyle, markers, markersSet, animationSet, pathArr, aniPathsAttr, initAniPath, lineStyle, chartLabelStyle, aniMarkersAttr, aniLabelsAttr, defaultChartLabels, pathIdx, type, lastPathAttr, stacked, virtualMarkers, wijCSS) {
                var path, fill, fillOpacity, opacity, area, startX, endX, tracker, trackerWidth, labelStyle, prevPathArr, prevPath, currentPathArr, idx, noFillStyle, endY, yOrigin = this.options.axis.y.origin;

                endY = bounds.endY;
                if (this.options.axis && this.options.axis.y && (yOrigin !== null && yOrigin !== undefined && !isNaN(yOrigin))) {
                    endY = this._calculatePoint(yOrigin, "y");
                }

                path = canvas.path(pathArr.join(" "));
                path.straight = initAniPath.join(" ");

                //shadow
                if (this.options.shadow !== false) {
                    chart.ChartUtil.paintShadow(path, 1, "#cccccc");
                }
                if (pathIdx === 0) {
                    lastPathAttr.length = 0;
                    if (pathArr.length > 1) {
                        startX = pathArr[1];
                        endX = pathArr[pathArr.length - 2];
                    } else {
                        startX = bounds.startX;
                        endX = bounds.endX;
                    }
                    $.merge(lastPathAttr, ["L", startX, endY, "L", endX, endY]);
                }

                tracker = canvas.path(pathArr.join(" "));
                path.tracker = tracker;
                if (lineStyle["stroke-width"]) {
                    trackerWidth = 10 + parseFloat(lineStyle["stroke-width"]);
                } else {
                    trackerWidth = 10;
                }
                tracker.attr({
                    "stroke-width": trackerWidth,
                    stroke: "#C0C0C0",
                    opacity: 0.01
                });
                $.wijraphael.addClass($(tracker.node), Raphael.format("{0} {1} {2}", wijCSS.canvasObject, wijCSS.lineElement, wijCSS.lineTracker));
                $(tracker.node).data("owner", $(path.node));

                if (type === "area") {
                    if (lineStyle.fill && lineStyle.fill !== "none") {
                        fill = lineStyle.fill;
                        delete lineStyle.fill;
                    } else {
                        fill = lineStyle.stroke;
                    }

                    fillOpacity = 0.5;
                    opacity = 1;
                    if (lineStyle["fill-opacity"] && lineStyle["fill-opacity"] !== "none") {
                        fillOpacity = lineStyle["fill-opacity"];
                    }
                    if (lineStyle["opacity"] && lineStyle["opacity"] !== "none") {
                        opacity = lineStyle["opacity"];
                    }
                    path.wijAttr(lineStyle);

                    if (pathArr.length > 1) {
                        startX = pathArr[1];
                    } else {
                        startX = bounds.startX;
                    }
                    if (stacked) {
                        //fix #35792
                        /*
                        if (pathIdx > 0) {
                        prevPathArr = Raphael.parsePathString(
                        paths[pathIdx - 1].attr("path"));
                        if (prevPathArr && prevPathArr.length > 0) {
                        for (idx = prevPathArr.length - 1; idx >= 0; idx--) {
                        prevPath = prevPathArr[idx];
                        if (prevPath.length === 3) {
                        pathArr.push("L");
                        pathArr.push(prevPath[1]);
                        pathArr.push(prevPath[2]);
                        }
                        }
                        pathArr.push("Z");
                        }
                        }
                        else {
                        */
                        pathArr.push("V");
                        pathArr.push(endY);
                        pathArr.push("H");
                        pathArr.push(startX);
                        pathArr.push("Z");
                        //}
                        //end
                    } else {
                        currentPathArr = Raphael.parsePathString(path.attr("path"));
                        if (currentPathArr && currentPathArr.length > 0) {
                            pathArr = [];
                            $.each(currentPathArr, function (i, currentPath) {
                                $.each(currentPath, function (j, val) {
                                    pathArr.push(val);
                                });
                                if (currentPath[0] === "M") {
                                    startX = currentPath[1];
                                }
                                if (i < currentPathArr.length - 1 && currentPathArr[i + 1][0] === "M") {
                                    pathArr.push("V");
                                    pathArr.push(endY);
                                    pathArr.push("H");
                                    pathArr.push(startX);
                                    pathArr.push("Z");
                                }
                                if (i === currentPathArr.length - 1) {
                                    pathArr.push("V");
                                    pathArr.push(endY);
                                    pathArr.push("H");
                                    pathArr.push(startX);
                                    pathArr.push("Z");
                                }
                            });
                        }
                    }
                    area = canvas.path(pathArr.join(" "));
                    $.wijraphael.addClass($(area.node), wijCSS.areaElement);
                    area.wijAttr({
                        fill: fill,
                        opacity: opacity,
                        "fill-opacity": fillOpacity,
                        stroke: "none"
                    });

                    initAniPath.push("V");
                    initAniPath.push(endY);
                    initAniPath.push("H");
                    initAniPath.push(startX);
                    initAniPath.push("Z");
                    area.straight = initAniPath.join(" ");

                    //area.toBack();
                    path.area = area;
                    animationSet.push(area);

                    aniPathsAttr.push({
                        path: $.extend(true, {}, path.attr()),
                        area: $.extend(true, {}, area.attr()),
                        markers: aniMarkersAttr,
                        labels: aniLabelsAttr
                    });
                } else {
                    //remove fill attribute when painting line.
                    //path.wijAttr(lineStyle);
                    noFillStyle = $.extend(true, {}, lineStyle);
                    if (noFillStyle.fill) {
                        delete noFillStyle.fill;
                    }
                    path.wijAttr(noFillStyle);

                    //end comments.
                    if (lineHoverStyle.fill) {
                        delete lineHoverStyle.fill;
                    }

                    aniPathsAttr.push({
                        path: $.extend(true, {}, path.attr()),
                        markers: aniMarkersAttr,
                        labels: aniLabelsAttr
                    });
                }

                path.markers = markers;

                paths.push(path);
                if (path.shadow) {
                    shadowPaths[pathIdx] = path.shadow;
                }

                animationSet.push(path);

                linesStyle[pathIdx] = {
                    lineStyle: lineStyle,
                    lineHoverStyle: lineHoverStyle,
                    markerStyle: lineMarkerStyle,
                    markerHoverStyle: lineMarkerHoverStyle
                };

                if (!lineSeries.markers.visible || lineSeries.display === "hide") {
                    markers.hide();
                }
                if (!lineSeries.visible || lineSeries.display === "hide") {
                    path.hide();
                    if (path.tracker) {
                        path.tracker.hide();
                    }
                    if (path.shadow) {
                        path.shadow.hide();
                    }
                    if (path.area) {
                        path.area.hide();
                    }
                    path.visible = false;
                }

                if (lineSeries.markers.style) {
                    markers.attr(lineSeries.markers.style);
                }
                markers.toFront();
                if (defaultChartLabels.length) {
                    labelStyle = $.extend(true, {}, chartLabelStyle);
                    if (lineSeries.textStyle) {
                        labelStyle = $.extend(true, labelStyle, lineSeries.textStyle);
                    }
                    defaultChartLabels.attr(labelStyle);
                    defaultChartLabels.toFront();
                    path.labels = defaultChartLabels;
                }
                markersSet[pathIdx] = markers;
                lineSeries.index = pathIdx;
                lineSeries.type = "line";
                lineSeries.path = path;
                lineSeries.lineMarkers = markers;
                lineSeries.lineStyle = lineStyle;
                lineSeries.lineHoverStyle = lineHoverStyle;
                lineSeries.virtualMarkers = virtualMarkers;
                $.wijraphael.addClass($(path.node), Raphael.format("{0} {1}", wijCSS.canvasObject, wijCSS.lineElement));
                $(path.node).data("wijchartDataObj", lineSeries);
            };

            LineChartRender.prototype._calculatePoint = function (val, dir) {
                var axes = this.options.axis, axis = $.isArray(axes[dir]) ? axes[dir][0] : axes[dir], bounds = this.options.bounds, min = axis.min, max = axis.max, len, rate;

                if (dir === "x") {
                    rate = (bounds.endX - bounds.startX) / (max - min);
                    return bounds.startX + (val - min) * rate;
                } else {
                    rate = (bounds.endY - bounds.startY) / (max - min);
                    return bounds.endY - (val - min) * rate;
                }
            };

            LineChartRender.prototype.renderPoint = function (cBounds, canvas, initAniPath, pathArr, markers, aniMarkersAttr, animationSet, defaultChartLabels, aniLabelsAttr, chartLabelEles, chartLabelFormatString, needAnimated, firstYPoint, lastYPoint, valX, valY, dataY, axis, fitType, isXTime, isYTime, pointIdx, lineMarkerStyle, lineMarkerHoverStyle, lineSeries, paintSymbol, showChartLabels, symbols, valuesX, valuesY, valsY, display, stacked, virtualMarkers, culture, wijCSS, sIdx, chartLabelFormatter) {
                var width = cBounds.endX - cBounds.startX, height = cBounds.endY - cBounds.startY, minX = axis.x.min, minY = axis.y.min, maxX = axis.x.max, maxY = axis.y.max, kx = width / (maxX - minX), ky = height / (maxY - minY), marker, dot, val, X = 0, Y, initAniY, markerData, defaultChartLabel, markerVisible = lineSeries.markers.visible, widget = this.widget, pointX, annotation;
                if (isNaN(valX) || typeof valX === "string") {
                    val = pointIdx;
                } else {
                    val = valX;
                }
                X = this._calculatePoint(val, "x");
                Y = this._calculatePoint(valY, "y");
                valsY[pointIdx].x = X;
                valsY[pointIdx].y = Y;

                if (needAnimated) {
                    initAniY = firstYPoint + (lastYPoint - firstYPoint) / (maxX - minX) * (val - minX);
                    initAniY = cBounds.endY - (initAniY - minY) * ky;
                    initAniPath.push(valsY[pointIdx].idx ? "L" : "M");
                    initAniPath.push(X);
                    initAniPath.push(initAniY);
                }

                if (!valsY[pointIdx].isHole) {
                    pathArr = this.getPathArrByFitType(pathArr, fitType, pointIdx, valuesY.length, cBounds, valuesX, valuesY, X, Y, isXTime, isYTime, valX, valY, valsY, display, stacked);
                } else {
                    return pathArr;
                }

                if (showChartLabels) {
                    defaultChartLabel = this.renderChartLabel(canvas, isYTime, { x: valX, y: valY, sIdx: sIdx }, chartLabelFormatString, chartLabelFormatter, X, Y, culture, wijCSS);
                    chartLabelEles.push(defaultChartLabel);
                    defaultChartLabels.push(defaultChartLabel);
                    aniLabelsAttr.push($.extend(true, {}, defaultChartLabel.attr()));
                }
                annotation = { x: X, y: Y };
                if (this.annoPoints[sIdx] == null)
                    this.annoPoints[sIdx] = {};
                this.annoPoints[sIdx][pointIdx] = annotation;

                if (markerVisible) {
                    marker = this.renderMarker(canvas, symbols, paintSymbol, lineSeries.markers, pointIdx, X, Y, lineMarkerStyle, wijCSS);
                    dot = marker.dot;

                    if (needAnimated) {
                        dot.straight = initAniY;
                    }
                }

                markerData = {};
                markerData.valX = valuesX[pointIdx];
                markerData.valY = dataY;
                markerData.index = pointIdx;
                markerData.type = "marker";
                markerData.lineSeries = lineSeries;
                markerData.x = X;
                markerData.y = Y;
                markerData.markerStyle = lineMarkerStyle;
                markerData.markerHoverStyle = lineMarkerHoverStyle;
                markerData.visible = true;

                if (markerVisible) {
                    markerData.marker = dot;
                    markerData.isSymbol = marker.isSymbol;
                    $(dot.node).data("wijchartDataObj", markerData);
                    markers.push(dot);

                    aniMarkersAttr.push($.extend(true, {}, dot.attr()));
                    animationSet.push(dot);
                }

                // cache the bar position to show indicator line.
                widget.dataPoints = widget.dataPoints || {};
                widget.pointXs = widget.pointXs || [];
                pointX = $.round(X, 2);

                if (!widget.dataPoints[pointX.toString()]) {
                    widget.dataPoints[pointX.toString()] = [];
                    widget.pointXs.push(pointX);
                }
                widget.dataPoints[pointX.toString()].push(markerData);
                virtualMarkers.push(markerData);
                return pathArr;
            };

            LineChartRender.prototype.processYValues = function (values, display, hole, stacked, lastValues) {
                var vals = [], idx = 0, firstYIdx = 0;
                $.each(values, function (i, value) {
                    if (!idx) {
                        firstYIdx = i;
                    }
                    var val = {
                        isHole: false,
                        isValue: true,
                        idx: idx,
                        firstYIdx: firstYIdx,
                        x: 0,
                        y: 0
                    };
                    idx++;

                    if (chart.ChartUtil.isHolefunction(value, hole)) {
                        if (stacked) {
                            values[i] = 0;
                        } else {
                            val.isHole = true;
                            if (display === "excludeHole") {
                                idx--;
                                val.idx = 0;
                            } else {
                                idx = 0;
                                val.idx = 0;
                            }
                            if (!chart.ChartUtil.isHolefunction(hole, undefined) && value === hole) {
                                val.isValue = true;
                            } else {
                                val.isValue = false;
                            }
                        }
                    }
                    vals.push(val);
                    if (stacked && i < lastValues.length) {
                        values[i] += lastValues[i];
                    }
                });
                lastValues.length = 0;
                $.merge(lastValues, values);
                return vals;
            };

            LineChartRender.prototype.renderMarker = function (canvas, symbols, paintSymbol, markers, markerIdx, X, Y, lineMarkerStyle, wijCSS) {
                var symbs, dot = null, isSymbol = false, markerType, markerWidth;
                if (paintSymbol) {
                    symbs = markers.symbol;
                    $.each(symbs, function (idx, symbol) {
                        if (symbol.index === markerIdx) {
                            dot = canvas.image(symbol.url, X - symbol.width / 2, Y - symbol.height / 2, symbol.width, symbol.height);
                            symbols.push(dot);
                            isSymbol = true;
                            return false;
                        }
                    });
                }
                if (dot === null) {
                    markerType = markers.type;
                    markerWidth = lineMarkerStyle.width;
                    dot = canvas.paintMarker(markerType, X, Y, markerWidth);
                    if (markers.visible) {
                        dot.attr(lineMarkerStyle);
                    }
                }

                $.wijraphael.addClass($(dot.node), Raphael.format("{0} {1} {2}", wijCSS.canvasObject, wijCSS.lineElement, wijCSS.canvasMarker));
                return {
                    dot: dot,
                    isSymbol: isSymbol
                };
            };

            LineChartRender.prototype.renderChartLabel = function (canvas, isYTime, points, chartLabelFormatString, chartLabelFormatter, X, Y, culture, wijCSS) {
                var labelText, defaultChartLabel, dclBox, widget = this.options.widget, processedChartLabel, chartLabelStyle, o = this.options;

                //Add comments by RyanWu@20110707.
                //For supporting date time value on y axi.
                //labelText = valY;
                labelText = isYTime ? $.fromOADate(points.y) : points.y, processedChartLabel = chart.ChartUtil.getChartLabel(chartLabelFormatString, labelText, culture, {
                    index: points.sIdx,
                    data: { x: points.x, y: points.y },
                    value: points.y,
                    chartLabelFormatter: chartLabelFormatter
                });
                labelText = processedChartLabel.text;
                chartLabelStyle = $.extend(true, {}, o.textStyle, o.chartLabelStyle);
                defaultChartLabel = widget._text.call(widget, X, Y, labelText);
                defaultChartLabel.wijAttr(chartLabelStyle);
                $.wijraphael.addClass($(defaultChartLabel.node), wijCSS.lineLabel);
                dclBox = defaultChartLabel.wijGetBBox();
                defaultChartLabel.transform(Raphael.format("...T{0},{1}", 0, -dclBox.height));
                return defaultChartLabel;
            };

            LineChartRender.prototype.getAnchors = function (p1x, p1y, p2x, p2y, p3x, p3y) {
                var l1 = (p2x - p1x) / 2, l2 = (p3x - p2x) / 2, a = Math.atan((p2x - p1x) / Math.abs(p2y - p1y)), b = Math.atan((p3x - p2x) / Math.abs(p2y - p3y)), alpha = 0, dx1 = 0, dy1 = 0, dx2 = 0, dy2 = 0;
                a = p1y < p2y ? Math.PI - a : a;
                b = p3y < p2y ? Math.PI - b : b;
                alpha = Math.PI / 2 - ((a + b) % (Math.PI * 2)) / 2;
                dx1 = l1 * Math.sin(alpha + a);
                dy1 = l1 * Math.cos(alpha + a);
                dx2 = l2 * Math.sin(alpha + b);
                dy2 = l2 * Math.cos(alpha + b);
                return {
                    x1: p2x - dx1,
                    y1: p2y + dy1,
                    x2: p2x + dx2,
                    y2: p2y + dy2
                };
            };

            LineChartRender.prototype.getPathArrByFitType = function (pathArr, fitType, idx, len, cBounds, valuesX, valuesY, X, Y, isXTime, isYTime, valX, valY, valsY, display, stacked) {
                var valY2 = null, Y0 = 0, Y2 = 0, X0 = 0, X2 = 0, valX2 = null, a = null, valueY = valsY[idx], isNextPointHole = false, index = valueY.idx, i, prevIdx = idx - 1, nextIdx = idx + 1;
                if (display === "excludeHole" && !stacked) {
                    if (idx > 0 && idx < len - 1) {
                        nextIdx = -1;
                        prevIdx = -1;
                        for (i = idx + 1; i < len; i++) {
                            isNextPointHole = true;
                            if (valsY[i].isHole) {
                                continue;
                            }
                            nextIdx = i;
                            isNextPointHole = false;
                            break;
                        }
                        for (i = idx - 1; i >= 0; i--) {
                            if (valsY[i].isHole) {
                                continue;
                            }
                            prevIdx = i;
                            break;
                        }
                        if (prevIdx > -1) {
                            X0 = valsY[prevIdx].x;
                            Y0 = valsY[prevIdx].y;
                        }
                    }
                } else {
                    if (idx < len - 1) {
                        isNextPointHole = valsY[nextIdx].isHole;
                    }
                    if (idx > 0 && idx < len - 1) {
                        X0 = valsY[prevIdx].x;
                        Y0 = valsY[prevIdx].y;
                    }
                }
                if (fitType === "line") {
                    pathArr = pathArr.concat([index ? "L" : "M", X, Y]);
                } else if (fitType === "spline") {
                    if (!index) {
                        if (idx === len - 1) {
                            pathArr = pathArr.concat(["M", X, Y]);
                        } else if (isNextPointHole) {
                            pathArr = pathArr.concat(["M", X, Y]);
                        } else {
                            pathArr = pathArr.concat(["M", X, Y, "C", X, Y]);
                        }
                    } else if (index && idx < len - 1 && !isNextPointHole) {
                        valY2 = valuesY[nextIdx];
                        if (isYTime) {
                            valY2 = $.toOADate(valY2);
                        }

                        //Y2 = cBounds.endY - (valY2 - minY) * ky;
                        Y2 = this._calculatePoint(valY2, "y");
                        if (isNaN(valX) || typeof valX === "string") {
                            X2 = this._calculatePoint(nextIdx, "x");
                        } else {
                            valX2 = valuesX[nextIdx];
                            if (isXTime) {
                                valX2 = $.toOADate(valX2);
                            }
                            X2 = this._calculatePoint(valX2, "x");
                        }
                        a = this.getAnchors(X0, Y0, X, Y, X2, Y2);
                        pathArr = pathArr.concat([a.x1, a.y1, X, Y, a.x2, a.y2]);
                    } else {
                        pathArr = pathArr.concat([X, Y, X, Y]);
                    }
                } else if (fitType === "bezier") {
                    if (!index) {
                        pathArr = pathArr.concat(["M", X, Y]);
                    } else if ((idx < len - 1 && valsY[idx + 1].isHole && index % 2 === 1) || (idx === len - 1 && index % 2 === 1)) {
                        pathArr = pathArr.concat(["Q", X, Y, X, Y]);
                    } else {
                        if (index % 2 === 0) {
                            pathArr = pathArr.concat([X, Y]);
                        } else {
                            pathArr = pathArr.concat(["Q", X, Y]);
                        }
                    }
                }
                return pathArr;
            };

            LineChartRender.prototype.bindLiveEvents = function (element, canvas, cBounds, widgetName, mouseDown, mouseUp, mouseOver, mouseOut, mouseMove, click, disabled, hint, linesStyle, tooltip, wijCSS) {
                var touchEventPre = "", proxyObj = {
                    element: element,
                    mousedown: function (e) {
                        if (disabled) {
                            return;
                        }

                        var tar = $(e.target), data, lineSeries = null;
                        if (tar.data("owner")) {
                            tar = tar.data("owner");
                        }
                        data = tar.data("wijchartDataObj");

                        if (tar.hasClass(wijCSS.canvasMarker)) {
                            lineSeries = data.lineSeries;
                            if (!lineSeries.markers.visible) {
                                mouseDown.call(element, e, lineSeries);
                            } else {
                                mouseDown.call(element, e, data);
                            }
                        } else {
                            mouseDown.call(element, e, data);
                        }
                    },
                    mouseup: function (e) {
                        if (disabled) {
                            return;
                        }

                        var tar = $(e.target), data, lineSeries = null;
                        if (tar.data("owner")) {
                            tar = tar.data("owner");
                        }
                        data = tar.data("wijchartDataObj");

                        if (tar.hasClass(wijCSS.canvasMarker)) {
                            lineSeries = data.lineSeries;
                            if (!lineSeries.markers.visible) {
                                mouseUp.call(element, e, lineSeries);
                            } else {
                                mouseUp.call(element, e, data);
                            }
                        } else {
                            mouseUp.call(element, e, data);
                        }
                    },
                    mouseover: function (e) {
                        if (disabled) {
                            return;
                        }

                        var tar = $(e.target), data, lineSeries = null;
                        if (tar.data("owner")) {
                            tar = tar.data("owner");
                        }
                        data = tar.data("wijchartDataObj");

                        if (tar.hasClass(wijCSS.canvasMarker)) {
                            lineSeries = data.lineSeries;
                            if (!lineSeries.markers.visible) {
                                mouseOver.call(element, e, lineSeries);
                            } else {
                                mouseOver.call(element, e, data);
                            }
                        } else {
                            mouseOver.call(element, e, data);
                        }
                    },
                    mouseout: function (e) {
                        if (disabled) {
                            return;
                        }

                        var tar = $(e.target), data, lineSeries = null;
                        if (tar.data("owner")) {
                            tar = tar.data("owner");
                        }
                        data = tar.data("wijchartDataObj");

                        if (tar.hasClass(wijCSS.canvasMarker)) {
                            lineSeries = data.lineSeries;
                            if (!lineSeries.markers.visible) {
                                mouseOut.call(element, e, lineSeries);
                            } else {
                                mouseOut.call(element, e, data);
                            }
                        } else {
                            mouseOut.call(element, e, data);
                        }
                    },
                    mousemove: function (e) {
                        if (disabled) {
                            return;
                        }

                        var tar = $(e.target), data, lineSeries = null;
                        if (tar.data("owner")) {
                            tar = tar.data("owner");
                        }
                        data = tar.data("wijchartDataObj");

                        if (tar.hasClass(wijCSS.canvasMarker)) {
                            lineSeries = data.lineSeries;
                            if (!lineSeries.markers.visible) {
                                mouseMove.call(element, e, lineSeries);
                            } else {
                                mouseMove.call(element, e, data);
                            }
                        } else {
                            mouseMove.call(element, e, data);
                        }
                    },
                    click: function (e) {
                        if (disabled) {
                            return;
                        }

                        var tar = $(e.target), data, lineSeries = null;
                        if (tar.data("owner")) {
                            tar = tar.data("owner");
                        }
                        data = tar.data("wijchartDataObj");

                        if (tar.hasClass(wijCSS.canvasMarker)) {
                            lineSeries = data.lineSeries;
                            if (!lineSeries.markers.visible) {
                                click.call(element, e, lineSeries);
                            } else {
                                click.call(element, e, data);
                            }
                        } else {
                            click.call(element, e, data);
                        }
                    }
                };

                if ($.support.isTouchEnabled && $.support.isTouchEnabled()) {
                    touchEventPre = "wij";
                }
                element.on(touchEventPre + "mousedown." + widgetName, "." + wijCSS.lineElement, $.proxy(proxyObj.mousedown, proxyObj)).on(touchEventPre + "mouseup." + widgetName, "." + wijCSS.lineElement, $.proxy(proxyObj.mouseup, proxyObj)).on(touchEventPre + "mouseover." + widgetName, "." + wijCSS.lineElement, $.proxy(proxyObj.mouseover, proxyObj)).on(touchEventPre + "mouseout." + widgetName, "." + wijCSS.lineElement, $.proxy(proxyObj.mouseout, proxyObj)).on(touchEventPre + "mousemove." + widgetName, "." + wijCSS.lineElement, $.proxy(proxyObj.mousemove, proxyObj)).on(touchEventPre + "click." + widgetName, "." + wijCSS.lineElement, $.proxy(proxyObj.click, proxyObj));

                chart.TrendlineRender.bindLiveEvents(element, widgetName, mouseDown, mouseUp, mouseOver, mouseOut, mouseMove, click, disabled, wijCSS, true);
            };

            LineChartRender.prototype.unbindLiveEvents = function (element, widgetName, wijCSS) {
                element.off("." + widgetName, "." + wijCSS.lineElement);
                chart.TrendlineRender.unbindLiveEvents(element, widgetName, wijCSS);
            };
            return LineChartRender;
        })(chart.BaseChartRender);
        chart.LineChartRender = LineChartRender;
    })(wijmo.chart || (wijmo.chart = {}));
    var chart = wijmo.chart;
})(wijmo || (wijmo = {}));

;
/// <reference path="../wijchart/jquery.wijmo.wijchartcore.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*globals Raphael,jQuery, window, Globalize*/
    /*
    * Depends:
    *	jquery.js
    *	raphael.js
    *	globalize.js
    *	jquery.ui.widget.js
    *	jquery.wijmo.raphael.js
    *	jquery.wijmo.wijchartcore.js
    *
    */
    (function (chart) {
        var PI = 180;
        var TwoPI = 360;

        /**
        * @widget
        */
        var wijpiechart = (function (_super) {
            __extends(wijpiechart, _super);
            function wijpiechart() {
                _super.apply(this, arguments);
            }
            wijpiechart.prototype._create = function () {
                this._handleChartStyles();
                _super.prototype._create.call(this);
                this.chartElement.addClass(this.options.wijCSS.pieChart);
            };

            /** Removes the functionality completely.
            * This will return the element back to its pre-init state.
            */
            wijpiechart.prototype.destroy = function () {
                var wijCSS = this.options.wijCSS, element = this.chartElement, fields = element.data("fields"), aniSectors = fields && fields.sectors, aniLabels = fields && fields.labels;

                element.removeClass(wijCSS.pieChart);
                _super.prototype.destroy.call(this);

                if (aniSectors && aniSectors.length) {
                    $.each(aniSectors, function (idx, sector) {
                        sector = null;
                    });
                }
                if (aniLabels && aniLabels.length) {
                    $.each(aniLabels, function (idx, label) {
                        label = null;
                    });
                }

                element.data("fields", null);
            };

            wijpiechart.prototype._isPieChart = function () {
                return true;
            };

            /** Returns the sector of the pie chart with the given index.
            * @param {number} index The index of the sector.
            * @returns {Raphael Element} Reference to raphael element object.
            */
            wijpiechart.prototype.getSector = function (index) {
                var fields = this.chartElement.data("fields");
                if (fields && fields.chartElements) {
                    return fields.chartElements.sectors[index];
                }
                return null;
            };

            //add binding for pie chart
            wijpiechart.prototype._bindData = function () {
                var o = this.options, ds = o.dataSource, data = o.data, seriesList = [], dataLabel, dataValue, dataOffset;

                if (ds && data) {
                    dataLabel = data.label;
                    dataValue = data.value;
                    dataOffset = data.offset;
                    if (dataLabel && dataLabel.bind) {
                        dataLabel = this._getBindData(ds, dataLabel.bind);
                    }
                    if (dataValue && dataValue.bind) {
                        dataValue = this._getBindData(ds, dataValue.bind);
                    }
                    if (dataOffset && dataOffset.bind) {
                        dataOffset = this._getBindData(ds, dataOffset.bind);
                    }
                    if (dataLabel && $.isArray(dataLabel) && dataLabel.length && dataValue && $.isArray(dataValue) && dataValue.length) {
                        $.each(dataValue, function (idx, val) {
                            var label, offset = 0;
                            if (idx >= 0 && idx < dataLabel.length) {
                                label = dataLabel[idx];
                            }
                            if (dataOffset && $.isArray(dataValue) && dataOffset.length && idx >= 0 && idx < dataOffset.length) {
                                offset = typeof dataOffset[idx] === 'undefined' ? 0 : dataOffset[idx];
                            }
                            seriesList.push({
                                data: val,
                                label: label,
                                offset: offset,
                                legendEntry: true
                            });
                        });
                        o.seriesList = seriesList;
                    }
                }
            };

            //Override chartcore's _hanldSharedXData, there's no x/y axis in piechart.
            wijpiechart.prototype._hanldSharedXData = function () {
            };

            wijpiechart.prototype._checkSeriesDataEmpty = function (series) {
                return isNaN(series.data);
            };

            wijpiechart.prototype._getSeriesFromTR = function (theaders, sList, seriesList) {
                var label = null, th = null, tds = null, data = null, series = null;
                if (sList.length) {
                    sList.each(function () {
                        th = $("th", $(this));
                        label = $.trim(th.text());
                        tds = $("td", $(this));
                        if (tds.length) {
                            data = parseFloat($.trim($(tds[0]).text()));
                        }
                        series = {
                            label: label,
                            legendEntry: true,
                            data: data
                        };
                        seriesList.push(series);
                    });
                }
            };

            wijpiechart.prototype._showSerieEles = function (seriesEle) {
                var showLabels = this.options.showChartLabels;
                if (seriesEle.sector) {
                    seriesEle.sector.show();
                    if (seriesEle.sector.shadow) {
                        seriesEle.sector.shadow.show();
                    }
                    if (seriesEle.sector.tracker) {
                        seriesEle.sector.tracker.show();
                    }
                }
                if (seriesEle.label && showLabels) {
                    seriesEle.label.show();
                    if (seriesEle.label.connector) {
                        seriesEle.label.connector.show();
                    }
                    $(seriesEle.label.node).data("legendHide", false);
                }
            };

            wijpiechart.prototype._hideSerieEles = function (seriesEle) {
                if (seriesEle.sector) {
                    seriesEle.sector.hide();
                    if (seriesEle.sector.shadow) {
                        seriesEle.sector.shadow.hide();
                    }
                    if (seriesEle.sector.tracker) {
                        seriesEle.sector.tracker.hide();
                    }
                }
                if (seriesEle.label) {
                    seriesEle.label.hide();
                    if (seriesEle.label.connector) {
                        seriesEle.label.connector.hide();
                    }
                    $(seriesEle.label.node).data("legendHide", true);
                }
            };

            wijpiechart.prototype._hasAxes = function () {
                return false;
            };

            wijpiechart.prototype._mouseMoveInsidePlotArea = function (e, mousePos) {
                _super.prototype._mouseMoveInsidePlotArea.call(this, e, mousePos);
                if (this.isTapAndHold) {
                    var previousAngle = this.previousAngle, rotation = 0, rotationStr = "", element = this.chartElement, dataObj = this.tapTarget ? this.tapTarget.data("wijchartDataObj") : {}, pieId = dataObj.pieID || "", sectors = element.data("fields").chartElements["sectors" + pieId], cb = this.canvasBounds, pieCX = (cb.startX + cb.endX) / 2, pieCY = (cb.startY + cb.endY) / 2, angle = Raphael.angle(mousePos.left, mousePos.top, pieCX, pieCY);
                    if (previousAngle) {
                        rotation = Math.round(angle - previousAngle);
                        if (Math.abs(angle - previousAngle) > PI) {
                            if (angle > previousAngle) {
                                rotation = rotation - TwoPI;
                            } else {
                                rotation = rotation + TwoPI;
                            }
                        }
                        if (rotation) {
                            rotationStr = Raphael.format("...r{0},{1},{2}", rotation, pieCX, pieCY);
                            $.each(sectors, function (idx, sector) {
                                sector.transform(rotationStr);
                            });
                            if (this.tooltip) {
                                this._setTouchTooltip(null);
                            }
                        }
                    }
                    this.previousAngle = angle;
                }
            };

            wijpiechart.prototype._mouseMoveOutsidePlotArea = function (e, mousePos) {
                _super.prototype._mouseMoveOutsidePlotArea.call(this, e, mousePos);
                if (this.isTapAndHold) {
                    this._rotateToSectorCenter(null);
                }
            };

            wijpiechart.prototype._rotateToSectorCenter = function (specifiedSector) {
                var _this = this;
                var animation = this.options.animation, element = this.chartElement, dataObj = this.tapTarget ? this.tapTarget.data("wijchartDataObj") : {}, pieId = dataObj.pieID || "", sectors = element.data("fields").chartElements["sectors" + pieId], labels = element.data("fields").chartElements["labels" + pieId], cb = this.canvasBounds, pieCX = (cb.startX + cb.endX) / 2, pieCY = (cb.startY + cb.endY) / 2, animate, touchSector, angle, self = this;

                this._hideSectorElements(sectors, labels);
                if (this.tooltip) {
                    touchSector = this._getTouchttSector(specifiedSector);
                }

                //add targetCenterAngle >=0.01 to prevent the precision issue.
                if (this.touchttSector && this.touchttSector === touchSector && Math.abs(this.targetCenterAngle) >= 0.01) {
                    if (this.targetCenterAngle > PI) {
                        angle = this.targetCenterAngle - TwoPI;
                    } else if (this.targetCenterAngle < -PI) {
                        angle = this.targetCenterAngle + TwoPI;
                    } else {
                        angle = this.targetCenterAngle;
                    }
                    animate = Raphael.animation({
                        transform: Raphael.format("...r{0},{1},{2}", angle, pieCX, pieCY)
                    }, animation.duration, animation.easing, function () {
                        self._rotateCallback(this, labels);
                    });

                    $.each(sectors, function (idx, sector) {
                        sector.animate(animate);
                    });
                } else {
                    $.each(sectors, function (idx, sector) {
                        _this._rotateCallback(sector, labels);
                    });
                }
                this.previousAngle = null;
                this.isTapAndHold = false;
                this.tapTarget = null;
            };

            wijpiechart.prototype._rotateCallback = function (sector, labels) {
                var cb = this.canvasBounds, pieCX = (cb.startX + cb.endX) / 2, pieCY = (cb.startY + cb.endY) / 2, idx = sector.index, rotation = 0, transforms = sector.attr("transform"), transformAttr, label;
                $.each(transforms, function (idx, transform) {
                    if (transform[0] !== "r") {
                        return true;
                    }
                    if (transform.length >= 4) {
                        rotation += transform[1];
                    }
                });

                transformAttr = Raphael.format("r{0},{1},{2}", rotation, pieCX, pieCY);
                if (pieCX > 0) {
                    rotation = rotation % TwoPI;
                    transformAttr = Raphael.format("r{0},{1},{2}", rotation, pieCX, pieCY);
                    sector.attr("transform", transformAttr);
                }
                if (sector.tracker) {
                    sector.tracker.attr("transform", transformAttr);
                    sector.tracker.show();
                }
                if (sector.shadow) {
                    sector.shadow.attr("transform", transformAttr);
                    sector.shadow.show();
                }
                if (labels && labels.length && labels.length > idx) {
                    label = labels[idx];
                    label.attr("transform", Raphael.format("r{0},{1},{2}r{3}", rotation, pieCX, pieCY, 0 - rotation));
                    if (label.connector) {
                        label.connector.attr("transform", transformAttr);
                    }

                    if ($(label.node).data("legendHide")) {
                        return;
                    }
                    label.show();
                    if (label.connector) {
                        label.connector.show();
                    }
                }
            };

            wijpiechart.prototype._getTouchttSector = function (specifiedSector) {
                var _this = this;
                var element = this.chartElement, dataObj = this.tapTarget ? this.tapTarget.data("wijchartDataObj") : {}, pieId = dataObj.pieID || "", sectors = element.data("fields").chartElements["sectors" + pieId], ttOpts = this.tooltip.getOptions(), ttCompass = ttOpts.compass, targetAngle = 90, targetSector;
                switch (ttCompass) {
                    case "east":
                        targetAngle = 0;
                        break;
                    case "south":
                        targetAngle = 270;
                        break;
                    case "west":
                        targetAngle = PI;
                        break;
                    case "north":
                    default:
                        targetAngle = 90;
                }

                $.each(sectors, function (idx, sector) {
                    var transforms = sector.attr("transform"), rotation = 0, angle = sector.angles;

                    $.each(transforms, function (idx, transform) {
                        if (transform[0] !== "r") {
                            return true;
                        }
                        if (transform.length >= 4) {
                            rotation += transform[1];
                        }
                    });
                    rotation = rotation % TwoPI;
                    if (rotation < 0) {
                        rotation = TwoPI + rotation;
                    }
                    rotation = (targetAngle + rotation) % TwoPI;
                    if (specifiedSector) {
                        if (sector === specifiedSector) {
                            _this.targetCenterAngle = (angle.start + angle.end) / 2 - rotation;
                            targetSector = specifiedSector;
                            return false;
                        }
                    } else {
                        if (angle.start <= rotation && angle.end >= rotation) {
                            _this.targetCenterAngle = (angle.start + angle.end) / 2 - rotation;
                            targetSector = sector;
                            return false;
                        }
                    }
                });
                return targetSector;
            };

            wijpiechart.prototype._setTouchTooltip = function (specifiedSector) {
                var ttOpts = this.tooltip.getOptions(), ttCompass = ttOpts.compass, sector = this._getTouchttSector(specifiedSector), hint = this.options.hint, title = hint.title, content = hint.content, isTitleFunc = $.isFunction(title), isContentFunc = $.isFunction(content), dataObj, obj;
                if (!sector || (this.touchttSector && this.touchttSector === sector)) {
                    return;
                }
                dataObj = $(sector.node).data("wijchartDataObj");
                obj = {
                    data: dataObj,
                    value: dataObj.value,
                    label: dataObj.label,
                    total: dataObj.total,
                    y: dataObj.value
                };
                if (isTitleFunc || isContentFunc) {
                    if (isTitleFunc) {
                        ttOpts.title = function () {
                            obj.fmt = title;
                            var fmt = $.proxy(obj.fmt, obj), tit = fmt();
                            return tit;
                        };
                    }
                    if (isContentFunc) {
                        ttOpts.content = function () {
                            obj.fmt = content;
                            var fmt = $.proxy(obj.fmt, obj), con = fmt();
                            return con;
                        };
                    }
                }
                this._showTouchTooltip(ttCompass);
                this.touchttSector = sector;
            };

            wijpiechart.prototype._showTouchTooltip = function (compass) {
                var element = this.chartElement, cb = this.canvasBounds, point = { x: 0, y: 0 };
                switch (compass) {
                    case "east":
                        point = {
                            x: element.width(),
                            y: (cb.startY + cb.endY) / 2
                        };
                        break;
                    case "south":
                        point = {
                            x: (cb.startX + cb.endX) / 2,
                            y: element.height()
                        };
                        break;
                    case "west":
                        point = {
                            x: 0,
                            y: (cb.startY + cb.endY) / 2
                        };
                        break;
                    case "north":
                    default:
                        point = {
                            x: (cb.startX + cb.endX) / 2,
                            y: 0
                        };
                }
                this.tooltip.showAt(point);
            };

            wijpiechart.prototype._isTouchBehaviorEnabled = function () {
                return this.options.enableTouchBehavior && this._isTouchEnabled();
            };

            wijpiechart.prototype._mouseDown = function (e, args) {
                var target = $(e.target), element = this.chartElement, pieId, sectors, labels;

                _super.prototype._mouseDown.call(this, e, args);
                if (this._isTouchBehaviorEnabled()) {
                    this.isTapAndHold = true;
                    if (target.data("owner")) {
                        target = target.data("owner");
                    }
                    this.tapTarget = target;
                    pieId = args.pieID || "";
                    sectors = element.data("fields").chartElements["sectors" + pieId];
                    labels = element.data("fields").chartElements["labels" + pieId];

                    this._hideSectorElements(sectors, labels);
                }
            };

            wijpiechart.prototype._hideSectorElements = function (sectors, labels) {
                $.each(sectors, function (idx, sector) {
                    sector.stop();
                    if (sector.tracker) {
                        sector.tracker.hide();
                    }
                    if (sector.shadow) {
                        sector.shadow.hide();
                    }
                    if (labels && labels.length) {
                        var label = labels[idx];
                        label.hide();
                        if (label.connector) {
                            label.connector.hide();
                        }
                    }
                });
            };

            wijpiechart.prototype._mouseUp = function (e, args) {
                _super.prototype._mouseUp.call(this, e, args);
                if (this._isTouchBehaviorEnabled() && this.isTapAndHold) {
                    this._rotateToSectorCenter(null);
                }
            };

            wijpiechart.prototype._mouseOver = function (e, args) {
                _super.prototype._mouseOver.call(this, e, args);
            };

            wijpiechart.prototype._mouseOut = function (e, args) {
                _super.prototype._mouseOut.call(this, e, args);
            };

            wijpiechart.prototype._mouseMove = function (e, args) {
                _super.prototype._mouseMove.call(this, e, args);
            };

            wijpiechart.prototype._click = function (e, args) {
                var element = this.chartElement, pieId, sectors, sector;

                _super.prototype._click.call(this, e, args);
                if (this._isTouchBehaviorEnabled() && this.tooltip) {
                    pieId = args.pieID || "";
                    sectors = element.data("fields").chartElements["sectors" + pieId];
                    if (sectors.length && sectors.length > args.index) {
                        sector = sectors[args.index];
                        this._setTouchTooltip(sector);
                        this._rotateToSectorCenter(sector);
                    }
                }
            };

            wijpiechart.prototype._paintTooltip = function () {
                var wijCSS = this.options.wijCSS, element = this.chartElement, fields = element.data("fields");

                _super.prototype._paintTooltip.call(this);

                if (this.tooltip && fields) {
                    if (this._isTouchBehaviorEnabled()) {
                        this.tooltip.setOptions({
                            closeBehavior: "none",
                            mouseTrailing: false,
                            animated: null,
                            showAnimated: null,
                            windowCollisionDetection: "fit"
                        });
                        this._setTouchTooltip(null);
                        this._rotateToSectorCenter(null);
                    } else {
                        if (fields.trackers && fields.trackers.length) {
                            this.tooltip.setSelector($("." + wijCSS.canvasObject, element[0]));
                            this.tooltip.setOptions({ relatedElement: fields.trackers[0] });
                        }
                    }
                }
            };

            wijpiechart.prototype._paintPlotArea = function () {
                var o = this.options, canvasBounds = this.canvasBounds, width = canvasBounds.endX - canvasBounds.startX, height = canvasBounds.endY - canvasBounds.startY, r = o.radius;

                if (!r) {
                    r = Math.min(width, height) / 2;
                } else {
                    if (width < 2 * r) {
                        r = width / 2;
                    }
                    if (height < 2 * r) {
                        r = height / 2;
                    }
                }

                //remove to fix a resize issue.
                //o.radius = r;
                canvasBounds.startX += width / 2 - r;
                canvasBounds.endX = canvasBounds.startX + 2 * r;
                canvasBounds.startY += height / 2 - r;
                canvasBounds.endY = canvasBounds.startY + 2 * r;
                if (this.chartElement.data("fields")) {
                    this.chartElement.data("fields").seriesEles = null;
                }
                this.piechartRender = new PieChartRender(this.chartElement, {
                    canvas: this.canvas,
                    tooltip: this.tooltip,
                    bounds: canvasBounds,
                    wijCSS: o.wijCSS,
                    radius: r,
                    startAngle: o.startAngle,
                    widgetName: this.widgetName,
                    innerRadius: o.innerRadius,
                    seriesList: o.seriesList,
                    seriesStyles: o.seriesStyles,
                    seriesHoverStyles: o.seriesHoverStyles,
                    seriesTransition: o.seriesTransition,
                    showChartLabels: o.showChartLabels,
                    disabled: this._isDisabled(),
                    textStyle: o.textStyle,
                    chartLabelStyle: o.chartLabelStyle,
                    chartLabelFormatString: o.chartLabelFormatString,
                    chartLabelFormatter: o.chartLabelFormatter,
                    labels: o.labels,
                    shadow: o.shadow,
                    animation: o.animation,
                    culture: this._getCulture(),
                    mouseDown: $.proxy(this._mouseDown, this),
                    mouseUp: $.proxy(this._mouseUp, this),
                    mouseOver: $.proxy(this._mouseOver, this),
                    mouseOut: $.proxy(this._mouseOut, this),
                    mouseMove: $.proxy(this._mouseMove, this),
                    click: $.proxy(this._click, this),
                    widget: this,
                    enableTouchBehavior: o.enableTouchBehavior,
                    availableWidth: width,
                    availableHeight: height,
                    direction: o.direction,
                    isTouchBehaviorEnable: this._isTouchBehaviorEnabled()
                });

                this.piechartRender.render(!o.radius);
            };

            wijpiechart.prototype._getTooltipText = function (fmt, target) {
                var tar = $(target.node), dataObj, obj;
                if (tar.data("owner")) {
                    tar = tar.data("owner");
                }
                dataObj = tar.data("wijchartDataObj");
                obj = {
                    data: dataObj,
                    value: dataObj.value,
                    label: dataObj.label,
                    total: dataObj.total,
                    target: target,
                    y: dataObj.value,
                    fmt: fmt
                };
                return $.proxy(fmt, obj)();
            };
            return wijpiechart;
        })(chart.wijchartcore);
        chart.wijpiechart = wijpiechart;

        /*
        * Piechart segments orientation
        */
        var pieChartDirection = (function () {
            function pieChartDirection() {
            }
            pieChartDirection.clockwise = "clockwise";
            pieChartDirection.counterClockwise = "counterClockwise";
            return pieChartDirection;
        })();

        var wijpiechart_css = (function (_super) {
            __extends(wijpiechart_css, _super);
            function wijpiechart_css() {
                _super.apply(this, arguments);
                this.pieChart = "wijmo-wijpiechart";
                this.pieLabel = "wijpiechart-label";
                this.pieElement = "wijpiechart";
                this.pieTracker = "pietracker";
            }
            return wijpiechart_css;
        })(chart.wijchartcore_css);
        chart.wijpiechart_css = wijpiechart_css;

        var wijpiechart_options = (function (_super) {
            __extends(wijpiechart_options, _super);
            function wijpiechart_options() {
                _super.apply(this, arguments);
                /**
                * Selector option for auto self initialization. This option is internal.
                * @ignore
                */
                this.initSelector = ":jqmData(role='wijpiechart')";
                /**
                * All CSS classes used in widgets.
                * @ignore
                */
                this.wijCSS = new wijmo.chart.wijpiechart_css();
                /** Sets the number of degrees of angle from which to begin painting wedges in the pie.
                * To see an example of this property in action, check out the following link,
                * http://jsbin.com/ewofiv/1
                */
                this.startAngle = 0;
                /** A value that indicates the radius used for a pie chart.
                * @type {number}
                * @remarks If the value is null, then the radius will be calculated
                * by the width/height value of the pie chart.
                */
                this.radius = null;
                /** A value that indicates the inner radius used for doughnut charts.*/
                this.innerRadius = 0;
                /** A value that indicates the chart label elements of chart.*/
                this.labels = {
                    /** A value that indicates the style of the chart labels.*/
                    style: {},
                    /** A value that indicates the format string of the chart labels.*/
                    formatString: "",
                    /** A value that indicates the formatter of the chart labels.
                    * @type {function}
                    */
                    formatter: null,
                    /** A value that indicates the style of the chart labels' connector.*/
                    connectorStyle: {},
                    /** A value that indicates the style of the chart labels.
                    * @remarks Options are 'inside', 'outside'.
                    */
                    position: "inside",
                    /** A value that indicates the offset of the chart labels.*/
                    offset: 10
                };
                /** The animation option  defines the animation effect and controls other aspects of the widget's animation,
                * such as duration and easing.
                */
                this.animation = {
                    /** A value that determines whether to show animation.*/
                    enabled: true,
                    /** A value that indicates the duration for the animation. */
                    duration: 400,
                    /** Sets the type of animation easing effect that users experience when the wijpiechart series
                    * is reloaded after they have changed the data for the seriesList option.
                    * @remarks  Values available for the animation easing effect include the following:
                    * easeInCubic – Cubic easing in. Begins at zero velocity and then accelerates.
                    * easeOutCubic – Cubic easing in and out. Begins at full velocity and then decelerates to zero.
                    * easeInOutCubic – Begins at zero velocity, accelerates until halfway, and then decelerates to zero velocity again.
                    * easeInBack – Begins slowly and then accelerates.
                    * easeOutBack – Begins quickly and then decelerates.
                    * easeOutElastic – Begins at full velocity and then decelerates to zero.
                    * easeOutBounce – Begins quickly and then decelerates. The number of bounces is related to the duration, longer durations produce more bounces.
                    */
                    easing: "easeInCubic",
                    /** A value that indicates the offset for an explode animation.*/
                    offset: 10
                };
                /** A value that indicates whether to show animation
                * and the duration for the animation when reload data.
                */
                this.seriesTransition = {
                    /** A value that determines whether to show animation when reload.*/
                    enabled: true,
                    /** A value that indicates the duration for the series transition.*/
                    duration: 1000,
                    /** A value that indicates the easing for the series transition. */
                    easing: "bounce"
                };
                /** An array collection that contains the data to be charted.
                * @remarks The following is the sample data for seriesList option,
                * [{
                * 	label: "Q1",
                * 	legendEntry: true,
                * 	data: 12,
                * 	 offset: 0
                * }, {
                * 	label: "Q2",
                * 	legendEntry: true,
                * 	data: 21,
                * 	offset: 0
                * }, {
                * 	label: "Q3",
                * 	legendEntry: true,
                * 	data: 9,
                * 	offset: 0
                * }, {
                * 	 label: "Q4",
                * 	legendEntry: true,
                * 	data: 29,
                * 	offset: 10
                * }]
                */
                this.seriesList = [];
                /** A value that indicates whether the piechart can be rotated and tooltip is always shown
                * on touchable devices.
                */
                this.enableTouchBehavior = true;
                /** Fires when the user clicks a mouse button.
                * @event
                * @param {Object} e The jQuery.Event object.
                * @param {IWijPieChartEventArgs} args The data with this event.
                */
                this.mouseDown = null;
                /** Fires when the user releases a mouse button
                * while the pointer is over the chart element.
                * @event
                * @param {Object} e The jQuery.Event object.
                * @param {IWijPieChartEventArgs} args The data with this event.
                */
                this.mouseUp = null;
                /** Fires when the user first places the pointer over the chart element.
                * @event
                * @param {Object} e The jQuery.Event object.
                * @param {IWijPieChartEventArgs} args The data with this event.
                */
                this.mouseOver = null;
                /** Fires when the user moves the pointer off of the chart element.
                * @event
                * @param {Object} e The jQuery.Event object.
                * @param {IWijPieChartEventArgs} args The data with this event.
                */
                this.mouseOut = null;
                /** Fires when the user moves the mouse pointer
                * while it is over a chart element.
                * @event
                * @param {Object} e The jQuery.Event object.
                * @param {IWijPieChartEventArgs} args The data with this event.
                */
                this.mouseMove = null;
                /** Fires when the user clicks the chart element.
                * @event
                * @param {Object} e The jQuery.Event object.
                * @param {IWijPieChartEventArgs} args The data with this event.
                */
                this.click = null;
                /** Sets the direction in which pie segmets will be drawn - clocwise or counterClockwise.
                * @type {pieChartDirection}
                * @remarks default value is "counterClockwise"
                */
                this.direction = pieChartDirection.counterClockwise;
            }
            return wijpiechart_options;
        })(chart.wijchartcore_options);
        ;

        wijpiechart.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijpiechart_options());

        $.wijmo.registerWidget("wijpiechart", wijpiechart.prototype);

        ;

        //render pie chart.
        /** @ignore*/
        var PieChartRender = (function () {
            function PieChartRender(element, options) {
                this.options = options;
                this.element = element;
            }
            PieChartRender.prototype.render = function (radiusNotSet) {
                var ele = this.element, o = this.options, paintShadow = function (element, offset, stroke) {
                    if (o.shadow) {
                        chart.ChartUtil.paintShadow(element, offset, stroke);
                    }
                }, getDiffAttrs = chart.ChartUtil.getDiffAttrs, canvas = o.canvas, getPositionByAngle = $.wijraphael.getPositionByAngle, seriesList = o.seriesList, seriesStyles = o.seriesStyles, seriesHoverStyles = o.seriesHoverStyles, stylesLength = seriesStyles.length, textStyle = o.textStyle, labelsOpts = o.labels || {
                    style: {},
                    formatString: "",
                    formatter: null,
                    connectorStyle: {},
                    position: "inside",
                    offset: 10
                }, chartLabelStyle = $.extend(true, {}, textStyle, o.chartLabelStyle, labelsOpts.style), chartLabelFormatString = labelsOpts.formatString || o.chartLabelFormatString, chartLabelFormatter = labelsOpts.formatter || o.chartLabelFormatter, culture = o.culture, bounds = o.bounds, startX = bounds.startX, startY = bounds.startY, radius = o.radius, showChartLabels = o.showChartLabels, animation = o.animation, seriesTransition = o.seriesTransition, innerRadius = o.innerRadius, fields = ele.data("fields") || {}, chartElements = fields.chartElements || {}, aniSectorAttrs = fields.aniSectorAttrs, aniLabelAttrs = fields.aniLabelAttrs, total = 0, angle = o.startAngle || 0, wijCSS = o.wijCSS, pieID, path, attr, sectorAttrs = [], labelAttrs = [], sectors = [], labels = [], tooltipTars = [], seriesEles = [], trackers = canvas.set(), widget = this.options.widget, calAngle = angle, availableWidth = o.availableWidth, availableHeight = o.availableHeight, oldRadius = o.radius, direction = o.direction;

                canvas.customAttributes.segment = function (x, y, a1, a2, outerR, innerR) {
                    var path = null, offset = 0.01;

                    if (a2 - a1 > TwoPI - offset) {
                        a2 -= offset;
                    } else if (a2 - a1 < offset) {
                        a2 += offset;
                    }
                    if (innerR) {
                        path = chart.ChartUtil.donut(x, y, outerR, innerR, a1, a2);
                    } else {
                        path = chart.ChartUtil.sector(x, y, outerR, a1, a2);
                    }
                    return {
                        "path": path
                    };
                };

                $.each(seriesList, function (idx, series) {
                    if (series && typeof (series.data) === "number") {
                        total += Math.abs(series.data);
                    }
                });

                if (radiusNotSet && showChartLabels && (labelsOpts.position === "outside")) {
                    $.each(seriesList, function (idx, series) {
                        var actualSize, textStyle, chartLabel, formatter, label, labelBounds, tempRadius = radius, seriesWidth = 0, seriesHeight = 0, anglePlus = TwoPI * Math.abs(series.data) / total, seriesAngle = anglePlus / 2 + calAngle, processedChartLabel;
                        series = $.extend(true, { offset: 0 }, series);
                        textStyle = $.extend(true, {}, textStyle, chartLabelStyle);
                        if (series.textStyle) {
                            textStyle = $.extend(true, textStyle, series.textStyle);
                        }
                        chartLabel = series.label;
                        processedChartLabel = chart.ChartUtil.getChartLabel(chartLabelFormatString, chartLabel, culture, {
                            index: idx,
                            value: series.data,
                            y: series.data,
                            total: total,
                            chartLabelFormatter: chartLabelFormatter
                        });
                        chartLabel = processedChartLabel.text;
                        if (aniLabelAttrs && seriesTransition.enabled) {
                            if (idx < aniLabelAttrs.length) {
                                attr = aniLabelAttrs[idx];
                                attr.text = chartLabel;
                                label = widget._text.call(widget, 0, 0, "");
                                label.wijAttr(attr);
                            } else {
                                label = widget._text.call(widget, 0, 0, chartLabel);
                                label.wijAttr(textStyle);
                            }
                        } else {
                            label = widget._text.call(widget, 0, 0, chartLabel);
                            label.wijAttr(textStyle);
                        }
                        labelBounds = label.wijGetBBox();
                        actualSize = getPositionByAngle(0, 0, series.offset + labelsOpts.offset + radius, seriesAngle);
                        seriesWidth = labelBounds.width + Math.abs(actualSize.x);
                        seriesHeight = labelBounds.height / 2 + Math.abs(actualSize.y);

                        if (seriesWidth > availableWidth / 2) {
                            radius = tempRadius - (seriesWidth - availableWidth / 2) / Math.abs(Math.cos(Raphael.rad(seriesAngle)));
                        }

                        if (seriesHeight > availableHeight / 2) {
                            radius = Math.min(radius, tempRadius - (availableHeight / 2 - seriesHeight) / Math.abs(Math.sin(Raphael.rad(seriesAngle))));
                        }
                        calAngle += anglePlus;
                        label.remove();
                        if (radius < innerRadius) {
                            radius = innerRadius;
                            return false;
                        }
                    });

                    if (radius != oldRadius) {
                        o.bounds.startX = o.bounds.startX + oldRadius - radius;
                        o.bounds.endX = o.bounds.startX + 2 * radius;
                        o.bounds.startY = o.bounds.startY + oldRadius - radius;
                        o.bounds.endY = o.bounds.startY + 2 * radius;
                        startX = bounds.startX;
                        startY = bounds.startY;
                    }
                }

                $.each(seriesList, function (idx, series) {
                    var seriesStyle = $.extend({
                        opacity: 1,
                        stroke: "gray",
                        "stroke-width": 1
                    }, seriesStyles[idx % stylesLength]), anglePlus = TwoPI * Math.abs(series.data) / total, cx = startX + radius, cy = startY + radius, center, sector, label, pos, textStyle, borderPos, tracker, chartLabel, formatter, labelPosition = labelsOpts.position, labelConnectorStyle = labelsOpts.connectorStyle, labelOffset = labelsOpts.offset, calculatedAngle, labelBounds, labelConnector, animate = false, processedChartLabel;

                    pieID = series.pieID;

                    var angleEnd, angleMediana;
                    var isClockwise = direction == pieChartDirection.clockwise;
                    if (isClockwise) {
                        angleEnd = angle - anglePlus, angleMediana = angle - anglePlus / 2;
                    } else {
                        angleEnd = angle + anglePlus, angleMediana = angle + anglePlus / 2;
                    }

                    series = $.extend(true, { offset: 0 }, series);
                    if (series.offset) {
                        center = getPositionByAngle(cx, cy, series.offset, angleMediana);
                        cx = center.x;
                        cy = center.y;
                    }

                    path = [cx, cy, angle, angleEnd, radius, innerRadius];

                    if (aniSectorAttrs && seriesTransition.enabled) {
                        seriesStyle["segment"] = path;
                        if (idx < aniSectorAttrs.length) {
                            attr = aniSectorAttrs[idx];
                        } else {
                            attr = $.extend(true, {}, seriesStyle);
                            attr.segment = [cx, cy, 0, TwoPI, radius, innerRadius];
                        }
                        sector = canvas.path().attr(attr);
                        seriesStyle = getDiffAttrs(attr, seriesStyle);
                        if (!sector.removed) {
                            sector.wijAnimate(seriesStyle, seriesTransition.duration, seriesTransition.easing, function () {
                                paintShadow(sector, 1, "#cccccc");
                                if (tracker && !tracker.removed && !sector.removed) {
                                    tracker.attr({ "path": sector.attr("path") });
                                }
                                delete seriesStyle["segment"];
                            });
                        }
                    } else {
                        sector = canvas.path().attr({ segment: path });
                        paintShadow(sector, 1, "#ccccc");
                        sector.wijAttr(seriesStyle);
                    }

                    sector.angles = { start: angle, end: angleEnd };
                    sector.index = idx;
                    sector.getOffset = function (offset) {
                        var pos = getPositionByAngle(cx, cy, offset, (sector.angles.start + sector.angles.end) / 2);
                        return { x: pos.x - cx, y: pos.y - cy };
                    };

                    sector.center = { x: cx, y: cy };
                    sector.radius = radius;
                    if (innerRadius) {
                        sector.innerRadius = innerRadius;
                    }
                    tracker = sector.clone();

                    // in vml, if the tracker has a stroke, the boder is black.
                    if (Raphael.vml) {
                        tracker.attr({
                            opacity: 0.01,
                            fill: "white",
                            "stroke-width": 0,
                            "fill-opacity": 0.01
                        });
                    } else {
                        tracker.attr({
                            opacity: 0.01,
                            fill: "white",
                            "fill-opacity": 0.01
                        });
                    }
                    $.wijraphael.addClass($(tracker.node), Raphael.format("{0} {1} {2} wijchart-tracker" + idx, wijCSS.canvasObject, wijCSS.pieElement, wijCSS.pieTracker));
                    $(tracker.node).data("owner", $(sector.node));
                    sector.tracker = tracker;
                    trackers.push(tracker);

                    // add class "wijmo-wijpiechart-series-n" to fix bug 18590
                    $.wijraphael.addClass($(sector.node), Raphael.format("{0} {1} wijmo-wijpiechart-series-" + idx, wijCSS.canvasObject, wijCSS.pieElement));

                    //addClass($(sector.node), "wijchart-canvas-object wijpiechart");
                    //end comments
                    $(sector.node).data("wijchartDataObj", series);

                    if (showChartLabels) {
                        if (labelPosition === "outside") {
                            borderPos = getPositionByAngle(cx, cy, radius, angleMediana);
                            pos = getPositionByAngle(cx, cy, radius + labelOffset, angleMediana);
                        } else {
                            pos = getPositionByAngle(cx, cy, series.offset + radius * 2 / 3, angleMediana);
                        }
                        textStyle = $.extend(true, {}, textStyle, chartLabelStyle);
                        if (series.textStyle) {
                            textStyle = $.extend(true, textStyle, series.textStyle);
                        }

                        chartLabel = series.label;
                        processedChartLabel = chart.ChartUtil.getChartLabel(chartLabelFormatString, chartLabel, culture, {
                            index: idx,
                            value: series.data,
                            y: series.data,
                            total: total,
                            chartLabelFormatter: chartLabelFormatter
                        });
                        chartLabel = processedChartLabel.text;
                        if (aniLabelAttrs && seriesTransition.enabled) {
                            if (idx < aniLabelAttrs.length) {
                                animate = true;
                                attr = aniLabelAttrs[idx];
                                attr.text = chartLabel;
                                label = widget._text.call(widget, 0, 0, "");
                                label.wijAttr(attr);
                                textStyle = getDiffAttrs(attr, textStyle);
                                textStyle.x = pos.x;
                                textStyle.y = pos.y;
                                label.wijAnimate(textStyle, seriesTransition.duration, seriesTransition.easing, function () {
                                    if (labelConnector) {
                                        labelConnector.show();
                                    }
                                });
                            } else {
                                label = widget._text.call(widget, pos.x, pos.y, chartLabel);
                                label.wijAttr(textStyle);
                            }
                        } else {
                            label = widget._text.call(widget, pos.x, pos.y, chartLabel);
                            label.wijAttr(textStyle);
                        }
                        if (labelPosition === "outside") {
                            calculatedAngle = (angleMediana) % TwoPI;
                            labelBounds = label.wijGetBBox();
                            if (calculatedAngle >= 90 && calculatedAngle <= 270) {
                                label.transform(Raphael.format("T{0},{1}", -labelBounds.width / 2, 0));
                            } else {
                                label.transform(Raphael.format("T{0},{1}", labelBounds.width / 2, 0));
                            }

                            //connector
                            labelConnector = canvas.path(Raphael.format("M{0} {1}L{2} {3}", borderPos.x, borderPos.y, pos.x, pos.y)).attr(labelConnectorStyle);
                            if (animate) {
                                labelConnector.hide();
                            }
                            label.connector = labelConnector;
                        }
                        $.wijraphael.addClass($(label.node), Raphael.format("{0} {1} {2}", wijCSS.canvasObject, wijCSS.pieElement, wijCSS.pieLabel));
                        $(label.node).data("wijchartDataObj", series);
                        tooltipTars.push(label);
                        labels.push(label);
                        labelAttrs[idx] = label.attr();
                    }

                    seriesEles.push({ label: labels[idx], sector: sector });

                    if (series.visible === false) {
                        sector.hide();
                        if (labels[idx]) {
                            labels[idx].hide();
                        }
                        if (labelConnector) {
                            labelConnector.hide();
                        }
                        if (sector.shadow) {
                            sector.shadow.hide();
                        }
                        tracker.hide();
                    }

                    sectorAttrs[idx] = sector.attr();
                    sectors.push(sector);
                    tooltipTars.push(sector);
                    series.style = seriesStyle;
                    series.hoverStyle = seriesHoverStyles[idx];
                    series.index = idx;
                    series.value = series.data;
                    series.y = series.data;
                    series.total = total;
                    series.type = "pie";

                    //angle += anglePlus;
                    angle = angleEnd;
                });

                //ensuring labels are rendered on top of pie slices.
                if (labels && labels.length) {
                    $.each(labels, function (idx, label) {
                        label.toFront();
                    });
                }

                //end comments.
                chartElements.sectors = sectors;
                if (pieID) {
                    chartElements["sectors" + pieID] = sectors;
                    chartElements["labels" + pieID] = labels;
                }
                chartElements.labels = labels;

                if (!fields.chartElements) {
                    fields.chartElements = {};
                }

                trackers.toFront();

                $.extend(true, fields.chartElements, chartElements);
                fields.aniSectorAttrs = sectorAttrs;
                fields.aniLabelAttrs = labelAttrs;
                fields.seriesEles = seriesEles;
                fields.trackers = trackers;
                ele.data("fields", fields);

                this.unbindLiveEvents();
                this.bindLiveEvents();
            };

            PieChartRender.prototype.bindLiveEvents = function () {
                var o = this.options, touchEnabled = o.widget._isTouchEnabled(), enableTouchBehavior = o.isTouchBehaviorEnable, ele = this.element, tooltip = o.tooltip, offset = { x: 0, y: 0 }, touchEventPre = "", touchBehaviorEventPre = "", isFunction = $.isFunction, disabled = o.disabled, animation = o.animation;

                if (touchEnabled) {
                    touchEventPre = "wij";
                }

                if (enableTouchBehavior) {
                    touchBehaviorEventPre = "wij";
                }

                if (tooltip) {
                    tooltip.setTargets(this.tooltipTars);
                }

                ele.on(touchEventPre + "mousedown." + o.widgetName, "." + o.wijCSS.pieElement, function (e) {
                    if (disabled) {
                        return;
                    }
                    var mouseDown = o.mouseDown, target = $(e.target), dataObj;
                    if (target.data("owner")) {
                        target = target.data("owner");
                    }
                    dataObj = target.data("wijchartDataObj");
                    if (!dataObj) {
                        return;
                    }

                    if (isFunction(mouseDown)) {
                        mouseDown.call(ele, e, dataObj);
                    }
                }).on(touchEventPre + "mouseup." + o.widgetName, "." + o.wijCSS.pieElement, function (e) {
                    if (disabled) {
                        return;
                    }

                    var mouseUp = o.mouseUp, target = $(e.target), dataObj;
                    if (target.data("owner")) {
                        target = target.data("owner");
                    }
                    dataObj = target.data("wijchartDataObj");
                    if (!dataObj) {
                        return;
                    }
                    if (isFunction(mouseUp)) {
                        mouseUp.call(ele, e, dataObj);
                    }
                }).on(touchBehaviorEventPre + "mouseover." + o.widgetName, "." + o.wijCSS.pieElement, function (e) {
                    if (disabled) {
                        return;
                    }

                    var mouseOver = o.mouseOver, target = $(e.target), animated = animation && animation.enabled, dataObj, id, index, sector, showAnimationTimer, hideAnimationTimer, explodeAnimationShowing;
                    if (target.data("owner")) {
                        target = target.data("owner");
                    }
                    dataObj = target.data("wijchartDataObj");
                    if (!dataObj) {
                        return;
                    }
                    id = dataObj.pieID || "";
                    index = dataObj.index;
                    sector = ele.data("fields").chartElements["sectors" + id][index];
                    showAnimationTimer = sector.showAnimationTimer;
                    hideAnimationTimer = sector.hideAnimationTimer;
                    explodeAnimationShowing = sector.explodeAnimationShowing;

                    if (isFunction(mouseOver)) {
                        mouseOver.call(ele, e, dataObj);
                    }

                    if (enableTouchBehavior) {
                        return;
                    }
                    if (sector.removed) {
                        return;
                    }
                    sector.wijAttr(dataObj.hoverStyle);

                    if (animated) {
                        if (hideAnimationTimer) {
                            window.clearTimeout(hideAnimationTimer);
                            hideAnimationTimer = null;
                            sector.hideAnimationTimer = hideAnimationTimer;
                        }

                        if (showAnimationTimer) {
                            window.clearTimeout(showAnimationTimer);
                            showAnimationTimer = null;
                            sector.showAnimationTimer = null;
                        }

                        if (explodeAnimationShowing) {
                            return;
                        }

                        showAnimationTimer = window.setTimeout(function () {
                            var duration = animation.duration, easing = animation.easing;

                            if (sector.removed) {
                                return;
                            }
                            offset = sector.getOffset(animation.offset || 10);
                            sector.offset = offset;
                            if (sector.shadow && !sector.shadow.removed) {
                                sector.shadow.hide();
                            }

                            sector.wijAnimate({
                                transform: Raphael.format("t{0},{1}", offset.x, offset.y)
                            }, duration, easing);
                            if (sector.tracker && !sector.tracker.removed) {
                                sector.tracker.wijAnimate({
                                    transform: Raphael.format("t{0},{1}", offset.x, offset.y)
                                }, duration, easing);
                            }

                            explodeAnimationShowing = true;
                            sector.explodeAnimationShowing = explodeAnimationShowing;
                        }, 150);
                        sector.showAnimationTimer = showAnimationTimer;
                    }
                }).on(touchBehaviorEventPre + "mouseout." + o.widgetName, "." + o.wijCSS.pieElement, function (e) {
                    if (disabled) {
                        return;
                    }
                    var mouseOut = o.mouseOut, target = $(e.target), animated = animation && animation.enabled, dataObj, id, index, sector, showAnimationTimer, hideAnimationTimer, explodeAnimationShowing;
                    if (target.data("owner")) {
                        target = target.data("owner");
                    }
                    dataObj = target.data("wijchartDataObj");
                    if (!dataObj) {
                        return;
                    }

                    id = dataObj.pieID || "";
                    index = dataObj.index;
                    sector = ele.data("fields").chartElements["sectors" + id][index];
                    showAnimationTimer = sector.showAnimationTimer;
                    hideAnimationTimer = sector.hideAnimationTimer;
                    explodeAnimationShowing = sector.explodeAnimationShowing;

                    if (isFunction(mouseOut)) {
                        mouseOut.call(ele, e, dataObj);
                    }
                    if (enableTouchBehavior) {
                        return;
                    }
                    if (sector.removed) {
                        return;
                    }

                    if (dataObj.style.segment) {
                        delete dataObj.style.segment;
                    }

                    sector.wijAttr(dataObj.style);

                    if (animated) {
                        if (hideAnimationTimer) {
                            window.clearTimeout(hideAnimationTimer);
                            hideAnimationTimer = null;
                            sector.hideAnimationTimer = hideAnimationTimer;
                        }

                        if (showAnimationTimer) {
                            window.clearTimeout(showAnimationTimer);
                            showAnimationTimer = null;
                            sector.showAnimationTimer = showAnimationTimer;
                        }

                        if (!explodeAnimationShowing) {
                            return;
                        }

                        hideAnimationTimer = window.setTimeout(function () {
                            var duration = animation.duration, easing = animation.easing;

                            offset = sector.offset;
                            if (sector.shadow && !sector.shadow.removed) {
                                sector.shadow.show();
                            }
                            if (!sector.removed) {
                                sector.wijAnimate({
                                    transform: "t0,0"
                                }, duration, easing);
                            }
                            if (sector.tracker && !sector.tracker.removed) {
                                sector.tracker.wijAnimate({
                                    transform: "t0,0"
                                }, duration, easing);
                            }
                            if (sector.shadow && !sector.shadow.removed) {
                                sector.shadow.wijAnimate({
                                    transform: "t0,0"
                                }, duration, easing);
                            }

                            offset = { x: 0, y: 0 };
                            explodeAnimationShowing = false;
                            sector.explodeAnimationShowing = explodeAnimationShowing;
                        }, 150);
                        sector.hideAnimationTimer = hideAnimationTimer;
                    }
                }).on(touchEventPre + "mousemove." + o.widgetName, "." + o.wijCSS.pieElement, function (e) {
                    if (disabled) {
                        return;
                    }
                    var mouseMove = o.mouseMove, target = $(e.target), dataObj;
                    if (target.data("owner")) {
                        target = target.data("owner");
                    }
                    dataObj = target.data("wijchartDataObj");
                    if (!dataObj) {
                        return;
                    }

                    if (isFunction(mouseMove)) {
                        mouseMove.call(ele, e, dataObj);
                    }
                }).on(touchEventPre + "click." + o.widgetName, "." + o.wijCSS.pieElement, function (e) {
                    if (disabled) {
                        return;
                    }

                    // The sector rotates twice on ios decive.
                    // There is 300ms click delay on iOS devices, when rotate the sector,
                    // the wijclick event will be fired twice, one is caused by touch on tracker(tracker is hiding after touch end),
                    // then another wijclick is caused by click on sector.
                    // So when click on sector, return it.
                    if (window.navigator.userAgent.match(/iPhone|iPad|iPod/i) && enableTouchBehavior && !($.wijraphael.hasClass(e.target, o.wijCSS.pieTracker))) {
                        return;
                    }

                    var click = o.click, target = $(e.target), dataObj;
                    if (target.data("owner")) {
                        target = target.data("owner");
                    }
                    dataObj = target.data("wijchartDataObj");
                    if (!dataObj) {
                        return;
                    }
                    if (isFunction(click)) {
                        click.call(ele, e, dataObj);
                    }
                });
            };

            PieChartRender.prototype.unbindLiveEvents = function () {
                var ele = this.element, o = this.options;
                ele.off("." + o.widgetName, "." + o.wijCSS.pieElement);
            };
            return PieChartRender;
        })();
        chart.PieChartRender = PieChartRender;
    })(wijmo.chart || (wijmo.chart = {}));
    var chart = wijmo.chart;
})(wijmo || (wijmo = {}));

;
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /// <reference path="../wijchart/jquery.wijmo.wijchartcore.ts"/>
    (function (chart) {
        var widgetName = "wijcandlestickchart", strOHLC = "ohlc", strCandlestick = "candlestick", strHL = "hl", strStrokeWidth = "stroke-width";

        /** @ignore */
        var datetimeUtil = (function () {
            function datetimeUtil(datetimeArr) {
                this.init(datetimeArr);
            }
            datetimeUtil.prototype.init = function (datetimeArr) {
                var times = [], dic = {}, length, i;

                $.each(datetimeArr, function (i, n) {
                    var val = $.toOADate(n);
                    if ($.inArray(val, times) === -1) {
                        times.push(val);
                    }
                });

                this.count = length = times.length;
                this.times = times = times.sort();
                this.timeDic = dic;

                // when the times contains less than 2 items, set default value.
                if (length < 2) {
                    this.max = times[0] || 0;
                    this.min = times[0] || 0;
                    this.unit = 24 * 60 * 60 * 1000;
                    if (length === 1) {
                        dic[times[0]] = 0;
                    }
                    return;
                }

                for (i = 0; i < length; i++) {
                    dic[times[i]] = i;
                }
                this._calculateUnit();
                this.max = times[this.count - 1];
                this.min = times[0];
            };

            datetimeUtil.prototype._calculateUnit = function () {
                var unit = Number.MAX_VALUE, i = 1;
                for (; i < this.count; i++) {
                    unit = Math.min(unit, this.times[i] - this.times[i - 1]);
                }
                this.unit = unit;
            };

            datetimeUtil.prototype.getOATime = function (index) {
                var count = this.count, times = this.times, num;
                if (index < 0) {
                    return this.min + index * this.unit;
                } else if (index > count - 1) {
                    return this.max + (index - count + 1) * this.unit;
                } else {
                    num = parseInt(index);
                    return times[num] + (index - num) * this.unit;
                }
            };

            datetimeUtil.prototype.getTime = function (index) {
                return $.fromOADate(this.getOATime(index));
            };

            datetimeUtil.prototype.getTimeIndex = function (datetime) {
                var oaDate = $.toOADate(datetime), index;

                // if datetime is larger than the max date of the series's x data. use max and unit to calculate the index.
                if (oaDate > this.max) {
                    return this.count - 1 + (oaDate - this.max) / this.unit;
                    // if the datetime is smaller than the min date of the series's  use min and unit to calculate the index
                } else if (oaDate < this.min) {
                    return (oaDate - this.min) / this.unit;
                } else {
                    // if the datetime is in series's x date, just get the index in the series's x data.
                    if (this.timeDic && this.timeDic[oaDate] != null) {
                        return this.timeDic[oaDate];
                    } else {
                        // if the datetime not in series's x data, use the closest date and unit to calculate the index.
                        $.each(this.times, function (i, time) {
                            if (time > oaDate) {
                                index = i - 1;
                                return false;
                            }
                        });
                        return index + (oaDate - this.times[index]) / this.unit;
                    }
                }
            };

            datetimeUtil.prototype.getCount = function () {
                return this.times.length;
            };

            datetimeUtil.prototype.dispose = function () {
                this.times = null;
                this.timeDic = null;
            };
            return datetimeUtil;
        })();
        chart.datetimeUtil = datetimeUtil;

        /** @widget */
        var wijcandlestickchart = (function (_super) {
            __extends(wijcandlestickchart, _super);
            function wijcandlestickchart() {
                _super.apply(this, arguments);
            }
            wijcandlestickchart.prototype._paintChartArea = function () {
                var o = this.options;

                if (this._isSeriesListDataEmpty()) {
                    return;
                }

                // Add high and low data to data.y for calculate the max and min of y axis.
                $.each(o.seriesList, function (i, series) {
                    var data = series.data;
                    if (!series.isTrendline) {
                        data.y = [].concat(data.high).concat(data.low);
                    }
                });
                _super.prototype._paintChartArea.call(this);

                // Delete the added data.y;
                // And recover the data.x
                $.each(o.seriesList, function (i, series) {
                    if (!series.isTrendline) {
                        delete series.data.y;
                    }
                    if (series.data.originalXValue) {
                        series.data.x = series.data.originalXValue;
                        delete series.data.originalXValue;
                    }
                });
            };

            wijcandlestickchart.prototype._getXAxisInfoValueLabels = function (xAxisInfo, xAxisOptions) {
                var self = this, annoFormatString;

                if (!xAxisOptions.annoFormatString || xAxisOptions.annoFormatString.length === 0) {
                    annoFormatString = chart.ChartDataUtil.getTimeDefaultFormat(this.timeUtil.max, this.timeUtil.min);
                } else {
                    annoFormatString = xAxisOptions.annoFormatString;
                }
                self.valueLabelsFromXData = false;
                self.xAxisLabelInfoList = [];
                if (xAxisOptions.annoMethod !== "valueLabels" || (!xAxisOptions.valueLabels || xAxisOptions.valueLabels.length === 0)) {
                    this.valueLabelsFromXData = true;
                    if (this.timeUtil) {
                        $.each(this.timeUtil.times, function (idx, time) {
                            var value = {
                                value: idx,
                                text: Globalize.format(self._getXTickText(idx), annoFormatString, self._getCulture())
                            };
                            self.xAxisLabelInfoList.push(value);
                        });
                    }
                } else {
                    $.each(xAxisOptions.valueLabels, function (idx, vL) {
                        var value, xAxisLabelInfo;
                        if (typeof vL === "string") {
                            xAxisLabelInfo = { text: vL, value: idx };
                        } else if (typeof vL === "object") {
                            xAxisLabelInfo = { text: vL.text };
                            value = vL.value;
                            if (value !== undefined && value !== null && self._isDate(value)) {
                                value = self.timeUtil.getTimeIndex(value);
                            } else {
                                value = idx;
                            }
                            xAxisLabelInfo["value"] = value;
                            xAxisLabelInfo["gridLine"] = vL.gridLine;
                            xAxisLabelInfo["gridLineStyle"] = vL.gridLineStyle;
                        }
                        self.xAxisLabelInfoList.push(xAxisLabelInfo);
                    });
                }

                xAxisInfo.annoMethod = "valueLabels";
                if (self.xAxisLabelInfoList && self.xAxisLabelInfoList.length) {
                    xAxisInfo.valueLabels = self.xAxisLabelInfoList;
                }
            };

            wijcandlestickchart.prototype._checkSeriesDataEmpty = function (series) {
                var type = this.options.type, data = series.data, checkEmptyData = this._checkEmptyData;

                if (!data || checkEmptyData(data.x)) {
                    return true;
                }
                if (series.isTrendline) {
                    if (!series.isValid || !series.innerData) {
                        return true;
                    }
                    return checkEmptyData(data.y);
                }
                if (checkEmptyData(data.high) || checkEmptyData(data.low)) {
                    return true;
                }
                if (type === strOHLC || type === strCandlestick) {
                    if (checkEmptyData(data.open) || checkEmptyData(data.close)) {
                        return true;
                    }
                }
                return false;
            };

            wijcandlestickchart.prototype._getLegendStyle = function (seriesStyle) {
                var style = seriesStyle.highLow;
                if (style) {
                    style = $.extend({}, style);
                    delete style.width;
                    delete style.height;
                    if (!style.stroke) {
                        style.stroke = style.fill;
                    }
                    return style;
                }
                return seriesStyle;
            };

            wijcandlestickchart.prototype._showHideSeries = function (seriesEles, type) {
                var nodeTypes = ["highLow", "open", "close", "path", "high", "low", "openClose"];
                $.each(seriesEles, function (i, candlestickNode) {
                    $.each(nodeTypes, function (idx, nodeType) {
                        if (candlestickNode[nodeType]) {
                            candlestickNode[nodeType][type]();
                        }
                    });
                    if (candlestickNode.path && $(candlestickNode.path.node).data("wijchartDataObj")) {
                        $(candlestickNode.path.node).data("wijchartDataObj").visible = (type === "show");
                    }
                });
            };

            wijcandlestickchart.prototype._showSerieEles = function (seriesEles) {
                if (seriesEles.isTrendline) {
                    chart.TrendlineRender.showSerieEles(seriesEles);
                    return;
                }
                this._showHideSeries(seriesEles, "show");
            };

            wijcandlestickchart.prototype._hideSerieEles = function (seriesEles) {
                if (seriesEles.isTrendline) {
                    chart.TrendlineRender.hideSerieEles(seriesEles);
                    return;
                }
                this._showHideSeries(seriesEles, "hide");
            };

            wijcandlestickchart.prototype._paintPlotArea = function () {
                var o = this.options, render = new CandlestickChartRender(this.chartElement, {
                    annotations: o.annotations,
                    canvas: this.canvas,
                    bounds: this.canvasBounds,
                    tooltip: this.tooltip,
                    widgetName: this.widgetName,
                    axis: o.axis,
                    seriesList: o.seriesList,
                    seriesStyles: o.seriesStyles,
                    seriesHoverStyles: o.seriesHoverStyles,
                    seriesTransition: o.seriesTransition,
                    showChartLabels: o.showChartLabels,
                    textStyle: o.textStyle,
                    chartLabelStyle: o.chartLabelStyle,
                    chartLabelFormatString: o.chartLabelFormatString,
                    shadow: o.shadow,
                    disabled: this._isDisabled(),
                    animation: o.animation,
                    culture: this._getCulture(),
                    type: o.type,
                    wijCSS: o.wijCSS,
                    mouseDown: $.proxy(this._mouseDown, this),
                    mouseUp: $.proxy(this._mouseUp, this),
                    mouseOver: $.proxy(this._mouseOver, this),
                    mouseOut: $.proxy(this._mouseOut, this),
                    mouseMove: $.proxy(this._mouseMove, this),
                    click: $.proxy(this._click, this),
                    timeUtil: this.timeUtil,
                    candlestickFormatter: o.candlestickFormatter,
                    widget: this
                });
                render.render();
            };

            wijcandlestickchart.prototype._paintTooltip = function () {
                var fields = this.chartElement.data("fields"), trackers;
                _super.prototype._paintTooltip.call(this);

                // if the series's data is empty, the field will be null.
                if (this.tooltip && fields && fields.trackers) {
                    trackers = fields.trackers;
                    this.tooltip.setTargets(trackers);
                    this.tooltip.setOptions({ relatedElement: trackers[0] });
                }
            };

            wijcandlestickchart.prototype._getTooltipText = function (fmt, target) {
                var dataObj = $(target.node).data("wijchartDataObj"), obj = {
                    data: dataObj,
                    label: dataObj.label,
                    x: dataObj.x,
                    high: dataObj.high,
                    low: dataObj.low,
                    open: dataObj.open,
                    close: dataObj.close,
                    target: target,
                    fmt: fmt
                };
                return $.proxy(fmt, obj)();
            };

            wijcandlestickchart.prototype._setDefaultTooltipText = function (data) {
                var type = this.options.type, tooltipText;

                tooltipText = data.label + " - " + Globalize.format(data.x, "d") + '\n High:' + data.high + '\n Low:' + data.low;

                if (type !== strHL) {
                    tooltipText += '\n Open:' + data.open + '\n Close:' + data.close + '';
                }
                return tooltipText;
            };

            wijcandlestickchart.prototype._getStyles = function (type, seriesStyles, optionName, isCompositeChart) {
                function getStyle(type, currentStyle, defaultStyle, needDefaultFill, isCompositeChart) {
                    var resultStyle = {}, styleNames = [];

                    if (defaultStyle === null || defaultStyle === undefined) {
                        return;
                    }
                    if (type === strHL) {
                        styleNames = ["highLow"];
                    } else if (type === strOHLC) {
                        styleNames = ["open", "close", "highLow"];
                    } else {
                        styleNames = ["fallingClose", "risingClose", "unchangeClose", "highLow"];
                    }
                    $.each(styleNames, function (j, styleName) {
                        if (isCompositeChart) {
                            currentStyle[styleName] = $.extend(true, {}, currentStyle, currentStyle[styleName]);
                        }
                        resultStyle[styleName] = $.extend(true, {}, defaultStyle, currentStyle[styleName]);
                        if (needDefaultFill && styleName == "risingClose" && (!currentStyle[styleName] || !currentStyle[styleName].fill)) {
                            resultStyle[styleName].fill = null;
                        }
                        if (styleName === "fallingClose" && (!currentStyle[styleName] || !currentStyle[styleName][strStrokeWidth])) {
                            resultStyle[styleName][strStrokeWidth] = 0;
                        }
                        if (styleName === "open" || styleName === "close" || styleName === "highLow") {
                            if (!currentStyle[styleName] || !currentStyle[styleName].stroke) {
                                resultStyle[styleName].stroke = resultStyle[styleName].fill;
                            }
                        }
                    });
                    return resultStyle;
                }

                var needDefaultFill = (optionName === "seriesStyles"), defFills = chart.wijchartcore.prototype._getDefFill(), currentCount = seriesStyles.length, maxCount = 0, defaultStyles, realStyles = [], index = 0;

                maxCount = Math.max(chart.wijchartcore.prototype.options[optionName].length, needDefaultFill ? defFills.length : 0, currentCount);
                defaultStyles = $.extend(true, new Array(maxCount), chart.wijchartcore.prototype.options[optionName]);
                for (index = 0; index < maxCount; index++) {
                    if (index >= currentCount) {
                        seriesStyles[index] = {};
                    }
                    if (needDefaultFill && index < defFills.length) {
                        if (!defaultStyles[index]) {
                            defaultStyles[index] = {};
                        }
                        defaultStyles[index].fill = defFills[index];
                    }
                    realStyles.push(getStyle(type, seriesStyles[index], defaultStyles[index], needDefaultFill, isCompositeChart));
                }
                return realStyles;
            };

            wijcandlestickchart.prototype._handleChartStyles = function () {
                var o = this.options;
                o["seriesStyles"] = this._getStyles(o.type, o["seriesStyles"], "seriesStyles", false);
                o["seriesHoverStyles"] = this._getStyles(o.type, o["seriesHoverStyles"], "seriesHoverStyles", false);
            };

            wijcandlestickchart.prototype._create = function () {
                this._handleChartStyles();
                this.bindXData = false;
                _super.prototype._create.call(this);

                this.chartElement.addClass(this.options.wijCSS.wijCandlestickChart);
            };

            wijcandlestickchart.prototype._setOption = function (key, value) {
                if (key === "axis") {
                    this._handleMaxMinInAxis(value);
                } else if (key === "type") {
                    this.options.type = value;
                    this._handleChartStyles();
                    this.styles = {
                        style: this.options.seriesStyles.slice(),
                        hoverStyles: this.options.seriesHoverStyles.slice()
                    };
                }
                _super.prototype._setOption.call(this, key, value);
            };

            wijcandlestickchart.prototype._seriesListSeted = function () {
                //if (this.timeUtil) {
                //    this.timeUtil.dispose();
                //    this.timeUtil = null;
                //}
                //this._handleXData();
            };

            // if user set max and min for x axis, they should set OADate or datetime, here need to calculate it to index by datetimeUtil.
            // If it is set other values, here will calculate wrong dateUtil.
            wijcandlestickchart.prototype._handleMaxMinInAxis = function (axis) {
                var _this = this;
                var xAxis, oldAxis = this.options.axis, handleTime = function (val) {
                    if (_this._isDate(val)) {
                        return _this.timeUtil.getTimeIndex(val);
                    } else {
                        return _this.timeUtil.getTimeIndex($.fromOADate(val));
                    }
                };
                if (axis && axis.x) {
                    xAxis = axis.x;
                    $.each(["max", "min"], function (i, name) {
                        var newValue = xAxis[name];
                        if (newValue === undefined || newValue === null) {
                            return true;
                        }

                        if (!oldAxis || !oldAxis.x || oldAxis.x[name] !== newValue) {
                            xAxis[name] = handleTime(newValue);
                        }
                    });
                }
            };

            wijcandlestickchart.prototype._handleXData = function () {
                var _this = this;
                var o = this.options, seriesList = o.seriesList = $.arrayClone(o.seriesList), xValues = [], isContainsDateTime = false, containsXData = function (series) {
                    return series.data && series.data.x;
                }, restoreXValues = function (series) {
                    var xData = series.data.x;
                    $.each(xData, function (i, x) {
                        if (!_this._isDate(x)) {
                            xData[i] = _this.timeUtil.getTime(x);
                        }
                    });
                };

                if (this.timeUtil && !this.bindXData) {
                    return;
                }
                this.bindXData = false;

                //TODO check the x data is datetime, If it's not datetime, throw an exception.
                $.each(seriesList, function (i, series) {
                    if (containsXData(series) && $.isArray(series.data.x)) {
                        xValues = xValues.concat(series.data.x);
                    }
                });

                // when the timeUtil is init, and the series x data contains date value,
                // Here need to recalculate the dateUtil and new x value.
                if (this.timeUtil) {
                    $.each(xValues, function (i, n) {
                        if (_this._isDate(n)) {
                            isContainsDateTime = true;
                            return false;
                        }
                    });
                    if (isContainsDateTime) {
                        xValues = [];
                        $.each(seriesList, function (i, series) {
                            if (containsXData(series)) {
                                restoreXValues(series);
                                xValues = xValues.concat(series.data.x);
                            }
                        });
                        this.timeUtil.dispose();
                        this.timeUtil = null;
                    }
                }

                if (!this.timeUtil) {
                    this.timeUtil = new datetimeUtil(xValues);
                }

                $.each(seriesList, function (i, series) {
                    if (containsXData(series) && $.isArray(series.data.x)) {
                        // Backup the original x values, recover it after paint.
                        series.data.originalXValue = series.data.x;

                        series.data.x = $.map(series.data.x, function (n, j) {
                            return _this.timeUtil.getTimeIndex(n);
                        });
                    }
                });
            };

            wijcandlestickchart.prototype._bindData = function () {
                _super.prototype._bindData.call(this);
                //this._handleXData();
            };

            wijcandlestickchart.prototype._preHandleSeriesData = function () {
                if (this.timeUtil) {
                    this.timeUtil.dispose();
                    this.timeUtil = null;
                }
                this._handleXData();

                _super.prototype._preHandleSeriesData.call(this);
            };

            // handle data bind
            wijcandlestickchart.prototype._bindSeriesData = function (ds, series, sharedXList) {
                var _this = this;
                var data = series.data;
                _super.prototype._bindSeriesData.call(this, ds, series, sharedXList);
                if (data.x && $.isArray(data.x)) {
                    this.bindXData = true;
                }
                $.each(["high", "low", "open", "close"], function (i, name) {
                    var d = data[name];
                    if (d && d.bind) {
                        data[name] = _this._getBindData(ds, d.bind);
                    }
                });
            };

            /** Remove the functionality completely. This will return the element back to its pre-init state. */
            wijcandlestickchart.prototype.destroy = function () {
                var element = this.chartElement;
                element.removeClass(this.options.wijCSS.wijCandlestickChart);
                _super.prototype.destroy.call(this);
                if (this.timeUtil) {
                    this.timeUtil.dispose();
                }
                element.data("fields", null);
            };

            /**
            * This method returns the candlestick elements, which has a set of Raphaël objects  that represent candlestick elements for the
            * series data, from the specified index.
            * @param {number} index The zero-based index of the candlestick to return.
            * @returns {Object} candlestick object which contains Raphael elements.
            */
            wijcandlestickchart.prototype.getCandlestick = function (index) {
                var fields = this.chartElement.data("fields");
                if (fields && fields.chartElements && fields.chartElements.candlestickEles) {
                    return fields.chartElements.candlestickEles[index] || null;
                }
                return null;
            };

            wijcandlestickchart.prototype._clearChartElement = function () {
                var o = this.options, fields = this.chartElement.data("fields"), chartElements, candlestickEles;

                if (fields && fields.chartElements) {
                    chartElements = fields.chartElements;
                    candlestickEles = chartElements.candlestickEles;
                    $.each(candlestickEles, function (i, candlestickEle) {
                        $.each(candlestickEle, function (key, node) {
                            if (node && node[0]) {
                                node.wijRemove();
                            }
                            candlestickEle[key] = null;
                        });
                        candlestickEles[i] = null;
                    });
                    chartElements.candlestickEles = null;
                    if (chartElements.group) {
                        chartElements.group.wijRemove();
                    }
                    chartElements.group = null;
                    if (fields.trackers) {
                        fields.trackers.wijRemove();
                    }
                    fields.trackers = null;
                }

                _super.prototype._clearChartElement.call(this);
            };

            wijcandlestickchart.prototype._calculateParameters = function (axisInfo, options) {
                _super.prototype._calculateParameters.call(this, axisInfo, options);
                if (axisInfo.id === "x") {
                    var minor = options.unitMinor, autoMin = options.autoMin, autoMax = options.autoMax, adj = this._getCandlestickAdjustment(axisInfo, minor);

                    if (autoMin) {
                        axisInfo.min -= adj;
                    }

                    if (autoMax) {
                        axisInfo.max += adj;
                    }

                    this._calculateMajorMinor(options, axisInfo);
                }
            };

            wijcandlestickchart.prototype._calculateMajorMinor = function (axisOptions, axisInfo) {
                var self = this, unitMajor;
                if (axisInfo.id === "x") {
                    if (!axisOptions.annoFormatString || axisOptions.annoFormatString.length === 0) {
                        axisInfo.annoFormatString = chart.ChartDataUtil.getTimeDefaultFormat(this.timeUtil.getOATime(axisInfo.max), this.timeUtil.getOATime(axisInfo.min));
                    } else {
                        axisInfo.annoFormatString = axisOptions.annoFormatString;
                    }
                }
                _super.prototype._calculateMajorMinor.call(this, axisOptions, axisInfo);
                unitMajor = axisOptions.unitMajor ? axisOptions.unitMajor : 1;
                self._adjustXValueLabelsByMajorUnit(unitMajor, axisInfo);
            };

            wijcandlestickchart.prototype._adjustXValueLabelsByMajorUnit = function (unitMajor, xAxisInfo) {
                if (xAxisInfo.id === "x") {
                    if (this.valueLabelsFromXData) {
                        xAxisInfo.valueLabels = [];
                        $.each(this.xAxisLabelInfoList, function (idx, valueLabel) {
                            if (idx % unitMajor === 0) {
                                xAxisInfo.valueLabels.push(valueLabel);
                            }
                        });
                    }
                }
            };

            wijcandlestickchart.prototype._getCandlestickAdjustment = function (axisInfo, minor) {
                var length = 0, adj;

                $.each(this.options.seriesList, function (i, s) {
                    if (s.data && s.data.x && $.isArray(s.data.x)) {
                        length = Math.max(s.data.x.length, length);
                    }
                });
                adj = (axisInfo.max - axisInfo.min) / length;
                if (adj === 0) {
                    adj = minor;
                } else {
                    if (minor < adj && minor !== 0) {
                        adj = Math.floor(adj / minor) * minor;
                    }
                }
                return adj;
            };

            wijcandlestickchart.prototype._getXTickText = function (text) {
                if (this.timeUtil.getCount() === 0) {
                    return "";
                }
                return this.timeUtil.getTime(text);
            };

            wijcandlestickchart.prototype._adjustTickValuesForCandlestickChart = function (tickValues) {
                var _this = this;
                var isValueLabels = this.options.axis.x.annoMethod === "valueLabels", values = [];
                if (isValueLabels && tickValues && $.isArray(tickValues)) {
                    $.each(tickValues, function (i, value) {
                        values[i] = _this.timeUtil.getTimeIndex($.fromOADate(value));
                    });
                    return values;
                }
                return _super.prototype._adjustTickValuesForCandlestickChart.call(this, tickValues);
            };

            wijcandlestickchart.prototype._getTickTextForCalculateUnit = function (value, axisInfo, prec) {
                if (axisInfo.id === "x") {
                    return Globalize.format(this._getXTickText(value), axisInfo.annoFormatString, this._getCulture());
                }
                return _super.prototype._getTickTextForCalculateUnit.call(this, value, axisInfo, prec);
            };
            return wijcandlestickchart;
        })(chart.wijchartcore);
        chart.wijcandlestickchart = wijcandlestickchart;

        /** @ignore */
        var CandlestickChartRender = (function (_super) {
            __extends(CandlestickChartRender, _super);
            function CandlestickChartRender(element, options) {
                _super.call(this, element, options);
                var self = this;
                self.bounds = options.bounds, self.type = options.type;
                self.timeUtil = options.timeUtil;
                self.trackers = options.canvas.set();
                self.isHover = false;
                self.animationSet = options.canvas.set();
                self.fieldsAniPathAttr = [];
                self.paths = [];
                self.aniPathsAttr = [];
            }
            CandlestickChartRender.prototype._paintCandlestickElements = function (series, seriesStyle, seriesHoverStyle, sIdx) {
                var data = series.data, length = Math.min(data.x.length, data.high.length, data.low.length), wijCSS = this.options.wijCSS, commonData = $.extend({ candlestickType: this.type, visible: true }, series), seriesEles = [], widget = this.options.widget, candlestickWidth, i, candlestickEles, pathNode, dataObj, pointX;

                commonData.type = "candlestick";
                if (data.open && data.close) {
                    length = Math.min(length, data.open.length, data.close.length);
                }
                candlestickWidth = this.width / length;
                for (i = 0; i < length; i++) {
                    candlestickEles = this._paintCandlestickGraphic(data, i, candlestickWidth, seriesStyle, seriesHoverStyle);

                    if (this.annoPoints[sIdx] == null)
                        this.annoPoints[sIdx] = {};
                    this.annoPoints[sIdx][i] = candlestickEles.annotation;

                    dataObj = $.extend({}, commonData);
                    if (candlestickEles.path) {
                        pathNode = $(candlestickEles.path.node);
                        $.wijraphael.addClass(pathNode, wijCSS.canvasObject + " " + wijCSS.candlestickChart + " " + wijCSS.candlestickChartTracker);
                        pathNode.css("opacity", 0);
                        if (this.type !== strHL) {
                            $.extend(dataObj, { open: data.open[i], close: data.close[i] });
                        }
                        $.extend(dataObj, {
                            high: data.high[i], low: data.low[i], index: i, x: this.timeUtil.getTime(data.x[i]),
                            candlestickEles: candlestickEles, style: seriesStyle, hoverStyle: seriesHoverStyle
                        });
                        pathNode.data("wijchartDataObj", dataObj);
                    }

                    if (series.visible === false) {
                        $.each(candlestickEles, function (i, ele) {
                            if (ele && ele.hide) {
                                ele.hide();
                            }
                        });
                    }

                    seriesEles.push(candlestickEles);

                    // cache the bar position to show indicator line.
                    widget.dataPoints = widget.dataPoints || {};
                    widget.pointXs = widget.pointXs || [];
                    pointX = candlestickEles.x;

                    if (!widget.dataPoints[pointX.toString()]) {
                        widget.dataPoints[pointX.toString()] = [];
                        widget.pointXs.push(pointX);
                    }

                    widget.dataPoints[pointX.toString()].push(dataObj);
                }
                return seriesEles;
            };

            CandlestickChartRender.prototype._unbindLiveEvents = function () {
                var widgetName = this.options.widgetName;
                this.element.off("." + widgetName, ".wijcandlestickchart");
                chart.TrendlineRender.unbindLiveEvents(this.element, widgetName, this.options.wijCSS);
            };

            CandlestickChartRender.prototype._bindLiveEvents = function () {
                var _this = this;
                var o = this.options, eventPrefix = "", element = this.element;

                if ($.support.isTouchEnabled && $.support.isTouchEnabled()) {
                    eventPrefix = "wij";
                }

                function getDataFromEventArg(e) {
                    var target = $(e.target);
                    return target.data("wijchartDataObj");
                }

                function fireClientEvent(event, e, dataObj) {
                    var map = {
                        mouseover: o.mouseOver,
                        mouseout: o.mouseOut,
                        mousedown: o.mouseDown,
                        mouseup: o.mouseUp,
                        mousemove: o.mouseMove,
                        click: o.click
                    };
                    if ($.isFunction(map[event])) {
                        return map[event].call(element, e, dataObj);
                    }
                }

                $.each(["mouseover", "mouseout", "mousedown", "mouseup", "mousemove", "click"], function (i, event) {
                    _this.element.on(eventPrefix + event + "." + o.widgetName, ".wijcandlestickchart", function (e) {
                        if (o.disabled) {
                            return;
                        }
                        var dataObj = getDataFromEventArg(e);
                        if (fireClientEvent(event, e, dataObj) !== false) {
                            if (event === "mouseover" || event === "mouseout") {
                                _this["_" + event](dataObj);
                            }
                        }
                        dataObj = null;
                    });
                });

                chart.TrendlineRender.bindLiveEvents(element, o.widgetName, o.mouseDown, o.mouseUp, o.mouseOver, o.mouseOut, o.mouseMove, o.click, o.disabled, o.wijCSS, false);
            };

            CandlestickChartRender.prototype._setCandlestickStyleForHover = function (eles, style, open, close) {
                var setStyle = function (ele, style) {
                    if (ele && style) {
                        ele.attr(style);
                    }
                };

                setStyle(eles.highLow, style.highLow);
                setStyle(eles.open, style.open);
                setStyle(eles.close, style.close);
                setStyle(eles.high, style.highLow);
                setStyle(eles.low, style.highLow);
                if (open !== undefined && close !== undefined) {
                    if (open > close) {
                        setStyle(eles.openClose, style.fallingClose);
                    } else if (open < close) {
                        setStyle(eles.openClose, style.risingClose);
                    } else {
                        setStyle(eles.openClose, style.unchangeClose);
                    }
                }
            };

            CandlestickChartRender.prototype._mouseover = function (obj) {
                if (obj.hoverStyle) {
                    this.isHover = true;
                    this._setCandlestickStyleForHover(obj.candlestickEles, obj.hoverStyle, obj.open, obj.close);
                }
            };

            CandlestickChartRender.prototype._mouseout = function (obj) {
                var style = obj.style;
                if (this.isHover) {
                    this._setCandlestickStyleForHover(obj.candlestickEles, style, obj.open, obj.close);
                    this._formatCandlestick({
                        high: obj.high, low: obj.low, open: obj.open, close: obj.close, hlStyle: style.highLow, oStyle: style.open,
                        cStyle: style.close, index: obj.index, eles: obj.candlestickEles, fallingCloseStyle: style.fallingClose,
                        risingCloseStyle: style.risingClose, unchangeCloseStyle: style.unchangeClose
                    });
                    this.isHover = false;
                }
            };

            CandlestickChartRender.prototype._paintCandlestickGraphic = function (data, index, candlestickWidth, seriesStyle, seriesHoverStyle) {
                var o = this.options, x = data.x[index], high = data.high[index], low = data.low[index], open = data.open ? data.open[index] : 0, close = data.close ? data.close[index] : 0, originX = this.bounds.startX, originY = this.bounds.endY, hasOC = this.type !== strHL, axis = o.axis, xAxis = axis.x, yAxis = axis.y, minX = xAxis.min, minY = yAxis.min, maxX = xAxis.max, maxY = yAxis.max, oWidth = 0, cWidth = 0, kx = this.width / (maxX - minX), ky = this.height / (maxY - minY), hlStyle, cStyle, oStyle, hlWidth, ox, oy, cx, cy, hx, hy, lx, ly, candlestickEles, halfWidth, fallingCloseStyle, risingCloseStyle, callbackObj, unchangeCloseStyle, extendStyle, closeWidth, candlestickStyle, annotation;

                function getstrokeFillStroke(style) {
                    if (style) {
                        return { fill: style.fill, stroke: style.stroke };
                    }
                    return null;
                }

                oStyle = seriesStyle.open;
                cStyle = seriesStyle.close;
                hlStyle = seriesStyle.highLow;
                fallingCloseStyle = seriesStyle.fallingClose;
                risingCloseStyle = seriesStyle.risingClose;
                unchangeCloseStyle = seriesStyle.unchangeClose;
                hlWidth = hlStyle[strStrokeWidth] || 0;
                hx = (x - minX) * kx + this.bounds.startX;
                hy = (originY) - (high - minY) * ky;
                lx = hx;
                ly = originY - (low - minY) * ky;
                if (hasOC) {
                    if (this.type === strOHLC) {
                        oWidth = oStyle[strStrokeWidth] || 0;
                        cWidth = cStyle[strStrokeWidth] || 0;
                    } else {
                        // candlestick
                        if (open > close) {
                            oWidth = cWidth = fallingCloseStyle[strStrokeWidth] || 0;
                            closeWidth = fallingCloseStyle.width || 0;
                            extendStyle = getstrokeFillStroke(fallingCloseStyle);
                            candlestickStyle = fallingCloseStyle;
                        } else if (open === close) {
                            oWidth = cWidth = unchangeCloseStyle[strStrokeWidth] || 0;
                            closeWidth = unchangeCloseStyle.width || 0;
                            extendStyle = getstrokeFillStroke(unchangeCloseStyle);
                            candlestickStyle = unchangeCloseStyle;
                        } else {
                            oWidth = cWidth = risingCloseStyle[strStrokeWidth] || 0;
                            closeWidth = risingCloseStyle.width || 0;
                            extendStyle = getstrokeFillStroke(risingCloseStyle);
                            candlestickStyle = risingCloseStyle;
                        }

                        // if hlStyle sets a style,
                        hlStyle = $.extend({}, extendStyle, hlStyle);
                        candlestickWidth = candlestickWidth - (oWidth + cWidth) / 2;
                        if (candlestickWidth < 2) {
                            candlestickWidth = 2;
                        }
                    }

                    halfWidth = (candlestickWidth / 2) * 0.8;
                    if (this.type === strCandlestick) {
                        halfWidth = Math.min(closeWidth / 2, halfWidth);
                    }
                    if (halfWidth < 1) {
                        halfWidth = 1;
                    }
                    ox = hx - halfWidth;
                    oy = originY - (open - minY) * ky;
                    cx = hx + halfWidth;
                    cy = originY - (close - minY) * ky;
                    oy = Math.max(oy, hy + oWidth / 2);
                    oy = Math.min(oy, ly - oWidth / 2);
                    cy = Math.max(cy, hy + cWidth / 2);
                    cy = Math.min(cy, ly - cWidth / 2);
                }

                annotation = { x: hx, y: hy };

                if (this.type === strOHLC) {
                    candlestickEles = this._paintOHLC({ h: { x: hx, y: hy }, l: { x: lx, y: ly }, o: { x: ox, y: oy }, c: { x: cx, y: cy } });
                    candlestickEles.open.attr(oStyle);
                    candlestickEles.close.attr(cStyle);
                } else if (this.type === strHL) {
                    candlestickEles = this._paintHL({ h: { x: hx, y: hy }, l: { x: lx, y: ly } });
                } else {
                    candlestickEles = this._paintCandlestick({ h: { x: hx, y: hy }, l: { x: lx, y: ly }, o: { x: ox, y: oy }, c: { x: cx, y: cy } });
                    candlestickEles.high.attr(hlStyle);
                    candlestickEles.low.attr(hlStyle);
                    candlestickEles.openClose.attr(candlestickStyle);
                }
                if (candlestickEles.highLow) {
                    candlestickEles.highLow.attr(hlStyle);
                }
                this._formatCandlestick({
                    high: high, low: low, open: open, close: close, hlStyle: hlStyle, oStyle: oStyle, cStyle: cStyle, index: index, eles: candlestickEles,
                    fallingCloseStyle: fallingCloseStyle, risingCloseStyle: risingCloseStyle, unchangeCloseStyle: unchangeCloseStyle
                });

                // add fill for fire the events, because the opacity of this element is 0, set any fill to this element is OK.
                candlestickEles.path.attr({
                    "stroke-width": Math.max(closeWidth || 1, cWidth || 1, hlWidth || 1, oWidth || 1),
                    fill: "#000"
                });
                this.trackers.push(candlestickEles.path);

                // for indicator line.
                candlestickEles.x = $.round(hx);

                // set the extend style to seriesStyle for hover event.
                seriesStyle.highLow = hlStyle;

                candlestickEles.annotation = annotation;

                return candlestickEles;
            };

            CandlestickChartRender.prototype._formatCandlestick = function (options) {
                var candlestickFormatter = this.options.candlestickFormatter, index = options.index, high = options.high, low = options.low, open = options.open, close = options.close, hlStyle = options.hlStyle, oStyle = options.oStyle, cStyle = options.cStyle, fallingCloseStyle = options.fallingCloseStyle, risingCloseStyle = options.risingCloseStyle, unchangeCloseStyle = options.unchangeCloseStyle, type = this.type, data, styles;

                if (candlestickFormatter) {
                    data = { high: high, low: low };
                    styles = { highLow: hlStyle };
                    if (type === strOHLC) {
                        $.extend(data, { open: open, close: close });
                        $.extend(styles, { open: oStyle, close: cStyle });
                    } else if (type === strCandlestick) {
                        $.extend(data, { open: open, close: close });
                        $.extend(styles, {
                            fallingClose: fallingCloseStyle,
                            risingClose: risingCloseStyle,
                            unchangeClose: unchangeCloseStyle
                        });
                    }
                    candlestickFormatter.call(this, { data: data, eles: options.eles, style: styles });
                }
            };

            CandlestickChartRender.prototype._paintTracker = function (options, canvas) {
                var x = [], y = [], maxX, minX, maxY, minY;
                $.each(options, function (key, point) {
                    x.push(point.x);
                    y.push(point.y);
                });
                maxX = Math.max.apply(null, x);
                minX = Math.min.apply(null, x);
                maxY = Math.max.apply(null, y);
                minY = Math.min.apply(null, y);
                return canvas.rect(minX, minY, maxX - minX, maxY - minY);
            };

            CandlestickChartRender.prototype._paintOHLC = function (options) {
                var h = options.h, l = options.l, o = options.o, c = options.c, canvas = this.options.canvas, hlPath = ["M", h.x, ",", h.y, "V", l.y], oPath = ["M", o.x, ",", o.y, "H", h.x], cPath = ["M", h.x, ",", c.y, "H", c.x], hlEle, oEle, cEle, path;

                hlEle = canvas.path(hlPath.join(""));
                oEle = canvas.path(oPath.join(""));
                cEle = canvas.path(cPath.join(""));
                path = this._paintTracker(options, canvas);
                this._setTrackerForCandlestickEle([hlEle, oEle, cEle], path);
                this.group.push(oEle, cEle, hlEle);
                return { highLow: hlEle, open: oEle, close: cEle, path: path };
            };

            CandlestickChartRender.prototype._setTrackerForCandlestickEle = function (eles, tracker) {
                $.each(eles, function (i, ele) {
                    ele.node.tracker = tracker;
                });
            };

            CandlestickChartRender.prototype._paintHL = function (options) {
                var h = options.h, l = options.l, canvas = this.options.canvas, hlEle, pathEle;

                hlEle = canvas.path(["M", h.x, ",", h.y, "V", l.y].join(""));
                pathEle = hlEle.clone();
                this._setTrackerForCandlestickEle([hlEle], pathEle);
                this.group.push(hlEle);
                return { highLow: hlEle, path: pathEle };
            };

            CandlestickChartRender.prototype._paintCandlestick = function (options) {
                var h = options.h, l = options.l, o = options.o, c = options.c, canvas = this.options.canvas, ocEle, hEle, lEle, topY, bottomY, hPath, lPath, ocPath, path;

                if (c.y < o.y) {
                    topY = c.y;
                    bottomY = o.y;
                } else {
                    topY = o.y;
                    bottomY = c.y;
                }
                hPath = ["M", h.x, ",", h.y, "V", topY];
                lPath = ["M", l.x, ",", l.y, "V", bottomY];
                ocPath = ["M", o.x, ",", topY, "H", c.x, "V", bottomY, "H", o.x, "V", topY, "Z"];
                hEle = canvas.path(hPath.join(""));
                lEle = canvas.path(lPath.join(""));
                ocEle = canvas.path(ocPath.join(""));
                path = this._paintTracker(options, canvas);
                this.group.push(hEle, lEle, ocEle);
                this._setTrackerForCandlestickEle([hEle, lEle, ocEle], path);
                return { high: hEle, low: lEle, openClose: ocEle, path: path };
            };

            CandlestickChartRender.prototype._handleStyle = function (style, notHandleWidth) {
                if (!style) {
                    return;
                }
                if (notHandleWidth !== true) {
                    $.each(["width", "height"], function (i, prop) {
                        if (style[prop]) {
                            style["stroke-width"] = style[prop];
                            delete style[prop];
                        }
                    });
                }
                return style;
            };

            CandlestickChartRender.prototype._extendStyles = function (style) {
                var s = $.extend(true, {}, style);

                if (s) {
                    s.highLow = this._handleStyle(s.highLow);
                    s.close = this._handleStyle(s.close);
                    s.open = this._handleStyle(s.open);
                    s.fallingClose = this._handleStyle(s.fallingClose, true);
                    s.risingClose = this._handleStyle(s.risingClose, true);
                    s.unchangeClose = this._handleStyle(s.unchangeClose, true);
                }
                return s;
            };

            CandlestickChartRender.prototype._paintCandlesticks = function () {
                var seriesEls = [], seriesEl, self = this, o = self.options, seriesList = o.seriesList, seriesStyles = o.seriesStyles, seriesHoverStyles = o.seriesHoverStyles, fields = self.element.data("fields") || {}, chartElements = fields.chartElements || {}, candlestickEles = chartElements.candlestickEles || [], ani = o.animation, seTrans = o.seriesTransition, wijCSS = o.wijCSS, paths = [], shadowPaths = [], canvas = o.canvas;
                self.annoPoints = {};
                $.each(seriesList, function (i, series) {
                    var seriesStyle = self._extendStyles(seriesStyles[i]), seriesHoverStyle = self._extendStyles(seriesHoverStyles[i]);
                    if (o.widget._checkSeriesDataEmpty(series)) {
                        return true;
                    }
                    if (series.isTrendline) {
                        chart.TrendlineRender.renderSingleTrendLine(series, seriesStyle["highLow"], seriesHoverStyle["highLow"], o.axis, undefined, self.fieldsAniPathAttr, ani, seTrans, i, self.bounds, canvas, paths, shadowPaths, self.animationSet, self.aniPathsAttr, wijCSS, seriesEls, false, o.shadow);
                    } else {
                        seriesEl = self._paintCandlestickElements(series, seriesStyle, seriesHoverStyle, i);
                        candlestickEles = candlestickEles.concat(seriesEl);
                        seriesEls.push(seriesEl);
                    }
                });
                fields.seriesEles = seriesEls;
                fields.trackers = self.trackers;
                chartElements.candlestickEles = candlestickEles;
                chartElements.group = self.group;
                fields.trendLines = paths;
                fields.chartElements = chartElements;
                self.fields = fields;
                self.trackers.toFront();
            };

            // Using group to improve clip animation performance.
            CandlestickChartRender.prototype._playAnimation = function () {
                var animation = this.options.animation, animated = animation && animation.enabled, duration, easing;

                if (animated) {
                    duration = animation.duration || 400;
                    easing = animation.easing;
                    this.group.attr("clip-rect", [this.bounds.startX, this.bounds.startY, 0, this.height].join(","));
                    this.group.wijAnimate({ "clip-rect": [this.bounds.startX, this.bounds.startY, this.width, this.height].join(",") }, duration, easing);
                }
            };

            CandlestickChartRender.prototype._playTrendLineAnimation = function () {
                var self = this, o = self.options, animation = o.animation, animated = animation && animation.enabled, seriesTransition = o.seriesTransition, trendLines = self.fields.trendLines, duration, easing;

                if (animated) {
                    duration = animation.duration || 400;
                    easing = animation.easing || "linear";
                    if (trendLines && trendLines.length) {
                        chart.TrendlineRender.playAnimation(animated, duration, easing, seriesTransition, o.bounds, trendLines, self.fieldsAniPathAttr, o.axis, o.widget.extremeValue);
                    }
                }
            };

            CandlestickChartRender.prototype.render = function () {
                this.group = this.options.canvas.group();
                this._paintCandlesticks();
                this.element.data("fields", this.fields);
                this._unbindLiveEvents();
                this._bindLiveEvents();
                this._playAnimation();
                this._playTrendLineAnimation();
                _super.prototype.render.call(this);
            };
            return CandlestickChartRender;
        })(chart.BaseChartRender);
        chart.CandlestickChartRender = CandlestickChartRender;

        var wijcandlestickchart_css = (function (_super) {
            __extends(wijcandlestickchart_css, _super);
            function wijcandlestickchart_css() {
                _super.apply(this, arguments);
                this.wijCandlestickChart = "wijmo-wijcandlestickchart";
                this.candlestickChart = "wijcandlestickchart";
                this.candlestickChartTracker = "candlesticktracker";
            }
            return wijcandlestickchart_css;
        })(chart.wijchartcore_css);
        chart.wijcandlestickchart_css = wijcandlestickchart_css;

        var wijcandlestickchart_options = (function (_super) {
            __extends(wijcandlestickchart_options, _super);
            function wijcandlestickchart_options() {
                _super.apply(this, arguments);
                /** A value that indicates how to draw the candlestick element. Possible value is ohlc, hl, candlestick*/
                this.type = strCandlestick;
                /**
                * The animation option defines the animation effect and controls other aspects of the widget's animation,
                * such as duration and easing.
                */
                this.animation = {
                    enabled: true,
                    duration: 400,
                    easing: ">"
                };
                /**
                * @ignore
                */
                this.wijCSS = new wijmo.chart.wijcandlestickchart_css();
                /**
                * A callback to format the candlestick element.
                * @type Function
                */
                this.candlestickFormatter = null;
                /** @ignore*/
                this.showChartLabels = true;
                /** @ignore*/
                this.chartLabelStyle = {};
                /** @ignore*/
                this.chartLabelFormatString = "";
                /**
                * Creates an object to use as the tooltip, or hint, when the mouse is over a chart element.
                */
                this.hint = $.extend(true, {}, this.hint, {
                    contentStyle: {
                        "font-size": 12
                    }
                });
                /**
                * This event fires when the user clicks a mouse button.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {ICandlestickChartEventArgs} data Information about an event
                */
                this.mouseDown = null;
                /**
                * Fires when the user releases a mouse button while the pointer is over the chart element.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {ICandlestickChartEventArgs} data Information about an event
                */
                this.mouseUp = null;
                /**
                * Fires when the user first places the pointer over the chart element.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {ICandlestickChartEventArgs} data Information about an event
                */
                this.mouseOver = null;
                /**
                * Fires when the user moves the pointer off of the chart element.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {ICandlestickChartEventArgs} data Information about an event
                */
                this.mouseOut = null;
                /**
                * Fires when the user moves the mouse pointer while it is over a chart element.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {ICandlestickChartEventArgs} data Information about an event
                */
                this.mouseMove = null;
                /**
                * Fires when the user clicks the chart element.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {ICandlestickChartEventArgs} data Information about an event
                */
                this.click = null;
            }
            return wijcandlestickchart_options;
        })(chart.wijchartcore_options);

        wijcandlestickchart.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijcandlestickchart_options());
        wijcandlestickchart.prototype.widgetEventPrefix = widgetName;
        $.wijmo.registerWidget(widgetName, wijcandlestickchart.prototype);

        
    })(wijmo.chart || (wijmo.chart = {}));
    var chart = wijmo.chart;
})(wijmo || (wijmo = {}));

;
/// <reference path="../Base/jquery.wijmo.widget.ts" />
/// <reference path="../wijtextbox/jquery.wijmo.wijtextbox.ts" />
/// <reference path="../wijutil/jquery.wijmo.wijutil.ts" />
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*globals jQuery, window, XMLHttpRequest*/
    /*
    * Depends:
    *   jquery.ui.core.js
    *   jquery.ui.widget.js
    */
    (function (_tree) {
        var $ = jQuery, widgetName = "wijtree", nodeWidgetName = "wijtreenode", localCSS = {
            wijtreeInner: "wijmo-wijtree-inner"
        }, formatString = function (format) {
            var args = [];
            for (var _i = 0; _i < (arguments.length - 1); _i++) {
                args[_i] = arguments[_i + 1];
            }
            return format.replace(/{(\d+)}/g, function (match, index) {
                return typeof args[index] !== 'undefined' ? args[index] : match;
            });
        }, generateTreeCheckMarkup = function (checked, checkState) {
            var css = $.wijmo.wijtreenode.prototype.options.wijCSS, html = "<div class='wijmo-checkbox ui-widget' role='checkbox'><div class='wijmo-checkbox-box ui-widget ui-corner-all {0}' style='position: relative;'><span class='{1}'></span></div></div>", stateClasses = [css.stateDefault], iconClasses = ["wijmo-checkbox-icon"];

            if (checkState === "triState" || checkState === "indeterminate") {
                stateClasses.push(css.stateActive);
                iconClasses.push(css.icon);
                iconClasses.push(css.iconStop);
            } else if (checked) {
                stateClasses.push(css.stateActive);
                iconClasses.push(css.icon);
                iconClasses.push(css.iconCheck);
            }
            return formatString(html, stateClasses.join(" "), iconClasses.join(" "));
        }, generateItemsMarkup = function (items, showExpandCollapse, showCheckBoxes) {
            if (typeof showCheckBoxes === "undefined") { showCheckBoxes = false; }
            var lis = "", opts = $.wijmo.wijtreenode.prototype.options;

            $.each(items, function (i, item) {
                if (!$.isPlainObject(item)) {
                    return true;
                }
                var u = item.navigateUrl || "#", hasChildren = item.nodes && item.nodes.length > 0, expanded = (item.expanded === null || item.expanded === undefined) ? opts.expanded : item.expanded, wijCSS = (item.wijCSS === null || item.wijCSS === undefined) ? opts.wijCSS : item.wijCSS, li = "<li class='" + (hasChildren ? "wijmo-wijtree-parent" : "wijmo-wijtree-item") + "'><div class='wijmo-wijtree-node " + wijCSS.stateDefault + (hasChildren ? " wijmo-wijtree-header " : "") + (showExpandCollapse && hasChildren ? (expanded ? "wijmo-state-expanded" : "wijmo-state-collapsed") : "") + "' role='treeitem' aria-expanded='false' aria-checked='false' aria-selected='false'><span class='" + localCSS.wijtreeInner + " " + wijCSS.wijtreeInner + " " + wijCSS.helperClearFix + " " + wijCSS.cornerAll + "'>";

                if (hasChildren) {
                    li += "<span class='wijmo-wijtree-hitarea " + (showExpandCollapse ? (wijCSS.icon + " " + (expanded ? wijCSS.iconArrowRightDown : wijCSS.iconArrowRight)) : "") + "'></span>";
                }
                li += "<span class='wijmo-wijtree-nodeimage'></span>";
                if (showCheckBoxes) {
                    li += generateTreeCheckMarkup(item.checked, item.checkState);
                }
                li += $.browser.safari ? "<a href='" + u + "'>" : "<a class='wijmo-wijtree-link' href='" + u + "'>";
                if (typeof item.text === "string" && item.text) {
                    li += "<span>" + item.text + "</span>";
                }
                li += "</a></span></div>";
                if (hasChildren) {
                    li += "<ul class='wijmo-wijtree-list wijmo-wijtree-child " + wijCSS.helperReset + "'";
                    if (showExpandCollapse && !expanded) {
                        li += " style='display: none'";
                    }
                    li += ">";
                    li += generateItemsMarkup(item.nodes, showExpandCollapse, showCheckBoxes);
                    li += "</ul>";
                }
                li += "</li>";
                lis += li;
            });

            return lis;
        }, createNodeWidget = function ($li, options, owner, nodeWidgetName, treeWidgetFullName) {
            if ($.fn[nodeWidgetName]) {
                $li.data("owner", owner);
                if (!!options && $.isPlainObject(options)) {
                    $.extend(options, { treeClass: treeWidgetFullName });
                    $li[nodeWidgetName](options);
                } else {
                    $li[nodeWidgetName]({ treeClass: treeWidgetFullName });
                }
            }
            return $li;
        }, createTreeNodeWidget = function ($li, options, owner, nodeWidgetName, treeWidgetFullName) {
            if (!$.fn[nodeWidgetName]) {
                return null;
            }
            createNodeWidget($li, options, owner, nodeWidgetName, treeWidgetFullName);
            return $li.data($li.data("widgetName"));
        }, setHTML = function (target, content) {
            if (content == undefined) {
                return;
            }
            return target.each(function () {
                this.innerHTML = '';
                $(this).append(content);
            });
        }, getTreeNodeWidget = function ($ele) {
            var treeNode = $ele.data($ele.data("widgetName"));
            return $.isPlainObject(treeNode) ? null : treeNode;
        }, enableTabFocus = function ($ele, enable) {
            if (enable) {
                $ele.removeAttr("tabindex");
            } else if ($ele.attr("tabindex") !== "-1") {
                $ele.attr("tabindex", "-1");
            }
        }, removeARIA = function (ele) {
            $(ele).find('.wijmo-wijtree-node').removeAttr('role').removeAttribute('aria-expanded').removeAttribute('aria-checked').removeAttribute('aria-selected');
        };

        /** @widget */
        var wijtree = (function (_super) {
            __extends(wijtree, _super);
            function wijtree() {
                _super.apply(this, arguments);
            }
            wijtree.prototype._create = function () {
                if (window.wijmoApplyWijTouchUtilEvents) {
                    $ = window.wijmoApplyWijTouchUtilEvents($);
                }
                this._initState();
                this._createTree();
                this._attachEvent();
                this._attachNodeEvent();
                _super.prototype._create.call(this);
            };

            wijtree.prototype._setOption = function (key, value) {
                var self = this, isResetHitArea = false, o = self.options, check;

                switch (key) {
                    case "allowDrag":
                        self._setAllowDrag(value);
                        break;
                    case "allowDrop":
                        self._setAllowDrop(value);
                        break;
                    case "showCheckBoxes":
                        self._setCheckBoxes(value);
                        break;
                    case "showExpandCollapse":
                        if (self.options.showExpandCollapse !== value) {
                            isResetHitArea = true;
                        }
                        break;
                    default:
                        break;
                }
                _super.prototype._setOption.call(this, key, value);

                if (key === "nodes") {
                    if (value && value.length) {
                        self._createChildNodes();
                    } else {
                        self._clearChildNodes();
                    }
                }

                if (isResetHitArea === true) {
                    self._setHitArea(value);
                }
            };

            wijtree.prototype._innerDisable = function () {
                _super.prototype._innerDisable.call(this);
                this._toggleDisableTree(true);
            };

            wijtree.prototype._innerEnable = function () {
                _super.prototype._innerEnable.call(this);
                this._toggleDisableTree(false);
            };

            wijtree.prototype._toggleDisableTree = function (disabled) {
                this._setAllowDrag(!disabled);
            };

            wijtree.prototype._initState = function () {
                var self = this, o = self.options;
                self._selectedNodes = [];
                self._checkedNodes = [];
                if (!o.nodes) {
                    o.nodes = [];
                }

                self._insertPosition = "unKnown"; //end,after,before
                self.nodeWidgetName = "wijtreenode";
            };

            wijtree.prototype._initVariable = function () {
                var self = this;
                self._creatingNode = false;
                self._allNodesCreated = false;
                self._initNodesCreated = false;
                self._initializingTree = false;
                self._nextNodeIndex = 0;
                self._nodesCntPerPage = 0;
                self._totalNodesCreated = 0;
            };

            wijtree.prototype._createTree = function () {
                var self = this, o = self.options, treeClass = [
                    "wijmo-wijtree", o.wijCSS.widget, o.wijCSS.content,
                    o.wijCSS.helperClearFix, o.wijCSS.cornerAll].join(' '), nodesClass = [
                    "wijmo-wijtree-list ", o.wijCSS.helperReset,
                    (o.showExpandCollapse ? "" : "wijmo-wijtree-allexpanded")].join(' '), ele = self.element;

                if (ele.is("ul")) {
                    self.$nodes = ele;
                    ele.wrap("<div></div>");
                    self.widgetDom = ele.parent();
                } else if (ele.is("div")) {
                    self.widgetDom = ele;
                    self.$nodes = self.widgetDom.children("ul").eq(0);
                }

                if (self.$nodes.length) {
                    self.widgetDom.addClass(treeClass);
                    self.$nodes.addClass(nodesClass);

                    self._createChildNodes();
                    self.widgetDom.append($("<div>").css("clear", "both"));
                    enableTabFocus(self.element.find(".wijmo-wijtree-link:gt(0)"), false);

                    if (self.options.nodes.length > 0) {
                        self.widgetDom.attribute({
                            role: "tree",
                            "aria-multiselectable": true
                        });
                    }
                }
            };

            wijtree.prototype._clearChildNodes = function () {
                this.$nodes.empty();
                this.nodes && this.nodes.length && (this.nodes.length = 0);
            };

            wijtree.prototype._getItemHeight = function () {
                return this.$nodes.children("li:first").children(".wijmo-wijtree-node").outerHeight(true);
            };

            wijtree.prototype._createNodesAtIdle = function () {
                if (!this._creatingNode) {
                    this._createNodesPartially(false);
                }
                return;
            };

            wijtree.prototype._createNodesPartially = function (createRest) {
                this._creatingNode = true;
                if (this._allNodesCreated || !this.options.nodes || !this.options.nodes.length) {
                    this._unbindCreateNodesEvent();
                    return;
                }
                var self = this, options = {
                    nIndex: undefined,
                    htmlGenerated: true
                }, nodes, lis = self.$nodes.children("li"), widget, currentNodesCnt = self._totalNodesCreated;

                nodes = self._getField("nodes");
                if (!nodes) {
                    return;
                }
                while (self._nextNodeIndex < lis.length) {
                    if (nodes[self._nextNodeIndex] != null) {
                        self._nextNodeIndex++;
                        continue;
                    }
                    options.nIndex = self._nextNodeIndex;
                    widget = createTreeNodeWidget($(lis[self._nextNodeIndex]), options, self, self.nodeWidgetName, self.widgetFullName);
                    nodes[self._nextNodeIndex] = widget;
                    self._nextNodeIndex++;
                    if (!createRest && currentNodesCnt + self._nodesCntPerPage < self._totalNodesCreated) {
                        break;
                    }
                }
                if (this._nextNodeIndex >= lis.length) {
                    this._unbindCreateNodesEvent();
                    this._allNodesCreated = true;
                }
                this._creatingNode = false;
            };

            wijtree.prototype._bindCreateNodesEvent = function () {
                var self = this;
                $(document).bind("scroll." + this.widgetName, $.proxy(self._createNodesAtIdle, self)).bind("mousemove." + this.widgetName, $.proxy(self._createNodesAtIdle, self)).bind("click." + this.widgetName, $.proxy(self._createNodesAtIdle, self)).bind("keydown." + this.widgetName, $.proxy(self._createNodesAtIdle, self));
            };

            wijtree.prototype._unbindCreateNodesEvent = function () {
                $(document).unbind('.' + this.widgetName);
            };

            wijtree.prototype._createChildNodes = function () {
                var self = this, o = self.options, options = {
                    nIndex: undefined,
                    htmlGenerated: false
                }, nodeWidgets = [], $ul = self.$nodes, lis, widget, $li;

                if (o.nodes && o.nodes.length) {
                    self._initVariable();
                    setHTML($ul, generateItemsMarkup(o.nodes, o.showExpandCollapse, o.showCheckBoxes));
                    self._nodesCntPerPage = document.documentElement.clientHeight / self._getItemHeight();
                    options.htmlGenerated = true;
                    self._initializingTree = true;
                    lis = $ul.children("li");
                    lis.each(function (idx, ele) {
                        $li = $(ele);

                        options.nIndex = idx;
                        if (!self._initNodesCreated) {
                            widget = createTreeNodeWidget($li, options, self, self.nodeWidgetName, self.widgetFullName);
                            self._nextNodeIndex++;
                        } else {
                            widget = null;
                            self._allNodesCreated = false;
                        }
                        nodeWidgets.push(widget);
                        if (self._totalNodesCreated >= self._nodesCntPerPage * 2) {
                            self._initNodesCreated = true;
                        }
                    });
                    self._initializingTree = false;
                    self._allNodesCreated = self._nextNodeIndex >= lis.length;
                    if (!self._allNodesCreated) {
                        self._bindCreateNodesEvent();
                    }
                } else {
                    lis = $ul.children("li");
                    lis.each(function (idx, ele) {
                        $li = $(ele);

                        widget = createTreeNodeWidget($li, options, self, self.nodeWidgetName, self.widgetFullName);
                        nodeWidgets.push(widget);
                        if (!$.browser.safari && widget.$navigateUrl && widget.$navigateUrl.length && widget.$navigateUrl.is("a")) {
                            widget.$navigateUrl.addClass("wijmo-wijtree-link");
                        }
                        o.nodes.push(widget.options);
                    });
                }
                self._hasChildren = nodeWidgets.length > 0;
                self._setField("nodes", nodeWidgets);
                self.nodes = nodeWidgets;
            };

            wijtree.prototype._createNodeWidget = function ($li, options) {
                return createNodeWidget($li, options, this, this.nodeWidgetName, this.widgetFullName);
            };

            /*tree event*/
            wijtree.prototype._attachEvent = function () {
                this._attachDroppable();
            };

            wijtree.prototype._attachDroppable = function () {
                var self = this, o = self.options, droppable = o.droppable, options = {
                    accept: "li",
                    scope: "tree"
                }, events = {
                    drop: function (event, ui) {
                        var d = ui.draggable, dragNode = self._getNodeWidget(d), dropNode, position, oldOwner, parent, brothers, idx, oldPosition, newPosition = -1, oldShowCheckBoxes = dragNode._tree.options.showCheckBoxes;

                        droppable = o.droppable;

                        if (self._trigger("nodeBeforeDropped", event, ui) === false || !dragNode || self._isDisabled()) {
                            self._isDragging = false;
                            return;
                        }
                        dropNode = dragNode._dropTarget;
                        position = dragNode._insertPosition;
                        if (dropNode && position !== "unKnown") {
                            oldOwner = dragNode._getOwner();

                            if (oldOwner) {
                                oldPosition = d.index();
                            }

                            /*reset old tree*/
                            dragNode._tree._isDragging = false;

                            if (position === "end") {
                                newPosition = dropNode.getNodes().length;
                                parent = dropNode;
                            } else if (position === "before" || position === "after") {
                                parent = dropNode._getOwner();
                                brothers = parent.getNodes();
                                idx = $.inArray(dropNode, brothers);
                                if (idx !== -1) {
                                    newPosition = position === "before" ? idx : idx + 1;
                                }
                            }
                            if (!parent._isAllowDrop()) {
                                self._isDragging = false;
                                return;
                            }

                            if (droppable && $.isFunction(droppable.drop)) {
                                ui["oldParent"] = oldOwner.element;
                                ui["newParent"] = parent.element;
                                ui["oldIndex"] = oldPosition;
                                ui["newIndex"] = newPosition;
                                droppable.drop.call(self.element, event, ui);
                            } else {
                                if (oldOwner) {
                                    oldOwner.remove(d);
                                }
                                if (newPosition !== -1) {
                                    // re-calculate position (when old parent == new parent)
                                    if (position === "before" || position === "after") {
                                        if (idx !== $.inArray(dropNode, brothers)) {
                                            newPosition--;
                                        }
                                    }

                                    // Handling when the drop tree has no child-nodes
                                    if (self.$nodes.children("li").length) {
                                        parent.add(d, newPosition);
                                    } else {
                                        self.add(d, newPosition);
                                    }
                                }
                            }

                            if (oldShowCheckBoxes !== self.options.showCheckBoxes) {
                                dragNode._setCheckBoxes(self.options.showCheckBoxes);
                            }

                            /*reset old tree*/
                            $("a", d).eq(0).blur();
                            if (dragNode.options.selected) {
                                dragNode._setSelected(false);
                            }

                            /*set tree*/
                            setTriState(oldOwner);
                            setTriState(parent);

                            $.extend(ui, {
                                sourceParent: oldOwner ? oldOwner.element : null,
                                sIndex: oldPosition,
                                targetParent: parent.element,
                                tIndex: newPosition,
                                widget: dragNode
                            });
                            self._trigger("nodeDropped", event, ui);
                        }
                    }
                }, setTriState = function (node) {
                    if (!node.element.is(":" + self.widgetFullName) && node.getNodes().length > 0 && node._tree.options.showCheckBoxes && node._tree.options.allowTriState) {
                        node.getNodes()[0]._setParentCheckState();
                    }
                };

                $.extend(options, droppable, events); // mind the order: events must be at last.
                if ($.fn.droppable) {
                    self.widgetDom.droppable(options);
                }
            };

            wijtree.prototype._attachNodeEvent = function () {
                // Note: 1. focus/blur do not support bubbling. 2. focusin/focusout is always available using jQuery, but only in webkit can you get widget from "event.data".
                this.element.bind("focusin." + this.widgetName, $.proxy(this._onFocus, this)).bind("focusout." + this.widgetName, $.proxy(this._onBlur, this)).bind("click." + this.widgetName, $.proxy(this._onClick, this)).bind("mouseover." + this.widgetName, $.proxy(this._onMouseOver, this)).bind("mouseout." + this.widgetName, $.proxy(this._onMouseOut, this)).bind("keydown." + this.widgetName, $.proxy(this._onKeyDown, this));
            };

            wijtree.prototype._onClick = function (event) {
                this._callEvent(event, '_onClick');
                if ($.browser.webkit) {
                    this.widgetDom.focus();
                }
            };

            wijtree.prototype._onFocus = function (event) {
                var $nodeDom;
                if (!event.data) {
                    $nodeDom = this._getNodeByDom(event.target);
                    event.data = $nodeDom.data($nodeDom.data("widgetName"));
                }
                this._callEvent(event, '_onFocus');
            };

            wijtree.prototype._onBlur = function (event) {
                var $nodeDom;
                if (!event.data) {
                    $nodeDom = this._getNodeByDom(event.target);
                    event.data = $nodeDom.data($nodeDom.data("widgetName"));
                }
                this._callEvent(event, '_onBlur');
            };

            wijtree.prototype._onKeyDown = function (event) {
                this._callEvent(event, '_onKeyDown');
            };

            wijtree.prototype._onMouseOut = function (event) {
                this._callEvent(event, '_onMouseOut');
            };

            wijtree.prototype._onMouseOver = function (event) {
                this._callEvent(event, '_onMouseOver');
            };

            wijtree.prototype._callEvent = function (event, type) {
                if (!this._allNodesCreated && this.options.nodes && this.options.nodes.length) {
                    this._createNodesAtIdle();
                }
                var el = event.target, node;
                if (el) {
                    node = this._getNodeWidgetByDom(el);
                    if (node === null) {
                        return;
                    } else if (node._hasChildren && node._getField("nodes")) {
                        if (!node._allNodesCreated && node.options.nodes && node.options.nodes.length) {
                            node._createChildNodesAtIdle();
                        }
                    }
                    node[type](event);
                }
            };

            wijtree.prototype._nodeSelector = function () {
                return ":wijmo-wijtreenode";
            };

            /*public methods*/
            /**
            * The getSelectedNodes method gets the selected nodes.
            * @example $("selector").wijtree("getSelectedNodes");
            * @returns {array}
            */
            wijtree.prototype.getSelectedNodes = function () {
                return this._selectedNodes;
            };

            /**
            * The getCheckedNodes method gets the nodes which are checked.
            * @example $("selector").wijtree("getCheckedNodes");
            * @returns {array}
            */
            wijtree.prototype.getCheckedNodes = function () {
                var self = this, checkedNodes = [], treeNodeWidgetName = self.nodeWidgetName;

                $(self._nodeSelector(), self.element).each(function (idx, ele) {
                    if ($(ele)[treeNodeWidgetName]("option", "checked") && $(ele)[treeNodeWidgetName]("option", "checkState") !== "indeterminate") {
                        checkedNodes.push($(ele));
                    }
                });
                return checkedNodes;
            };

            /**
            * The destroy method will remove the rating functionality completely and will return the element to its pre-init state.
            * @example $("selector").wijtree("destroy");
            */
            wijtree.prototype.destroy = function () {
                var self = this, $nodes = self.$nodes, o = self.options, c = [
                    "wijmo-wijtree", o.wijCSS.widget,
                    o.wijCSS.content, o.wijCSS.helperClearFix, o.wijCSS.cornerAll].join(' ');
                self.widgetDom.removeClass(c).removeAttr("role").removeAttribute("aria-multiselectable");
                enableTabFocus(self.element.find(".wijmo-wijtree-link"), true);

                if (self.widgetDom.data("ui-droppable")) {
                    self.widgetDom.droppable("destroy");
                }

                self._unbindCreateNodesEvent();
                self.element.unbind('.' + self.widgetName);
                self.widgetDom.children("div[style]:last").remove();
                $nodes.removeData("nodes").removeClass("wijmo-wijtree-list" + " " + o.wijCSS.helperReset);
                $nodes.children("li").each(function (idx, ele) {
                    var nodeWidget = self._getNodeWidget($(ele));
                    if (nodeWidget) {
                        nodeWidget.destroy();
                    }
                });
                $.wijmo.wijtree.prototype.options.nodes = null;

                _super.prototype.destroy.call(this);
            };

            /**
            * The add method adds a node to the tree widget.
            * @example $("#tree").wijtree("add", "node 1", 1);
            * @param {string|object} node
            * 1.markup html.such as "<li><a>node</a></li>" as a node.
            * 2.wijtreenode widget.
            * 3.object options according to the options of wijtreenode.
            * 4.node's text.
            * @param {number} position The position to insert at.
            */
            wijtree.prototype.add = function (node, position) {
                var nodeWidget = null, o = {}, $node, self = this, i, originalLength, itemDom, cnodes, $li;

                if ($.browser.safari) {
                    itemDom = "<li><a href='{0}'>{1}</a></li>";
                } else {
                    itemDom = "<li><a href='{0}' class='wijmo-wijtree-link'>{1}</a></li>";
                }
                if (typeof node === "string") {
                    $node = $(itemDom.replace(/\{0\}/, "#").replace(/\{1\}/, node));
                    self._createNodeWidget($node, o);
                    nodeWidget = $node.data($node.data("widgetName"));
                } else if (node.jquery) {
                    if (!node.data("widgetName")) {
                        self._createNodeWidget(node, o);
                    }
                    nodeWidget = node.data(node.data("widgetName"));
                    nodeWidget._setField("owner", self);
                } else if (node.nodeType) {
                    $node = $(node);
                    self._createNodeWidget($node, o);
                    nodeWidget = $node.data($node.data("widgetName"));
                } else if ($.isPlainObject(node)) {
                    $node = $(itemDom.replace(/\{0\}/, node.url ? node.url : "#").replace(/\{1\}/, node.text)); //node
                    node.isAddedNodeWithOptions = true;
                    self._createNodeWidget($node, node);
                    nodeWidget = $node.data($node.data("widgetName"));
                }

                if (nodeWidget === null) {
                    return;
                }
                originalLength = self.nodes.length;
                if (!position || position > originalLength) {
                    if (position !== 0) {
                        position = originalLength;
                    }
                }
                cnodes = nodeWidget.getNodes();
                nodeWidget._tree = self;
                for (i = 0; i < cnodes.length; i++) {
                    cnodes[i]._tree = self;
                }

                if (originalLength > 0 && originalLength !== position) {
                    $li = this.$nodes.find(">li:eq(" + position + ")");
                    if (nodeWidget.element.get(0) !== $li.get(0)) {
                        nodeWidget.element.insertBefore($li);
                    }
                } else {
                    self.$nodes.append(nodeWidget.element);
                }
                self._changeCollection(position, nodeWidget);
                nodeWidget._initNodeClass();
            };

            /**
            * The remove method removes the indicated node from the wijtree element.
            * @example $("#tree").wijtree("remove", 1);
            * @param {number|object} node
            * which node to be removed
            * 1.wijtreenode element.
            * 2.the zero-based index of which node you determined to remove.
            */
            wijtree.prototype.remove = function (node) {
                var idx = -1, nodeWidget, lis = this.$nodes.children("li");
                if (node && node.jquery) {
                    idx = node.index();
                } else if (typeof node === "number") {
                    idx = node;
                }
                if (idx < 0 || idx >= this.nodes.length) {
                    return;
                }
                nodeWidget = this.nodes[idx];
                if (nodeWidget) {
                    nodeWidget.element.detach();
                    removeARIA(nodeWidget.element);
                } else {
                    $(lis[idx]).detach();
                    removeARIA(lis[idx]);
                }
                this._changeCollection(idx);
            };

            wijtree.prototype._changeCollection = function (idx, nodeWidget) {
                var nodes = this.nodes, ons = this.options.nodes, widgetDom = this.widgetDom;
                if (nodeWidget) {
                    nodes.splice(idx, 0, nodeWidget);
                    ons.splice(idx, 0, nodeWidget.options);
                } else {
                    nodes.splice(idx, 1);
                    ons.splice(idx, 1);
                }

                if (nodes.length === 0) {
                    widgetDom.removeAttr("role");
                    widgetDom.removeAttribute("aria-multiselectable");
                } else {
                    widgetDom.attr("role", "tree");
                    widgetDom.attribute("aria-multiselectable", true);
                }
            };

            /**
            * The getNodes method gets an array that contains the root nodes of the current tree.
            * @example $("#tree").wijtree("getNodes");
            * @return {Array}
            */
            wijtree.prototype.getNodes = function () {
                if (this.options.nodes && this.options.nodes.length) {
                    this._createNodesPartially(true);
                }
                return this.nodes;
            };

            wijtree.prototype._createParentNodes = function ($li) {
                var self = this, options = { nIndex: undefined, htmlGenerated: true }, nodeWidget, $lis = [], $seachedNode = $li;

                if ($seachedNode.closest("ul").parent().hasClass("wijmo-wijtree")) {
                    options.nIndex = this.element.children("li").index($seachedNode);
                    createTreeNodeWidget($seachedNode, options, self, self.nodeWidgetName, self.widgetFullName);
                } else {
                    while (!$seachedNode.closest("ul").parent().hasClass("wijmo-wijtree")) {
                        $seachedNode = $seachedNode.closest("ul").closest("li");
                        $lis.push($seachedNode);
                        if (getTreeNodeWidget($seachedNode))
                            break;
                    }
                    $lis.reverse();
                    $.each($lis, function (index, $ele) {
                        nodeWidget = getTreeNodeWidget($ele);
                        if (!nodeWidget) {
                            options.nIndex = $ele.parent().children("li").index($ele);
                            nodeWidget = createTreeNodeWidget($ele, options, self, self.nodeWidgetName, self.widgetFullName);
                        }
                        nodeWidget._createChildNodeWidget();
                    });
                }
                return getTreeNodeWidget($li);
            };

            /**
            * The findNodeByText method finds a node by the specified node text.
            * @example $("#tree").wijtree("findNodeByText", "node 1");
            * @param {string} txt The text of which node you want to find.
            * @return {wijtreenode}
            */
            wijtree.prototype.findNodeByText = function (txt) {
                var self = this, nodes = $(".wijmo-wijtree-node a>span", this.$nodes).filter(function () {
                    return $(this).text() === txt;
                }), nodeWidget = null, node;
                if (nodes.length) {
                    node = nodes.eq(0).closest("li");
                    nodeWidget = getTreeNodeWidget(node);
                    if (!nodeWidget) {
                        nodeWidget = self._createParentNodes(node);
                    }
                }
                return nodeWidget;
            };

            wijtree.prototype._setAllowDrag = function (value) {
                var self = this, $allNodes, nodeSelector = self._nodeSelector(), nodeWName = "wijmo-" + self.nodeWidgetName;

                if (!$.fn.draggable) {
                    return;
                }

                if (value) {
                    $allNodes = self.element.find(nodeSelector);
                    $allNodes.each(function () {
                        var w = $(this).data(nodeWName);
                        if (!$(this).data("ui-draggable") && w.options.allowDrag !== false && (!w.$navigateUrl.data("events") || !w.$navigateUrl.data("events").mousedown)) {
                            w.$navigateUrl.one("mousedown." + w.widgetName, w, w._onMouseDown);
                        }
                    });
                } else {
                    $allNodes = self.element.find(nodeSelector + ":ui-draggable");
                    $allNodes.each(function () {
                        var w = $(this).data(nodeWName);
                        if (!w.options.allowDrag) {
                            $(this).draggable("destroy");
                        }
                    });
                }
            };

            wijtree.prototype._setAllowDrop = function (value) {
                if (!$.fn.droppable) {
                    return;
                }

                if (!this.widgetDom.data("ui-droppable")) {
                    this._attachDroppable();
                }
            };

            wijtree.prototype._setCheckBoxes = function (value) {
                var self = this;
                $.each(self.getNodes(), function (idx, node) {
                    node._setCheckBoxes(value);
                });
            };

            wijtree.prototype._setHitArea = function (value) {
                var self = this;

                self.$nodes[value ? "addClass" : "removeClass"]("wijmo-wijtree-allexpanded");
                self.$nodes.children("li").each(function (idx, ele) {
                    var nodeWidget = self._getNodeWidget($(ele));
                    if (nodeWidget !== null) {
                        nodeWidget._setHitArea(value);
                    }
                });
            };

            /*region methods(private)*/
            wijtree.prototype._getNodeWidget = function ($node) {
                if ($node.is(this._nodeSelector())) {
                    var widget = $node.data($node.data("widgetName"));
                    return widget;
                }
                return null;
            };

            wijtree.prototype._getNodeWidgetByDom = function (el) {
                var node = this._getNodeByDom(el);
                return this._getNodeWidget(node);
            };

            wijtree.prototype._getNodeByDom = function (el) {
                return $(el).closest(this._nodeSelector());
            };

            wijtree.prototype._refreshNodesClass = function () {
                var nodes = this.getNodes(), i;
                for (i = 0; i < nodes.length; i++) {
                    nodes[i]._initNodeClass();
                }
            };

            wijtree.prototype._getField = function (key) {
                return this.element.data(key);
            };

            wijtree.prototype._setField = function (key, value) {
                this.element.data(key, value);
            };

            wijtree.prototype._isAllowDrop = function () {
                return this.options.allowDrop;
            };
            return wijtree;
        })(wijmo.wijmoWidget);
        _tree.wijtree = wijtree;

        var wijtreenode = (function (_super) {
            __extends(wijtreenode, _super);
            function wijtreenode() {
                _super.apply(this, arguments);
            }
            wijtreenode.prototype._setOption = function (key, value) {
                var self = this, check;

                switch (key) {
                    case "accessKey":
                        if (self.$navigateUrl !== null) {
                            self.$navigateUrl.attr("accesskey", value);
                        }
                        break;
                    case "checked":
                        if (self.options[key] !== value) {
                            self._checkClick();
                        }
                        break;
                    case "collapsedIconClass":
                    case "expandedIconClass":
                    case "itemIconClass":
                        self.options[key] = value;
                        self._initNodeImg();
                        break;
                    case "expanded":
                        self._setExpanded(value);
                        break;
                    case "selected":
                        self._setSelected(value);
                        break;
                    case "text":
                        self._setText(value);
                        break;
                    case "toolTip":
                        self._setToolTip(value);
                        break;
                    case "navigateUrl":
                        self._setNavigateUrlHref(value);
                        break;
                    case "allowDrag":
                        self._setAllowDrag(value);
                        break;
                    default:
                        break;
                }

                if (key === "nodes") {
                    self.options.nodes.length = 0;
                    self._setField("nodes", null);
                    self._setNodes = true;
                    $.each(value, function (i, n) {
                        self.options.nodes.push(n);
                    });
                    self.options.nodes.concat();
                    if (value && value.length) {
                        self._hasChildren = self._hasSubNodes();
                        self._createChildNodes();
                        self._initNodeClass();
                    } else {
                        self._clearChildNodes();
                    }
                } else {
                    _super.prototype._setOption.call(this, key, value);
                }
            };

            wijtreenode.prototype._initVariable = function () {
                var self = this;
                self._allNodesCreated = false;
                self._initNodesCreated = false;
                self._nextNodeIndex = 0;
            };

            wijtreenode.prototype._initState = function () {
                var self = this;
                self._tree = null;
                self._dropTarget = null;
                self._checkState = "unChecked"; //Checked, UnChecked, Indeterminate
                self._insertPosition = "unKnown"; //end,after,before
                self.$nodeBody = null;
                self.$checkBox = null;
                self.$hitArea = null;
                self.$nodes = null;
                self.$subnodes = null;
            };

            wijtreenode.prototype._create = function () {
                var self = this, o = self.options;
                self._setNodes = o.isAddedNodeWithOptions;
                self._initState();
                self.element.data("widgetName", "wijmo-wijtreenode");
                self._createTreeNode();
                self._initNode();

                if (o.selected) {
                    self._tree._selectedNodes.push(self);
                }

                if (o.checked) {
                    self._checkState = "checked";
                }
                _super.prototype._create.call(this);
            };

            wijtreenode.prototype._createTreeNode = function () {
                var $li = this.element, childOpts, self = this, ownerOpts, o = self.options;

                if (self._tree === null) {
                    self._tree = self._getTree();
                }

                if (!isNaN(o.nIndex)) {
                    ownerOpts = self._getOwner().options, childOpts = ownerOpts.nodes[o.nIndex];
                    if (childOpts && !childOpts.nodes) {
                        childOpts.nodes = [];
                    }
                    $.extend(o, childOpts);
                    ownerOpts.nodes[o.nIndex] = o;
                } else if (!o.nodes) {
                    o.nodes = [];
                }

                if (self._isHtmlGenerated()) {
                    self._tree._totalNodesCreated++;
                    self.$nodeBody = $li.children(".wijmo-wijtree-node");
                    self.$inner = self.$nodeBody.children("." + localCSS.wijtreeInner);
                    self.$nodeImage = self.$inner.children(".wijmo-wijtree-nodeimage");

                    if (self._tree.options.showCheckBoxes) {
                        self.$checkBox = $li.find(">div>span>div.wijmo-checkbox");
                        self.$checkBoxBody = self.$checkBox.children("div");
                        self.$checkBoxIcon = self.$checkBoxBody.children("span");
                    }
                    self.$navigateUrl = self.$inner.children("a");
                    self.$text = self.$navigateUrl.children("span").eq(0);
                } else {
                    self.$nodeImage = $("<span>");
                    self.$nodeBody = $("<div>").attribute({
                        role: "treeitem",
                        "aria-expanded": false,
                        "aria-checked": false,
                        "aria-selected": false
                    });

                    self.$navigateUrl = $li.children("a");

                    if (self.$navigateUrl.length === 0) {
                        self.$navigateUrl = $li.children("div");
                        self.$navigateUrl.addClass("wijmo-wijtree-template");
                        self._isTemplate = true;
                    }

                    if (self.$navigateUrl.length === 0) {
                        self.$navigateUrl = $("<a href='#'></a>");
                    }

                    if (!self._isTemplate) {
                        self.$text = self.$navigateUrl.children("span").eq(0);
                        if (self.$text.length === 0) {
                            self.$navigateUrl.wrapInner("<span></span>");
                            self.$text = self.$navigateUrl.children("span").eq(0);
                        }
                    }
                    self.$inner = $("<span></span>").addClass(o.wijCSS.helperClearFix + " " + localCSS.wijtreeInner + " " + o.wijCSS.wijtreeInner + " " + o.wijCSS.cornerAll);
                    self.$inner.append(self.$nodeImage);
                    if (self._tree.options.showCheckBoxes) {
                        self._createTreeCheck();
                    }
                    self.$inner.append(self.$navigateUrl);
                    self.$nodeBody.append(self.$inner);
                    $li.prepend(self.$nodeBody);
                }

                self._hasChildren = self._hasSubNodes();
                self._createChildNodes();
            };

            wijtreenode.prototype._clearChildNodes = function () {
                var nodes = this._getField("nodes");
                this.$nodes.empty();
                nodes && nodes.length && (nodes.length = 0);
                this.$subnodes && this.$subnodes.length && (this.$subnodes.length = 0);
            };

            wijtreenode.prototype._createChildNodes = function () {
                var self = this, o = self.options, $li = self.element;

                self._initVariable();
                if (self._hasChildren) {
                    if (self.$nodes === null) {
                        self.$nodes = $li.children("ul").eq(0);
                    }
                    if (self._isHtmlGenerated()) {
                        self.$hitArea = self.$inner.children(".wijmo-wijtree-hitarea");
                    } else {
                        $li.addClass("wijmo-wijtree-parent");
                        self.$nodeBody.addClass("wijmo-wijtree-node wijmo-wijtree-header " + o.wijCSS.stateDefault);
                        self.$hitArea = $("<span>");
                        self.$inner.prepend(self.$hitArea);
                        self.$nodes.addClass("wijmo-wijtree-list wijmo-wijtree-child " + o.wijCSS.helperReset);
                    }
                    if (o.expanded || !self._isHtmlGenerated()) {
                        self._createChildNodeWidget();
                    }
                } else {
                    if (!self._isHtmlGenerated()) {
                        $li.addClass("wijmo-wijtree-item");
                        self.$nodeBody.addClass("wijmo-wijtree-node " + o.wijCSS.stateDefault);
                    }
                    self._setField("nodes", []);
                }
            };

            wijtreenode.prototype._isHtmlGenerated = function () {
                return !!this.options.htmlGenerated;
            };

            wijtreenode.prototype._createInitNode = function ($li, index, nodesCount, opts, subNodes) {
                var self = this, nodeWidget;
                nodeWidget = getTreeNodeWidget($li);
                if (!nodeWidget) {
                    if (subNodes) {
                        subNodes.push($li);
                    }
                    opts.nIndex = index;
                    if (!self._initNodesCreated || !self._isHtmlGenerated()) {
                        nodeWidget = createTreeNodeWidget($li, opts, self, nodeWidgetName, self.options.treeClass);
                        if (!subNodes && !$.browser.safari) {
                            $li.children(".wijmo-wijtree-node").find("." + localCSS.wijtreeInner + " a").addClass("wijmo-wijtree-link");
                        }
                        nodeWidget._index = index;
                        self._nextNodeIndex++;
                    } else {
                        nodeWidget = null;
                        self._allNodesCreated = false;
                    }
                    if (self._tree._initializingTree) {
                        if (self._tree._totalNodesCreated >= self._tree._nodesCntPerPage * 2) {
                            self._initNodesCreated = true;
                        }
                    } else {
                        if (self._nextNodeIndex >= self._tree._nodesCntPerPage * 2) {
                            self._initNodesCreated = true;
                        }
                    }
                }
                self._allNodesCreated = self._nextNodeIndex >= nodesCount;
                return nodeWidget;
            };

            wijtreenode.prototype._bindCreateNodesEvent = function () {
                var self = this;
                $(document).bind("scroll." + this.widgetName, $.proxy(self._createChildNodesAtIdle, self)).bind("mousemove." + this.widgetName, $.proxy(self._createChildNodesAtIdle, self)).bind("click." + this.widgetName, $.proxy(self._createChildNodesAtIdle, self)).bind("keydown." + this.widgetName, $.proxy(self._createChildNodesAtIdle, self));
            };

            wijtreenode.prototype._unbindCreateNodesEvent = function () {
                $(document).unbind('.' + this.widgetName);
            };

            wijtreenode.prototype._createChildNodesAtIdle = function () {
                if (!this._tree._creatingNode) {
                    this._createChildNodesPartially(false);
                }
                return;
            };

            wijtreenode.prototype._createChildNodesPartially = function (createRest) {
                this._tree._creatingNode = true;
                var self = this, options = {
                    nIndex: undefined,
                    htmlGenerated: true
                }, nodes = [], lis = self.$nodes.children("li"), widget, currentNodesCnt = self._nextNodeIndex;

                if (!self._getField("nodes")) {
                    self._setField("nodes", nodes);
                } else {
                    nodes = self._getField("nodes");
                }
                if (this._allNodesCreated || !this.options.nodes || !this.options.nodes.length) {
                    this._unbindCreateNodesEvent();
                    return;
                }
                while (self._nextNodeIndex < lis.length) {
                    if (nodes[self._nextNodeIndex] != null) {
                        self._nextNodeIndex++;
                        continue;
                    }
                    options.nIndex = self._nextNodeIndex;
                    widget = createTreeNodeWidget($(lis[self._nextNodeIndex]), options, self, nodeWidgetName, self.options.treeClass);
                    nodes[self._nextNodeIndex] = widget;
                    self._nextNodeIndex++;
                    if (!createRest && currentNodesCnt + self._tree._nodesCntPerPage < self._nextNodeIndex) {
                        break;
                    }
                }
                if (this._nextNodeIndex >= lis.length) {
                    this._unbindCreateNodesEvent();
                    this._allNodesCreated = true;
                }
                this._tree._creatingNode = false;
            };

            wijtreenode.prototype._createChildNode = function () {
                var self = this, o = self.options, nodes = [], lis, opts = {
                    nIndex: undefined,
                    cfli: undefined,
                    treeClass: o.treeClass,
                    nodes: undefined,
                    htmlGenerated: self._isHtmlGenerated()
                };
                if (self._setNodes && o.nodes && o.nodes.length) {
                    if (!self.$nodes || !self.$nodes.length) {
                        self.$nodes = $("<ul>").appendTo(self.element);
                    }
                    setHTML(self.$nodes, generateItemsMarkup(o.nodes, self._tree.options.showExpandCollapse, self._tree.options.showCheckBoxes));
                    self.$subnodes = [];
                    opts.htmlGenerated = true;
                    lis = self.$nodes.children("li");
                    lis.each(function (idx, ele) {
                        var $li = $(ele);
                        nodes.push(self._createInitNode($li, idx, lis.length, opts, self.$subnodes));
                    });
                } else {
                    if (!o.nodes) {
                        o.nodes = [];
                    }
                    if (self.$subnodes === null) {
                        self._updateSubNodes();
                    }
                    $.each(self.$subnodes, function (idx, $li) {
                        if (!self._isHtmlGenerated()) {
                            opts.nodes = [];
                        }
                        nodes.push(self._createInitNode($li, idx, self.$subnodes.length, opts));
                    });
                }
                if (!self._allNodesCreated) {
                    self._bindCreateNodesEvent();
                }
                return nodes;
            };

            wijtreenode.prototype._initNode = function () {
                var self = this, o = self.options;
                if (!self._initialized) {
                    self._initialized = true;
                    self._initNavigateUrl();
                    if (!self._isTemplate && self.$text && self.$text.length) {
                        self._text = self.$text.html();
                        o.text = self._text;
                    }
                    self._hasChildren = self._hasSubNodes();
                    self._initNodesUL();
                    self._initNodeClass();
                    self._initNodeImg();
                    if (self._isAllowDrag()) {
                        self.$navigateUrl.one("mousedown." + self.widgetName, self, self._onMouseDown);
                    }
                }
            };

            wijtreenode.prototype._initNodeClass = function () {
                var self = this, o = self.options, style, nodeClass = "wijmo-wijtree-item", hitClass = o.wijCSS.icon + " " + (o.expanded ? o.wijCSS.iconArrowRightDown : o.wijCSS.iconArrowRight);

                if (self._tree.options.showExpandCollapse) {
                    if (self._hasChildren || !!o.hasChildren) {
                        if (!self._isHtmlGenerated()) {
                            self.$nodeBody.removeClass("wijmo-state-expanded wijmo-state-collapsed");
                            if (o.expanded) {
                                self.$nodeBody.addClass("wijmo-state-expanded");
                            } else {
                                self.$nodeBody.addClass("wijmo-state-collapsed");
                            }
                        }
                        if (self.$hitArea !== null) {
                            self.$hitArea.removeClass([o.wijCSS.icon, o.wijCSS.iconArrowRightDown, o.wijCSS.iconArrowRight].join(' '));
                            self.$hitArea.addClass(hitClass);
                        } else {
                            self.$hitArea = $("<span>").addClass(hitClass).prependTo(self.$inner);
                            self.element.removeClass(nodeClass).addClass("wijmo-wijtree-parent");
                        }

                        if (self._hasChildren && self.$nodes && self.$nodes.length) {
                            style = o.expanded ? "" : "none";
                            self.$nodes.css({ display: style });
                        }
                    } else if (self.$hitArea && self.$hitArea.length) {
                        self.$hitArea.remove();
                        self.$hitArea = null;
                        self.element.removeClass("wijmo-wijtree-parent").addClass(nodeClass);
                    }
                }

                if (!self._hasChildren && self.$nodes && self.$nodes.length) {
                    self.$nodes.css({ display: "none" });
                }

                if (o.selected && self.$inner) {
                    self.$inner.addClass(o.wijCSS.stateActive);
                }
            };

            wijtreenode.prototype._initNodesUL = function () {
                var self = this;

                if (!self._isHtmlGenerated() && self._tree.options.showExpandCollapse) {
                    if (self._hasChildren && self.$nodes && self.$nodes.length) {
                        self.$nodes[self._expanded ? 'show' : 'hide']();
                    }
                }
            };

            wijtreenode.prototype._initNavigateUrl = function () {
                var self = this, href;

                if (self._isHtmlGenerated()) {
                    return;
                }
                href = self.$navigateUrl.attr("href");
                if (!this._isTemplate) {
                    if (!href || href.length === 0) {
                        self._setNavigateUrlHref("#");
                    }
                }
            };

            wijtreenode.prototype._applyIconClass = function ($el, o) {
                var vAttr = $el.attr("expandediconclass");

                if (vAttr) {
                    o.expandedIconClass = vAttr;
                    $el.removeAttr("expandediconclass");
                }
                vAttr = $el.attr("collapsediconclass");
                if (vAttr) {
                    o.collapsedIconClass = vAttr;
                    $el.removeAttr("collapsediconclass");
                }
                vAttr = $el.attr("itemiconclass");
                if (vAttr) {
                    o.itemIconClass = vAttr;
                    $el.removeAttr("itemiconclass");
                }
            };

            wijtreenode.prototype._initNodeImg = function () {
                var self = this, o = self.options, $el = self.element;
                if (self.$nodeImage === null || !self.$nodeImage.length) {
                    self.$nodeImage = $("<span>");
                }

                /* initial html has icon attribute for asp.net mvc*/
                self._applyIconClass($el, o);

                /* end */
                if (o.collapsedIconClass !== "" && o.expandedIconClass !== "") {
                    self.$nodeImage.removeClass().addClass(o.wijCSS.icon).addClass(o.expanded ? o.expandedIconClass : o.collapsedIconClass);
                    if (!self._tree.options.showExpandCollapse) {
                        self.$nodeImage.addClass(o.expandedIconClass);
                    }
                    self.$nodeImage.insertBefore(self.$checkBox);
                } else if (o.itemIconClass !== "") {
                    self.$nodeImage.removeClass().addClass(o.wijCSS.icon);
                    self.$nodeImage.addClass(o.itemIconClass);
                    self.$nodeImage.insertBefore(self.$checkBox);
                }
            };

            wijtreenode.prototype._setNavigateUrlHref = function (href) {
                if (this.$navigateUrl) {
                    if (href === "" || typeof href === "undefined" || href === null) {
                        href = "#";
                    }
                    this.$navigateUrl.attr("href", href);
                }
            };

            wijtreenode.prototype._editNode = function () {
                this._tree._editMode = true;
                this.$navigateUrl.hide();
                if (!this.$editArea) {
                    this.$editArea = $("<input type=\"text\">").wijtextbox();
                }
                this.$editArea.val(this.$text.html());
                this.$editArea.insertBefore(this.$navigateUrl);
                this.$editArea.bind("blur", this, this._editionComplete);
                this.$editArea.focus();
            };

            wijtreenode.prototype._editionComplete = function (event) {
                var self = event.data, text;
                self._tree._editMode = false;
                if (self.$editArea) {
                    text = self.$editArea.val();
                    self.$editArea.remove();
                }
                self.$navigateUrl.show();
                self.$editArea = null;
                self._changeText(text);
            };

            wijtreenode.prototype._changeText = function (text) {
                var self = this, o = self.options;
                if (self.$text !== null && text !== "") {
                    self.$text.text(text);
                    o.text = text;
                    self._tree._trigger("nodeTextChanged", null, self);
                }
            };

            /*behavior Methods*/
            wijtreenode.prototype._toggleExpanded = function () {
                var self = this, o = self.options;
                if (!self._isClosestDisabled()) {
                    if (self._hasChildren || o.hasChildren) {
                        self._setExpanded(!o.expanded);
                    }
                }
            };

            wijtreenode.prototype._createChildNodeWidget = function () {
                var self = this, nodes = [];
                if (!self._getField("nodes")) {
                    if (self._hasChildren) {
                        nodes = self._createChildNode();
                    }
                    self._setField("nodes", nodes);
                }
            };

            wijtreenode.prototype._expandNode = function (expand) {
                var self = this, treeOption = self._tree.options, trigger = expand ? "nodeExpanding" : "nodeCollapsing";

                if (self._tree._trigger(trigger, null, {
                    node: this,
                    params: this.options.params
                }) === false) {
                    return;
                }

                self._createChildNodeWidget();
                self.$nodeBody.attribute("aria-expanded", expand);
                self._expanded = expand;
                self.options.expanded = expand;

                if (!self._isClosestDisabled()) {
                    if (expand) {
                        if (treeOption.expandDelay > 0) {
                            window.clearTimeout(self._expandTimer);
                            self._expandTimer = window.setTimeout(function () {
                                self._expandNodeVisually();
                            }, treeOption.expandDelay);
                        } else {
                            self._expandNodeVisually();
                        }
                    } else {
                        if (treeOption.collapseDelay > 0) {
                            window.clearTimeout(self._collapseTimer);
                            self._collapseTimer = window.setTimeout(function () {
                                self._collapseNodeVisually();
                            }, treeOption.collapseDelay);
                        } else {
                            self._collapseNodeVisually();
                        }
                    }
                }
            };

            wijtreenode.prototype._expandNodeVisually = function () {
                var self = this, $nodes, o = self.options;
                if (self._tree.options.autoCollapse) {
                    $nodes = self.element.siblings(":" + this.widgetFullName);
                    $.each($nodes, function (i) {
                        var widget = self._getNodeWidget($nodes[i]);
                        if (widget.options.expanded) {
                            widget._setExpanded(false);
                        }
                    });
                }
                if (o.collapsedIconClass !== "" && o.expandedIconClass !== "") {
                    self.$nodeImage.removeClass(o.collapsedIconClass).addClass(o.expandedIconClass);
                }
                self._internalSetNodeClass(true);
                self._show();
            };

            wijtreenode.prototype._collapseNodeVisually = function () {
                var self = this;
                if (self.options.collapsedIconClass !== "" && self.options.expandedIconClass !== "") {
                    self.$nodeImage.removeClass(self.options.expandedIconClass).addClass(self.options.collapsedIconClass);
                }

                if (self._tree._focusNode && self.$nodes.find(self._tree._focusNode.$navigateUrl).length) {
                    self._setFocused(true);
                }
                self._internalSetNodeClass(false);
                self._hide();
            };

            wijtreenode.prototype._internalSetNodeClass = function (expanded) {
                var css = this.options.wijCSS, iconCss = [css.icon, css.iconArrowRightDown, css.iconArrowRight].join(' ');
                if (!this.$hitArea) {
                    return;
                }
                this.$hitArea.removeClass(iconCss).addClass(css.icon).addClass(expanded ? css.iconArrowRightDown : css.iconArrowRight);
                this.$nodeBody.removeClass("wijmo-state-expanded").removeClass("wijmo-state-collapsed");
                if (expanded) {
                    this.$nodeBody.addClass("wijmo-state-expanded");
                } else {
                    this.$nodeBody.addClass("wijmo-state-collapsed");
                }
            };

            wijtreenode.prototype._show = function () {
                this._animation(true);
            };

            wijtreenode.prototype._hide = function () {
                this._animation(false);
            };

            wijtreenode.prototype._animation = function (show) {
                var self = this, $nodes = self.$nodes, animate = show ? "expandAnimation" : "collapseAnimation", event = show ? "nodeExpanded" : "nodeCollapsed", effect, animation = self._tree.options[animate], opacity, strOpacity;

                function restoreOpacity($ele) {
                    if ($ele.css(strOpacity) !== opacity) {
                        $ele.css(strOpacity, opacity);
                    }
                }

                if ($nodes && $nodes.length) {
                    if (animation) {
                        if ($.browser.msie && parseInt($.browser.version) < 9) {
                            strOpacity = "filter";
                        } else {
                            strOpacity = "opacity";
                        }
                        opacity = $nodes.css(strOpacity);
                        effect = animation.animated || animation.effect;
                        if ($.effects && !!effect) {
                            $nodes[show ? "show" : "hide"](effect, {
                                easing: animation.easing
                            }, animation.duration, function () {
                                restoreOpacity($nodes);
                                self._tree._trigger(event, null, self);
                            });
                        } else {
                            $nodes[show ? "show" : "hide"](animation.duration, function () {
                                restoreOpacity($nodes);
                                self._tree._trigger(event, null, self);
                            });
                        }
                    } else {
                        $nodes[show ? "show" : "hide"]();
                        self._tree._trigger(event, null, self);
                    }
                }
            };

            wijtreenode.prototype._getBounds = function ($el) {
                var h = $el.height(), w = $el.width(), t = $el.offset().top, l = $el.offset().left;
                return { h: h, w: w, t: t, l: l };
            };

            wijtreenode.prototype._isMouseInsideRect = function (p, b) {
                if (p.x < b.l || p.x >= b.l + b.w) {
                    return false;
                }
                if (p.y <= b.t + 1 || p.y >= b.t + b.h) {
                    /*fix 1px on the mouse out the element
                    (e.g. 31<30.98 now 31<30.98+1 maybe
                    pageY/PageX are int but left/top are float)*/
                    return false;
                }
                return true;
            };

            /**
            * not used
            */
            wijtreenode.prototype._getNodeByMouseOn = function (p) {
                var self = this;
                $("li").each(function () {
                    var b = self._getBounds($(this));

                    //$.ui.isOver is removed from jQuery UI 1.10, so remove this method.
                    //if ($.ui.isOver(p.y, p.x, b.t, b.l, b.h, b.w)) {
                    //    return $(this);
                    //}
                    if ((p.y > b.t) && (p.y < (b.t + b.h)) && (p.x > b.l) && (p.x < (b.l + b.w))) {
                        return $(this);
                    }
                });
                return null;
            };

            wijtreenode.prototype._drowTemplate = function (p, $tmpl, $target) {
                var position = "unKnown", body = $target.is(".wijmo-wijtree-node") ? $target : $target.children(".wijmo-wijtree-node"), n = this._getBounds(body);
                $tmpl.width(body.width());

                if (p.y > n.t && p.y < n.t + n.h / 2) {
                    $tmpl.offset({ left: n.l, top: n.t });
                    position = "before";
                } else if (p.y > n.t + n.h / 2 && p.y < n.t + n.h) {
                    $tmpl.offset({ left: n.l, top: n.t + n.h });
                    position = "after";
                }
                return position;
            };

            wijtreenode.prototype._beginDrag = function (e) {
                var self = this, $item = self.element, $drag, to = self._tree.options, draggable = to.draggable, $tmpl = $("<div>").addClass("wijmo-wijtree-insertion " + to.wijCSS.stateDefault), options = {
                    cursor: "point",
                    cursorAt: { top: 15, left: -25 },
                    helper: function () {
                        return $("<div>" + self.$navigateUrl.html() + "</div>").addClass(to.wijCSS.header).addClass(to.wijCSS.cornerAll);
                    },
                    distance: $.browser.msie ? 1 : 10,
                    handle: self.$navigateUrl,
                    scope: "tree"
                }, events = {
                    start: function (event, ui) {
                        self._tree._isDragging = true;
                        self._tree.widgetDom.prepend($tmpl);
                        self._tree._trigger("nodeDragStarted", event, self);
                        if (draggable && $.isFunction(draggable.start)) {
                            draggable.start.call(self.element, event, ui);
                        } else {
                            $item.hide();
                        }
                    },
                    drag: function (event, ui) {
                        var ev = event, t = (ev.srcElement || ev.originalEvent.target), $target = $(t), dropNode, p = { x: ev.pageX, y: ev.pageY };

                        if ($tmpl) {
                            $tmpl.hide();
                        }
                        if ($target) {
                            dropNode = self._getNodeWidget(t);
                            if (dropNode && !dropNode._tree._isDisabled()) {
                                if ($target.closest("." + localCSS.wijtreeInner, self.element).length) {
                                    self._insertPosition = "end"; //end,after,before
                                } else {
                                    $tmpl.show();
                                    self._insertPosition = self._drowTemplate(p, $tmpl, dropNode.element);
                                }
                                if (dropNode !== self) {
                                    self._dropTarget = dropNode;
                                }
                            } else if ($target.is(":" + self.options.treeClass)) {
                                self._dropTarget = $target.data(self.options.treeClass);
                                self._insertPosition = "end";
                            }
                        }
                        self._tree._trigger("nodeDragging", event, self);
                        if (draggable && $.isFunction(draggable.drag)) {
                            draggable.drag.call(self.element, event, ui);
                        }
                    },
                    stop: function (event, ui) {
                        $tmpl.remove();
                        self._dropTarget = null;
                        self._insertPosition = "unKnown";
                        self._tree._isDragging = false;
                        if (draggable && $.isFunction(draggable.stop)) {
                            draggable.stop.call(self.element, event, ui);
                        } else {
                            $item.show();
                            self._resetDrag();
                        }
                    }
                };

                if (typeof to.dropVisual === "string") {
                    $drag = $(to.dropVisual);
                    $tmpl = $drag.length ? $drag : $tmpl;
                } else if ($.isFunction(to.dropVisual)) {
                    $drag = $(to.dropVisual.call());
                    $tmpl = $drag.length ? $drag : $tmpl;
                }
                $tmpl.hide();

                $.extend(options, draggable, events); // mind the order: events must be at last.
                if ($.fn.draggable) {
                    $item.draggable(options).trigger(e);
                    if ($.browser.mozilla) {
                        self._setFocused(true);
                    }
                }
            };

            wijtreenode.prototype._resetDrag = function () {
                var self = this, nodes, i, o = self.options;
                if (!self._isAllowDrag() && self.element.data("ui-draggable")) {
                    self.element.draggable("destroy");
                }
                nodes = self.getNodes();
                for (i = 0; i < nodes.length; i++) {
                    nodes[i]._resetDrag();
                }
            };

            wijtreenode.prototype._createTreeCheck = function () {
                var self = this, o = self.options, html = generateTreeCheckMarkup(o.checked, o.checkState);

                self.$checkBox = $(html);
                self.$checkBox.insertAfter(self.$nodeImage);
                self.$checkBoxBody = self.$checkBox.children("div");
                self.$checkBoxIcon = self.$checkBoxBody.children("span");
            };

            wijtreenode.prototype._mouseOverTreeCheck = function (event) {
                var $el = $(event.target), self = this, o = self.options, css = o.wijCSS;
                if (self._isOverCheckbox($el)) {
                    self.$checkBoxBody.addClass(css.stateHover);
                }
            };

            wijtreenode.prototype._mouseOutTreeCheck = function (event) {
                var $el = $(event.target), self = this, o = self.options, css = o.wijCSS;
                if (self._isOverCheckbox($el)) {
                    self.$checkBoxBody.removeClass(css.stateHover);
                }
            };

            wijtreenode.prototype._setTreeCheckState = function (checkState) {
                var self = this, o = self.options, css = o.wijCSS, checkClass = css.icon + " " + css.iconCheck, triStateClass = css.icon + " " + css.iconStop;

                if (checkState === "unCheck") {
                    self.$checkBoxBody.removeClass(css.stateActive);
                    self.$checkBoxIcon.removeClass(checkClass + " " + triStateClass);
                } else if (checkState === "check") {
                    self.$checkBoxBody.addClass(css.stateActive);
                    self.$checkBoxIcon.removeClass(triStateClass).addClass(checkClass);
                } else if (checkState === "triState") {
                    self.$checkBoxBody.addClass(css.stateActive);
                    self.$checkBoxIcon.removeClass(checkClass).addClass(triStateClass);
                }
            };

            wijtreenode.prototype._checkClick = function () {
                var self = this, o = self.options;
                if (!self._isClosestDisabled()) {
                    if (self._tree._trigger("nodeCheckChanging", null, self) === false) {
                        return;
                    }
                    if (o.checked && self._checkState === "indeterminate") {
                        self._checkState = "checked";
                        self._checkItem();
                    } else {
                        self._checkState = o.checked ? "unChecked" : "checked";
                        self._setChecked(!o.checked);
                    }
                    self._tree._trigger("nodeCheckChanged", null, self);
                }
            };

            wijtreenode.prototype._checkItem = function () {
                var self = this, autoCheck = false, tree = self._tree;
                if (tree === null || !tree.options.showCheckBoxes) {
                    return;
                }
                if (tree.options.autoCheckNodes && self._checkState !== "indeterminate") {
                    autoCheck = true;
                    self._changeChecked(self.options.checked);
                }
                if (tree.options.allowTriState) {
                    self._setParentCheckState();
                }
                self.options.checked ? self._checkNode(autoCheck) : self._unCheckNode(autoCheck);
            };

            wijtreenode.prototype._checkNode = function (autoCheck) {
                // todo: add to tree._checkedNodes
                var self = this, o = self.options, nodes = this.getNodes(), i;
                if (self._checkState === "checked") {
                    self._setTreeCheckState("check");
                    o.checkState = "checked";
                } else if (self._checkState === "indeterminate") {
                    self._setTreeCheckState("triState");
                    o.checkState = "indeterminate";
                }

                if (autoCheck) {
                    for (i = 0; i < nodes.length; i++) {
                        nodes[i]._checkNode(true);
                    }
                }
            };

            wijtreenode.prototype._unCheckNode = function (autoCheck) {
                // todo: remove to tree._checkedNodes
                var nodes = this.getNodes(), o = this.options, i;
                this._setTreeCheckState("unCheck");
                o.checkState = "unChecked";
                if (autoCheck) {
                    for (i = 0; i < nodes.length; i++) {
                        nodes[i]._unCheckNode(true);
                    }
                }
            };

            wijtreenode.prototype._changeChecked = function (checked) {
                var nodes = this.getNodes();
                $.each(nodes, function (i, node) {
                    node.options.checked = checked;
                    node.$nodeBody.attribute("aria-checked", checked);
                    node._checkState = checked ? "checked" : "unChecked";
                    node._changeChecked(checked);
                });
            };

            wijtreenode.prototype._setParentCheckState = function () {
                var owner = this._getOwner(), nodes, allChecked = true, hasChildrenChecked = false, triState = false, i, self = this;
                if (owner.element.is(":" + self.options.treeClass)) {
                    return;
                }
                nodes = owner.getNodes();
                for (i = 0; i < nodes.length; i++) {
                    if (nodes[i]._checkState === "indeterminate") {
                        triState = true;
                    }
                    if (nodes[i].options.checked) {
                        hasChildrenChecked = true;
                    } else {
                        allChecked = false;
                    }
                    if (!allChecked && hasChildrenChecked) {
                        break;
                    }
                }
                if (triState) {
                    owner._checkState = "indeterminate";
                    owner._setChecked(true);
                } else {
                    if (hasChildrenChecked) {
                        if (allChecked) {
                            owner._checkState = "checked";
                            owner._checkNode(false);
                        } else {
                            owner._checkState = "indeterminate";
                        }
                        owner._setChecked(true);
                    } else {
                        owner._checkState = "unChecked";
                        owner._setChecked(false);
                        owner._unCheckNode(false);
                    }
                }
                owner._setParentCheckState();
            };

            /*Events*/
            // todo: make self assignment consistent. (need to refactor other places.)
            wijtreenode.prototype._isOverCheckbox = function (el) {
                return el.closest(".wijmo-checkbox", this.element).length > 0;
            };

            wijtreenode.prototype._isWithinHitArea = function (el) {
                return this.$hitArea && this.$hitArea[0] === el[0];
            };

            wijtreenode.prototype._isOverInner = function (el) {
                return el.closest("." + localCSS.wijtreeInner, this.element).length > 0;
            };

            wijtreenode.prototype._onKeyDown = function (event) {
                var el = $(event.target), self = this;
                if (self._isOverInner(el)) {
                    //update for Move focus to next control with Tab key.
                    if (event.keyCode === wijmo.getKeyCodeEnum().TAB) {
                        return true;
                    }
                    self._keyAction(event);
                }
            };

            wijtreenode.prototype._onClick = function (event) {
                var el = $(event.target), self = this;
                if (self._isOverCheckbox(el)) {
                    self._checkClick();
                    event.preventDefault();
                    event.stopPropagation();
                } else if (self._isWithinHitArea(el)) {
                    self._toggleExpanded();
                    event.preventDefault();
                    event.stopPropagation();
                } else if (self._isOverInner(el)) {
                    self._click(event);
                }
            };

            wijtreenode.prototype._onMouseDown = function (event) {
                var el = $(event.target), node = event.data;
                if (!node._tree._isDisabled() && node._isAllowDrag()) {
                    if (el.closest(".wijmo-wijtree-node", node.element).length > 0) {
                        node._beginDrag(event);
                    }
                }
            };

            wijtreenode.prototype._onMouseOver = function (event) {
                var el = $(event.target), self = this, rel = $(event.relatedTarget);
                if (self._isOverInner(el) && (this._tree._overNode !== self || rel.is(':' + this.widgetFullName) || rel.is('.wijmo-wijtree-node'))) {
                    if (!self._isClosestDisabled()) {
                        self._mouseOver(event);
                    }
                    this._tree._overNode = self;
                }
                if (!self._isClosestDisabled()) {
                    self._mouseOverHitArea(event);
                    self._mouseOverTreeCheck(event);
                }
            };

            wijtreenode.prototype._onMouseOut = function (event) {
                var el = $(event.target), self = this, rel = $(event.relatedTarget), node = this._getNodeWidget(rel.get(0));
                if (self._isOverInner(el) && (this._tree._overNode !== node || rel.is(':' + this.widgetFullName) || rel.is('.wijmo-wijtree-list') || rel.is('.ui-effects-wrapper') || rel.is('.wijmo-wijtree-node'))) {
                    if (!self._isClosestDisabled()) {
                        self._mouseOut(event);
                    }
                    this._tree._overNode = null;
                }
                if (!self._isClosestDisabled()) {
                    self._mouseOutHitArea(event);
                    self._mouseOutTreeCheck(event);
                }
            };

            wijtreenode.prototype._onFocus = function (event) {
                var el = $(event.target), self = this, css = self.options.wijCSS;
                if (self._isOverInner(el) && !self._isClosestDisabled() && !(el.hasAllClasses(css.iconArrowRightDown) || el.hasAllClasses(css.iconArrowRight)) && !self._isOverCheckbox(el)) {
                    if (self._tree._focusNode) {
                        self._tree._focusNode.$navigateUrl.trigger("focusout");
                        enableTabFocus(self._tree._focusNode.$navigateUrl, false);
                    } else {
                        enableTabFocus(self._tree.nodes[0].$navigateUrl, false);
                    }

                    enableTabFocus(el, true);
                    self._focused = true;
                    self._tree._focusNode = this;
                    self.$inner.addClass(css.stateFocus);
                    self._tree._trigger("nodeFocus", event, self);
                }
            };

            wijtreenode.prototype._onBlur = function (event) {
                var el = $(event.target), node = event.data, css = node.options.wijCSS;
                if (!node._isClosestDisabled()) {
                    node._focused = false;
                    if (node._isOverInner(el)) {
                        node.$inner.removeClass(css.stateFocus);
                    }
                    node._tree._trigger("nodeBlur", event, node);
                }
            };

            wijtreenode.prototype._click = function (event) {
                var self = this, o = self.options, tree = self._tree, url = self.$navigateUrl.attr("href");
                if (!self._isClosestDisabled()) {
                    if (!/^[#,\s]*$/.test(url)) {
                        if ($.browser.msie && /^7\.[\d]*/.test($.browser.version)) {
                            if (url.indexOf(window.location.href) < 0) {
                                return;
                            }
                        } else {
                            return;
                        }
                    }
                    self._isClick = true;
                    tree._ctrlKey = event.ctrlKey;
                    if (o.selected && tree._ctrlKey) {
                        self._setSelected(false);
                    } else if (o.selected && !self._tree._editMode && tree.options.allowEdit && !self._isTemplate) {
                        self._editNode();
                    } else {
                        self._setSelected(!o.selected);
                    }
                    if (!self._isTemplate) {
                        event.preventDefault();
                        event.stopPropagation();
                    }
                } else {
                    self._setNavigateUrlHref("");
                }
            };

            wijtreenode.prototype._selectNode = function (select, event) {
                var self = this, o = self.options, ctrlKey, idx;
                if (!self._isClosestDisabled() && !self._tree._isDragging) {
                    ctrlKey = self._tree._ctrlKey;
                    if (ctrlKey) {
                        idx = $.inArray(self, self._tree._selectedNodes);
                        if (idx !== -1 && !select) {
                            self._tree._selectedNodes.splice(idx, 1);
                            self.$inner.removeClass(o.wijCSS.stateActive);
                        }
                    } else {
                        $.each(self._tree._selectedNodes, function (i, n) {
                            n.$inner.removeClass(o.wijCSS.stateActive);
                            n.options.selected = false;
                            n.$nodeBody.attribute("aria-selected", false);
                        });
                        self._tree._selectedNodes = [];
                    }
                    if (select) {
                        idx = $.inArray(self, self._tree._selectedNodes);
                        if (idx === -1) {
                            this._tree._selectedNodes.push(self);
                        }
                        self.$inner.addClass(o.wijCSS.stateActive);
                    } else {
                        self.$inner.removeClass(o.wijCSS.stateActive);
                    }
                    if (self._isClick) {
                        self._tree._trigger("nodeClick", event, self);
                    }
                    self._isClick = false;
                    self._tree._ctrlKey = false;
                    self._tree._trigger("selectedNodeChanged", event, self);
                }
            };

            wijtreenode.prototype._keyAction = function (e) {
                var el = e.target, self = this, keyCode = wijmo.getKeyCodeEnum();
                if (self._isClosestDisabled()) {
                    return;
                }
                if (el) {
                    if (self._tree._editMode && e.keyCode !== keyCode.ENTER) {
                        return;
                    }
                    switch (e.keyCode) {
                        case keyCode.UP:
                            self._moveUp();
                            break;
                        case keyCode.DOWN:
                            self._moveDown();
                            break;
                        case keyCode.RIGHT:
                            if (self._tree.options.showExpandCollapse) {
                                self._moveRight();
                            }
                            break;
                        case keyCode.LEFT:
                            if (self._tree.options.showExpandCollapse) {
                                self._moveLeft();
                            }
                            break;
                        case 83:
                            if (!self._tree._editMode && self._tree.options.allowSorting) {
                                self.sortNodes();
                            }
                            break;
                        case 113:
                            if (self._tree.options.allowEdit) {
                                self._editNode();
                            }
                            break;
                        case 109:
                            if (self._tree.options.showExpandCollapse && this._expanded) {
                                self._setExpanded(false);
                            }
                            break;
                        case 107:
                            if (self._tree.options.showExpandCollapse && !this._expanded) {
                                self._setExpanded(true);
                            }
                            break;
                        case keyCode.ENTER:
                            if (self._tree._editMode) {
                                e.data = self;
                                self._editionComplete(e);
                                self._setFocused(true);
                                e.preventDefault();
                            }
                            break;
                        case keyCode.SPACE:
                            if (self._tree.options.showCheckBoxes) {
                                self._checkClick(); //fix bug 113652
                            }
                            break;
                    }
                    if (!self._isTemplate && e.keyCode !== keyCode.ENTER) {
                        e.preventDefault();
                        e.stopPropagation();
                    }
                }
            };

            wijtreenode.prototype._prevNode = function (node) {
                var el = node.element;
                if (el.prev().length > 0) {
                    return el.prev().data(el.data("widgetName"));
                }
            };

            wijtreenode.prototype._nextNode = function (node) {
                var el = node.element;
                if (el.next().length > 0) {
                    return el.next().data(el.data("widgetName"));
                }
            };

            wijtreenode.prototype._getNextExpandedNode = function (node) {
                var nextNode = node, nextNodes = node.getNodes(), newNode;
                if (node._expanded && nextNodes.length > 0) {
                    newNode = nextNodes[nextNodes.length - 1];
                    if (newNode !== null) {
                        nextNode = this._getNextExpandedNode(newNode);
                    }
                }
                return nextNode;
            };

            wijtreenode.prototype._getNextNode = function (owner) {
                var nextNode = null, self = this;
                if (owner.element.is(":" + self.options.treeClass)) {
                    return null;
                }
                nextNode = self._nextNode(owner);
                if (nextNode) {
                    return nextNode;
                }
                return self._getNextNode(owner._getOwner());
            };

            wijtreenode.prototype._moveUp = function () {
                var level = this._getCurrentLevel(), prevNode = this._prevNode(this);
                if (!prevNode) {
                    if (level > 0) {
                        this._getOwner()._setFocused(true);
                    }
                } else {
                    this._getNextExpandedNode(prevNode)._setFocused(true);
                }
            };

            wijtreenode.prototype._moveDown = function () {
                var nodes = this.getNodes(), nextNode, owner, pNextNode;
                if (this._expanded && nodes.length > 0) {
                    nodes[0]._setFocused(true);
                } else {
                    nextNode = this._nextNode(this);
                    if (nextNode) {
                        nextNode._setFocused(true);
                    } else {
                        owner = this._getOwner();
                        pNextNode = this._getNextNode(owner);
                        if (pNextNode) {
                            pNextNode._setFocused(true);
                        }
                    }
                }
            };

            wijtreenode.prototype._moveLeft = function () {
                var nextNode = this._getOwner();
                if (this._expanded) {
                    this._setExpanded(false);
                } else if (nextNode !== null && !nextNode.element.is(":" + this.options.treeClass)) {
                    nextNode._setFocused(true);
                }
            };

            wijtreenode.prototype._moveRight = function () {
                if (this._hasChildren) {
                    if (!this._expanded) {
                        this._setExpanded(true);
                    } else {
                        var nextNode = this.getNodes()[0];
                        if (nextNode !== null) {
                            nextNode._setFocused(true);
                        }
                    }
                }
            };

            wijtreenode.prototype._mouseOver = function (event) {
                var self = this, tree = self._tree;
                if (!tree._editMode) {
                    self._mouseOverNode();
                    if (!tree._isDragging) {
                        tree._trigger("nodeMouseOver", event, self);
                    }
                }
            };

            wijtreenode.prototype._mouseOut = function (event) {
                var self = this, tree = self._tree;
                if (!tree._editMode) {
                    self._mouseOutNode();
                    if (!tree._isDragging) {
                        tree._trigger("nodeMouseOut", event, self);
                    }
                }
            };

            wijtreenode.prototype._mouseOverNode = function () {
                if (this.$inner !== null && !this._isOverNode) {
                    this.$inner.addClass(this.options.wijCSS.stateHover);
                    this._isOverNode = true;
                }
            };

            wijtreenode.prototype._mouseOutNode = function () {
                if (this.$inner !== null && this._isOverNode) {
                    this.$inner.removeClass(this.options.wijCSS.stateHover);
                    this._isOverNode = false;
                }
            };

            wijtreenode.prototype._mouseOverHitArea = function (event) {
                var bound, p, self = this, tree = self._tree;
                if (tree.options.expandCollapseHoverUsed) {
                    if (self._hasChildren && !self._isOverHitArea) {
                        bound = self._getBounds(self.element);
                        p = { x: event.pageX, y: event.pageY };
                        if (self._isMouseInsideRect(p, bound)) {
                            self._isOverHitArea = true;
                            self._setExpanded(true);
                        }
                    }
                }
            };

            wijtreenode.prototype._mouseOutHitArea = function (event) {
                var p = { x: event.pageX, y: event.pageY }, bound, self = this, tree = self._tree;
                if (tree.options.expandCollapseHoverUsed) {
                    if (self._hasChildren && !!self._isOverHitArea) {
                        bound = self._getBounds(self.element);
                        if (!self._isMouseInsideRect(p, bound)) {
                            self._isOverHitArea = false;
                            self._setExpanded(false);
                        }
                    } else if (self._getOwner().element.is(":" + self.widgetFullName)) {
                        bound = self._getBounds(self._getOwner().element);
                        if (!self._isMouseInsideRect(p, bound)) {
                            self._getOwner()._isOverHitArea = false;
                            self._getOwner()._setExpanded(false);
                        }
                    }
                }
            };

            /*public methods*/
            /**
            * Destroy the node widget.
            */
            wijtreenode.prototype.destroy = function () {
                var self = this, $nodes, o = self.options, $childnode;
                if (self.element.data("ui-draggable")) {
                    self.element.draggable("destroy");
                }
                if (self.$hitArea) {
                    self.$hitArea.remove();
                }
                if (self.$checkBox) {
                    self.$checkBox.remove();
                }
                if (self.$nodeImage) {
                    self.$nodeImage.remove();
                }
                self._unbindCreateNodesEvent();
                self.$navigateUrl.unwrap().unwrap().removeClass(o.wijCSS.stateDefault).removeClass(o.wijCSS.stateActive).unbind("mousedown");
                $nodes = self.element.find("ul:first").show();
                $nodes.removeClass();

                $nodes.children("li").each(function () {
                    $childnode = $(this);
                    var nodeWidget = getTreeNodeWidget($childnode);
                    if (nodeWidget) {
                        nodeWidget.destroy();
                    }
                });

                self.element.removeData("nodes").removeData("owner").removeData("widgetName").removeClass();

                _super.prototype.destroy.call(this);
            };

            /**
            * The add method adds a node to the node.
            * @example $("#treenode1").wijtreenode("add", "node 1", 1);
            * @param {string|object} node
            * 1.markup html.such as "<li><a>node</a></li>" as a node.
            * 2.wijtreenode element.
            * 3.object options according to the options of wijtreenode.
            * 4. node's text.
            * @param {number} position The position to insert at.
            */
            wijtreenode.prototype.add = function (node, position) {
                var nodeWidget = null, $node, nodes, self = this, cnodes, i, itemDom, originalLength, $link, $checkbox;

                if ($.browser.safari) {
                    itemDom = "<li><a href='{0}'>{1}</a></li>";
                } else {
                    itemDom = "<li><a href='{0}' class='wijmo-wijtree-link'>{1}</a></li>";
                }
                if (typeof node === "string") {
                    $node = $(itemDom.replace(/\{0\}/, "#").replace(/\{1\}/, node));
                    self._createNodeWidget($node);
                    nodeWidget = $node.data($node.data("widgetName"));
                } else if (node.jquery) {
                    if (!node.data("widgetName")) {
                        self._createNodeWidget(node);
                    }
                    nodeWidget = node.data(node.data("widgetName"));
                } else if (node.nodeType) {
                    $node = $(node);
                    self._createNodeWidget($node);
                    nodeWidget = $node.data($node.data("widgetName"));
                } else if ($.isPlainObject(node)) {
                    $node = $(itemDom.replace(/\{0\}/, node.url ? node.url : "#").replace(/\{1\}/, node.text)); //node
                    node.isAddedNodeWithOptions = true;
                    self._createNodeWidget($node, node);
                    nodeWidget = $node.data($node.data("widgetName"));
                }

                if (nodeWidget === null) {
                    return;
                }

                if (!$.browser.safari) {
                    $link = self.element.children(".wijmo-wijtree-node").find("." + localCSS.wijtreeInner + " .wijmo-wijtree-link");
                    if ($link && $link.length > 0) {
                        $link.removeClass("wijmo-wijtree-link");
                    }

                    $checkbox = self.element.children(".wijmo-wijtree-node").find("." + localCSS.wijtreeInner + " .wijmo-checkbox");
                    if ($checkbox && $checkbox.length > 0) {
                        $checkbox.removeClass("wijmo-checkbox");
                    }
                }

                nodes = self.getNodes();
                if (!position || position > nodes.length) {
                    if (position !== 0) {
                        position = nodes.length;
                    }
                }

                if ($.mobile) {
                    nodeWidget.element.find("a").addClass("ui-link");
                }

                cnodes = nodeWidget.getNodes();
                nodeWidget._tree = self._tree;
                for (i = 0; i < cnodes.length; i++) {
                    cnodes[i]._tree = self._tree;
                }
                nodeWidget._setField("owner", self);
                originalLength = nodes.length;
                if (!self.$nodes || !self.$nodes.length) {
                    self.$nodes = $("<ul></ul>").addClass("wijmo-wijtree-list").addClass(self.options.wijCSS.helperReset).addClass("wijmo-wijtree-child");
                    self.element.append(self.$nodes);
                }
                if (originalLength > 0 && originalLength !== position) {
                    if (nodeWidget.element.get(0) !== nodes[position].element.get(0)) {
                        nodeWidget.element.insertBefore(nodes[position].element);
                    }
                } else {
                    self.$nodes.append(nodeWidget.element);
                }
                self.$subnodes = null;
                self._changeCollection(position, nodeWidget);
                self._collectionChanged();
                nodeWidget._initNodeClass();

                if (!$.browser.safari) {
                    self._restoreStyles($link, $checkbox);
                    setTimeout(function () {
                        self._restoreStyles($link, $checkbox);
                    }, 0);
                }
            };

            wijtreenode.prototype._restoreStyles = function ($link, $checkbox) {
                if ($link && $link.length > 0) {
                    $link.addClass("wijmo-wijtree-link");
                }
                if ($checkbox && $checkbox.length > 0) {
                    $checkbox.addClass("wijmo-checkbox");
                }
            };

            /**
            * The remove method removes the indicated node from this node.
            * @example $("#tree").wijtree("remove", 1);
            * @param {string|object} node
            * which node to be removed
            * 1.wijtreenode element.
            * 2.the zero-based index of which node you determined to remove.
            */
            wijtreenode.prototype.remove = function (node) {
                var idx = -1, nodeWidget, self = this, nodes = this.getNodes();
                if (node.jquery) {
                    idx = node.index();
                } else if (typeof node === "number") {
                    idx = node;
                }
                if (idx < 0 || idx >= nodes.length) {
                    return;
                }
                nodeWidget = nodes[idx];
                nodeWidget.element.detach();
                removeARIA(nodeWidget.element);
                self.$subnodes = null;
                self._changeCollection(idx);
                self._collectionChanged();
            };

            /**
            * The getNodes method gets an array that contains the root nodes of the current tree node.
            * @example $("#tree").wijtree("getNodes");
            * @return {Array}
            */
            wijtreenode.prototype.getNodes = function () {
                if (this._hasChildren) {
                    this._createChildNodesPartially(true);
                } else {
                    this._setField("nodes", []);
                }
                return this._getField("nodes");
            };

            wijtreenode.prototype._changeCollection = function (idx, nodeWidget) {
                var nodes = this.getNodes(), ons = this.options.nodes;
                if (nodeWidget) {
                    nodes.splice(idx, 0, nodeWidget);
                    ons.splice(idx, 0, nodeWidget.options);
                } else {
                    nodes.splice(idx, 1);
                    ons.splice(idx, 1);
                }
            };

            /**
            * Sorts the child nodes of the node.
            */
            wijtreenode.prototype.sortNodes = function () {
                var nodes = this.getNodes();
                this._sort();
                $.each(nodes, function (i, childNode) {
                    childNode._index = i;
                    childNode._insertBefore(i);
                });
                this._refreshNodesClass();
            };

            /**
            * Checks or unchecks the node.
            * @param {boolean} value Check or uncheck the node.
            */
            wijtreenode.prototype.check = function (value) {
                this._setOption("checked", value);
            };

            /**
            * Selects or unselects the node.
            * @param {boolean} value select or unselect the node.
            */
            wijtreenode.prototype.select = function (value) {
                this._setOption("selected", value);
            };

            /**
            * Get owner which contains the node.
            */
            wijtreenode.prototype.getOwner = function () {
                var owner = this._getOwner();
                if (owner && owner.element.is("li")) {
                    return owner;
                }
                return null;
            };

            /**
            * Expands the node.
            */
            wijtreenode.prototype.expand = function () {
                this._setOption("expanded", true);
            };

            /**
            * Collapses the node.
            */
            wijtreenode.prototype.collapse = function () {
                this._setOption("expanded", false);
            };

            /*region prvite Methods*/
            wijtreenode.prototype._insertBefore = function (i) {
                var $lis = this.element.parent().children("li");
                if (this.element.index() !== i) {
                    this.element.insertBefore($lis.eq(i));
                }
            };

            wijtreenode.prototype._sort = function () {
                var nodes = this.getNodes();
                if (this._isSorted) {
                    if (!this._isDecsSort) {
                        nodes.sort(this._compare2NodeTextAsc);
                        this._isDecsSort = true;
                    } else {
                        nodes.sort(this._compare2NodeTextDesc);
                        this._isDecsSort = false;
                    }
                } else {
                    nodes.sort(this._compare2NodeTextAsc);
                    this._isSorted = true;
                    this._isDecsSort = true;
                }
            };

            wijtreenode.prototype._compare2NodeTextAsc = function (a, b) {
                if (a !== null && b !== null) {
                    return a._text.localeCompare(b._text);
                }
            };

            wijtreenode.prototype._compare2NodeTextDesc = function (a, b) {
                if (a !== null && b !== null) {
                    return -1 * a._text.localeCompare(b._text);
                }
            };

            wijtreenode.prototype._collectionChanged = function () {
                this._hasChildren = this._hasSubNodes();
                this._initNodeClass();
                //this._refreshNodesClass();
            };

            wijtreenode.prototype._refreshNodesClass = function () {
                var nodes = this.getNodes(), i;
                for (i = 0; i < nodes.length; i++) {
                    nodes[i]._initNodeClass();
                }
            };

            wijtreenode.prototype._setChecked = function (value) {
                var self = this;
                if (self.options.checked === value && self._checkState !== "indeterminate") {
                    return;
                }
                self.options.checked = value;
                self.$nodeBody.attribute("aria-checked", value);
                this._checkItem();
            };

            wijtreenode.prototype._isClosestDisabled = function () {
                var self = this, disabledClass = "." + self._tree.widgetFullName + "-disabled,." + self.widgetFullName + "-disabled";
                if (self.element.closest(disabledClass, self._tree.element).length) {
                    return true;
                }
                return false;
            };

            wijtreenode.prototype._setExpanded = function (value) {
                var self = this, o = self.options;
                if (self._expanded === value) {
                    return;
                }
                if (self._hasChildren || o.hasChildren) {
                    self._expandNode(value);
                }
            };

            wijtreenode.prototype._setFocused = function (value) {
                if (value) {
                    this.$navigateUrl.focus();
                    this._setFocusNode();
                } else {
                    this.$navigateUrl.trigger("focusout");
                }
            };

            wijtreenode.prototype._setFocusNode = function () {
                if (this._tree._focusNode && $.browser.webkit) {
                    this._tree._focusNode.$navigateUrl.trigger("focusout");
                }
                this._focused = true;
                this._tree._focusNode = this;
                this.$inner.addClass(this.options.wijCSS.stateFocus);
            };

            wijtreenode.prototype._setToolTip = function (value) {
                if (value.length) {
                    this.element.attr("title", value);
                } else {
                    this.element.removeAttr("title");
                }
            };

            wijtreenode.prototype._setText = function (value) {
                if (this._text !== value && value.length) {
                    this._text = value;
                    this._changeText(value);
                }
            };

            wijtreenode.prototype._setSelected = function (value) {
                var self = this, o = self.options;
                if (o.selected !== value) {
                    o.selected = value;
                    self.$nodeBody.attribute("aria-selected", value);
                    self._selectNode(value);
                    self._setFocused(value);
                }
            };

            wijtreenode.prototype._setCheckBoxes = function (value) {
                var self = this;
                if (self.$checkBox) {
                    self.$checkBox[value ? 'show' : 'hide']();
                } else if (value) {
                    self._createTreeCheck();
                }

                $.each(self.getNodes(), function (idx, node) {
                    node._setCheckBoxes(value);
                });
            };

            wijtreenode.prototype._setHitArea = function (value) {
                var self = this;
                if (self._hasChildren) {
                    if (value) {
                        self._initNodeClass();
                        if (self.$hitArea) {
                            self.$hitArea.show();
                        }
                    } else {
                        self._expanded = true;
                        self.options.expanded = true;
                        self.$nodeBody.attribute("aria-expanded", true);
                        if (self.$nodes && self.$nodes.length) {
                            self.$nodes.show();
                        }
                        self._initNodeClass();
                        if (self.$hitArea) {
                            self.$hitArea.hide();
                        }
                    }
                }
                $.each(self.getNodes(), function (idx, node) {
                    node._setHitArea(value);
                });
            };

            wijtreenode.prototype._getOwner = function () {
                return this._getField("owner");
            };

            wijtreenode.prototype._getTree = function () {
                var owner = this._getOwner();
                if (owner) {
                    if (owner._tree) {
                        return owner._tree;
                    } else {
                        return owner;
                    }
                }
                return null;
            };

            wijtreenode.prototype._getInitElement = function () {
                var li = $("<li>"), self = this, ul = $("<ul>"), nodes = self.getNodes();
                li.append(self.$navigateUrl.clone());
                if (nodes.length) {
                    li.append(ul);
                    $.each(nodes, function (i, n) {
                        var c = n._getInitElement();
                        ul.append(c);
                    });
                }
                return li;
            };

            wijtreenode.prototype._updateSubNodes = function () {
                var lis, i;

                this.$subnodes = [];
                if (this.$nodes === null || !this.$nodes.length) {
                    return;
                }
                lis = this.$nodes.children("li");
                for (i = 0; i < lis.length; i++) {
                    this.$subnodes.push($(lis[i]));
                }
            };

            wijtreenode.prototype._hasSubNodes = function () {
                if (this.options.nodes && this.options.nodes.length > 0) {
                    return true;
                }
                if (this._isHtmlGenerated()) {
                    return false;
                }
                if (this.$nodes === null) {
                    this.$nodes = this.element.children("ul").eq(0);
                }
                if (this.$nodes.length === 0) {
                    return false;
                }
                if (this.$subnodes === null) {
                    this._updateSubNodes();
                }
                return this.$subnodes.length > 0;
            };

            wijtreenode.prototype._getNodeWidget = function (el) {
                var node = this._getNodeByDom(el), widget;
                if (node.length > 0) {
                    widget = node.data(node.data("widgetName"));
                    return widget;
                }
                return null;
            };

            wijtreenode.prototype._createNodeWidget = function ($li, options) {
                return createNodeWidget($li, options, this, nodeWidgetName, this.options.treeClass);
            };

            wijtreenode.prototype._getNodeByDom = function (el) {
                return $(el).closest(":" + this.widgetFullName);
            };

            wijtreenode.prototype._getCurrentLevel = function () {
                return this.element.parentsUntil(":" + this.options.treeClass).length - 1;
            };

            wijtreenode.prototype._getField = function (key) {
                return this.element.data(key);
            };

            wijtreenode.prototype._setField = function (key, value) {
                this.element.data(key, value);
            };

            wijtreenode.prototype._setAllowDrag = function (value) {
                var self = this;
                if (value) {
                    self.$navigateUrl.one("mousedown." + self.widgetName, self, self._onMouseDown);
                } else if (self.element.data("ui-draggable")) {
                    self.element.draggable("destroy");
                }
            };

            wijtreenode.prototype._isAllowDrag = function () {
                var self = this, no = self.options, to = self._tree.options;
                if (no.allowDrag || (to.allowDrag && no.allowDrag !== false)) {
                    return true;
                } else {
                    return false;
                }
            };

            wijtreenode.prototype._isAllowDrop = function () {
                var self = this, no = self.options, to = self._tree.options;
                if (no.allowDrop || (to.allowDrop && no.allowDrop !== false)) {
                    return true;
                } else {
                    return false;
                }
            };
            return wijtreenode;
        })(wijmo.wijmoWidget);
        _tree.wijtreenode = wijtreenode;

        var wijtreenode_options = (function () {
            function wijtreenode_options() {
                /**
                * wijCSS
                * @ignore
                */
                this.wijCSS = {
                    wijtreeInner: ""
                };
                /** wijMobileCSS
                * @ignore
                */
                this.wijMobileCSS = {
                    header: "ui-header ui-bar-a",
                    content: "ui-body-b",
                    stateDefault: "ui-btn ui-btn-b",
                    stateHover: "ui-btn-down-c",
                    stateActive: "ui-btn-down-b"
                };
                /** @ignore */
                this.treeClass = "wijmo-wijtree";
                /** Selector option for auto self initialization.
                *   This option is internal.
                * @ignore
                */
                this.initSelector = ":jqmData(role='wijtreenode')";
                /** @ignore */
                this.accessKey = "";
                /** The checked option checks the tree node checkbox when it is set to true. It will uncheck the tree node checkbox when set to false.
                */
                this.checked = false;
                /** The collapsedIconClass option sets the collapsed node icon (based on ui-icon) for the specified nodes.
                */
                this.collapsedIconClass = "";
                /** The expanded option will expand the tree node if set to "true." It will collapse the tree node if set to "false.".
                */
                this.expanded = false;
                /** The expandedIconClass option sets the expanded node icon (based on ui-icon) for the specified nodes.
                */
                this.expandedIconClass = "";
                /** The itemIconClass option sets the node icon (based on ui-icon). It will be displayed on both expanded and collapsed nodes when the expandedIconClass and collapsedIconClass options are not specified.
                */
                this.itemIconClass = "";
                /** The navigateUrl option sets the node's navigate url link.
                */
                this.navigateUrl = "";
                /** The selected option selects the specified node when set to true, otherwise it unselects the node.
                */
                this.selected = false;
                /** This option sets the node's text.
                */
                this.text = "";
                /** The toolTip option sets the node's tooltip.
                */
                this.toolTip = "";
                /** The hasChildren option determines whether the specified node has child nodes. It's always used when you're custom adding child nodes, such as in an async load.
                */
                this.hasChildren = false;
                /** The params option sets the parameter needed to pass when the user is custom loading child nodes.
                */
                this.params = {};
                /** Determines the child nodes of this nodes.
                */
                this.nodes = null;
                /** Determines whether to enable node dragging.
                * Default value is null which means whether to enable node dragging depends on the setting of treeview's allowDrag option.
                */
                this.allowDrag = null;
                /** Determines whether to enable node dropping.
                * Default value is null which means whether to enable node dropping depends on the setting of treeview's allowDrop option.
                */
                this.allowDrop = null;
            }
            return wijtreenode_options;
        })();

        var wijtree_options = (function () {
            function wijtree_options() {
                /**
                * wijMobileCSS
                * @ignore
                */
                this.wijMobileCSS = {
                    header: "ui-header ui-bar-a",
                    content: "ui-body-b",
                    stateDefault: "ui-btn ui-btn-b",
                    stateHover: "ui-btn-down-b",
                    stateActive: "ui-btn-down-c"
                };
                /** When the allowDrag option is set to true, the tree nodes can be dragged.
                */
                this.allowDrag = false;
                /** When allowDrop is set to true, one tree node can be dropped within another tree node.
                */
                this.allowDrop = false;
                /** The allowEdit option allows a user to edit the tree nodes at run time.
                */
                this.allowEdit = false;
                /** The allowSorting option allows the tree nodes to be sorted at run time when the user presses the "s" key.
                */
                this.allowSorting = true;
                /** The allowTriState option allows the tree nodes to exhibit triState behavior. This lets the node checkboxes be checked, unchecked, or indeterminate. This option must be used with the showCheckBoxes option.
                */
                this.allowTriState = true;
                /** The autoCheckNodes option allows the sub-nodes to be checked when the parent nodes are checked. To use this option, showCheckboxes must be set to "true."
                */
                this.autoCheckNodes = true;
                /** If this option is set to true,
                * the expanded node will be collapsed if another node is expanded.
                */
                this.autoCollapse = false;
                /** If set to true, the select, click,
                * and check operations are disabled too.
                */
                this.disabled = false;
                /** The expandCollapseHoverUsed option allows the tree to expand or collapse when the mouse hovers over the expand/collapse button.
                */
                this.expandCollapseHoverUsed = false;
                /** The showCheckBoxes option allows the node Check Box to be shown on the tree nodes.
                */
                this.showCheckBoxes = false;
                /** The showExpandCollapse option determines if the tree is displayed in an expanded or collapsed state. If set to "false," then the wijtree widget will be displayed in the expanded state.
                */
                this.showExpandCollapse = true;
                /** The expandAnimation option determines the animation effect, easing, and duration for showing child nodes when the parent node is expanded.
                */
                this.expandAnimation = { effect: "blind", easing: "linear", duration: 200 };
                /** The expandDelay option controls the length of time in milliseconds to delay before the node is expanded.
                */
                this.expandDelay = 0;
                /** The collapseAnimation option determines the animation effect, easing, and duration for hiding child nodes when the parent node is collapsed.
                */
                this.collapseAnimation = { effect: "blind", easing: "linear", duration: 200 };
                /** This option controls the length of time in milliseconds to delay before the node collapses.
                */
                this.collapseDelay = 0;
                /** Customize the jquery-ui-draggable plugin of wijtree.
                */
                this.draggable = null;
                /** Customize the jquery-ui-droppable plugin of wijtree.
                */
                this.droppable = null;
                /** Customizes the helper element to be used to display the position that
                * the node will be inserted to.
                * If a function is specified, it must return a DOMElement.
                * @type {String|Function}
                */
                this.dropVisual = null;
                /** Set the child nodes object array as the datasource of wijtree.
                * @type {Array}
                * @example
                * // Supply a function as an option.
                * $(".selector").wijtree("option","nodes",
                * [{ text:"node1", navigateUrl:"#" }]);
                */
                this.nodes = null;
                /** The nodeBlur event fired when the node loses focus.
                * @event
                * @param {jQuery.Event} e jQuery Event object
                * @param {object} data The node widget that relates to this event.
                */
                this.nodeBlur = null;
                /** The nodeFocus event fired when the node is focused.
                * @event
                * @param {jQuery.Event} e jQuery Event object
                * @param {object} data The node widget that relates to this event.
                */
                this.nodeFocus = null;
                /** The nodeClick event fires when a tree node is clicked.
                * @event
                * @param {jQuery.Event} e jQuery Event object
                * @param {object} data The node widget that relates to this event.
                */
                this.nodeClick = null;
                /** The nodeCheckChanging event fires before a node is checked.
                * You can cancel this event by returning false.
                * @event
                * @param {jQuery.Event} e jQuery Event object
                * @param {object} data The node widget that relates to this event.
                */
                this.nodeCheckChanging = null;
                /** The nodeCheckChanged event fires when a node is checked.
                * @event
                * @param {jQuery.Event} e jQuery Event object
                * @param {object} data The node widget that relates to this event.
                */
                this.nodeCheckChanged = null;
                /** The nodeCollapsed event fires when a tree node is collapsed.
                * @event
                * @param {jQuery.Event} e jQuery Event object
                * @param {object} data The node widget that relates to this event.
                */
                this.nodeCollapsed = null;
                /** The nodeExpanded event handler.
                * A function called when a node is expanded.
                * @event
                * @param {jQuery.Event} e jQuery Event object
                * @param {object} data The node widget that relates to this event.
                */
                this.nodeExpanded = null;
                /** The nodeDragging event handler.A function called
                * when the node is moved during a drag-and-drop operation.
                * @event
                * @param {jQuery.Event} e jQuery Event object
                * @param {object} data The node widget that relates to this event.
                */
                this.nodeDragging = null;
                /** The nodeDragStarted event fires when a user starts to drag a node.
                * @event
                * @param {jQuery.Event} e jQuery Event object
                * @param {object} data The node widget that relates to this event.
                */
                this.nodeDragStarted = null;
                /** The nodeBeforeDropped event handler is called before a draggable node is dropped in another position. If the event handler returns false, the drop action will be prevented.
                * @event
                * @param {jQuery.Event} e jQuery Event object
                * @param {object} data The node widget that relates to this event.
                */
                this.nodeBeforeDropped = null;
                /** The nodeDropped event is called when an acceptable draggable node is dropped over to another position.
                * @event
                * @dataKey {jQuery} sourceParent The source parent of current draggable node before it be dragged, a jQuery object.
                * @dataKey {number} sIndex The Index of dragged node in source parent.
                * @dataKey {jQuery} targetParent The target parent of current draggable node after it be dropped, a jQuery object.
                * @dataKey {number} tIndex The Index of dragged node in target parent.
                * @dataKey {jQuery} draggable The current draggable node.
                * @dataKey {object} offset The current absolute position of the draggable helper.
                * @dataKey {object} position The current position of the draggable helper.
                */
                this.nodeDropped = null;
                /** The nodeMouseOver event fires when a user places the mouse pointer over a node.
                * @event
                * @param {object} event jQuery.Event object.
                * @param {object} data The node widget that relates to this event.
                */
                this.nodeMouseOver = null;
                /** The nodeMouseOut event fires when the user moves the mouse pointer off of a node.
                * @event
                * @param {jQuery.Event} e jQuery Event object
                * @param {object} data The node widget that relates to this event.
                */
                this.nodeMouseOut = null;
                /** The nodeTextChanged event fires when the text of a node changes.
                * @event
                * @param {jQuery.Event} e jQuery Event object
                * @param {object} data The node widget that relates to this event.
                */
                this.nodeTextChanged = null;
                /** The selectedNodeChanged event fires when the selected node changes.
                * @event
                * @param {jQuery.Event} e jQuery Event object
                * @param {object} data The node widget that relates to this event.
                */
                this.selectedNodeChanged = null;
                /** The nodeExpanding event fires before a tree node is expanded.
                * This event can be canceled, if return false
                * @event
                * @param {jQuery.Event} e jQuery Event object
                * @param {object} data The node widget that relates to this event.
                */
                this.nodeExpanding = null;
                /** The nodeCollapsing event fires before a node collapses.
                * This event can be canceled, if return false
                * @event
                * @param {jQuery.Event} e jQuery Event object
                * @param {object} data The node widget that relates to this event.
                */
                this.nodeCollapsing = null;
            }
            return wijtree_options;
        })();

        wijtreenode.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijtreenode_options());
        wijtree.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijtree_options());

        $.wijmo.registerWidget("wijtree", wijtree.prototype);
        $.wijmo.registerWidget("wijtreenode", wijtreenode.prototype);

        

        

        

        

        
    })(wijmo.tree || (wijmo.tree = {}));
    var tree = wijmo.tree;
})(wijmo || (wijmo = {}));

;
/// <reference path="../Base/jquery.wijmo.widget.ts" />
/// <reference path="../External/declarations/swfobject.d.ts" />
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    (function (upload) {
        var $ = jQuery, widgetName = "wijupload";

        var uploadClass = "wijmo-wijupload", uploadFileRowClass = "wijmo-wijupload-fileRow", isUploadFileRow = "." + uploadFileRowClass, uploadFilesListClass = "wijmo-wijupload-filesList", uploadCommandRowClass = "wijmo-wijupload-commandRow", uploadUploadAllClass = "wijmo-wijupload-uploadAll", uploadCancelAllClass = "wijmo-wijupload-cancelAll", uploadButtonContainer = "wijmo-wijupload-buttonContainer", uploadUploadClass = "wijmo-wijupload-upload", isUploadUpload = "." + uploadUploadClass, uploadCancelClass = "wijmo-wijupload-cancel", isUploadCancel = "." + uploadCancelClass, uploadFileClass = "wijmo-wijupload-file", uploadProgressClass = "wijmo-wijupload-progress", uploadLoadingClass = "wijmo-wijupload-loading", wijuploadXhr, wijuploadFrm, _getFileName = function (fileName) {
            if (fileName.indexOf("\\") > -1) {
                fileName = fileName.substring(fileName.lastIndexOf("\\") + 1);
            }
            return fileName;
        }, _getFileNameByInput = function (fileInput) {
            var files = fileInput.files, name = "";

            if (files) {
                $.each(files, function (i, n) {
                    name += _getFileName(n.name) + "; ";
                });
                if (name.length) {
                    name = name.substring(0, name.lastIndexOf(";"));
                }
            } else {
                name = _getFileName(fileInput.value);
            }

            return name;
        }, _getFileSize = function (file) {
            var files = file.files, size = 0;
            if (files && files.length > 0) {
                $.each(files, function (i, n) {
                    if (n.size) {
                        size += n.size;
                    }
                });
            }
            return size;
        };

        wijuploadXhr = function (uploaderId, fileRow, action) {
            var uploader, inputFile = $("input", fileRow), _cancel = function (xhr) {
                if (xhr) {
                    xhr.abort();
                    xhr = null;
                }
            }, _destroy = function (xhr) {
                if (xhr) {
                    xhr = null;
                }
            }, Uploader = function () {
                var self = this, file = inputFile.get(0), files = file.files, xhrs = [], idx = 0, uploadedSize = 0, createXHR = function (name, action) {
                    var xhttpr = new XMLHttpRequest();

                    xhttpr.open("POST", action, true);
                    xhttpr.setRequestHeader("Wijmo-RequestType", "XMLHttpRequest");
                    xhttpr.setRequestHeader("Cache-Control", "no-cache");
                    xhttpr.setRequestHeader("Wijmo-FileName", encodeURI(name));
                    xhttpr.setRequestHeader("Content-Type", "application/octet-stream");

                    xhttpr.upload.onprogress = function (e) {
                        if (e.lengthComputable) {
                            var obj;
                            if ($.isFunction(self.onProgress)) {
                                obj = {
                                    supportProgress: true,
                                    loaded: uploadedSize + e.loaded,
                                    total: _getFileSize(inputFile[0]),
                                    fileName: _getFileName(self.currentFile.name),
                                    fileNameList: _getFileNameByInput(inputFile[0]).split("; ")
                                };
                                self.onProgress(obj);
                            }
                        }
                    };

                    xhttpr.onreadystatechange = function (e) {
                        if (this.readyState === 4) {
                            var response = this.responseText, obj;
                            uploadedSize += files[idx].size;
                            idx++;
                            if (files.length > idx) {
                                _doAjax(files[idx]);
                            } else if ($.isFunction(self.onComplete)) {
                                obj = {
                                    e: e,
                                    response: response,
                                    supportProgress: true
                                };
                                self.onComplete(obj);
                            }
                        }
                    };
                    xhrs.push(xhttpr);
                    return xhttpr;
                }, _doAjax = function (file) {
                    var name = _getFileName(file.name), xhr = createXHR(name, action);
                    self.handleRequest(xhr, file);
                    self.currentFile = file;
                    xhr.send(file);
                };
                self.fileRow = fileRow;
                self.inputFile = inputFile;
                self.upload = function () {
                    _doAjax(files[idx]);
                };
                self.cancel = function () {
                    $.each(xhrs, function (i, xhr) {
                        _cancel(xhr);
                    });
                    if ($.isFunction(self.onCancel)) {
                        self.onCancel();
                    }
                };
                self.destroy = function () {
                    $.each(xhrs, function (i, xhr) {
                        _destroy(xhr);
                    });
                };
                self.updateAction = function (act) {
                    action = act;
                };
                self.handleRequest = null;
                self.onCancel = null;
                self.onComplete = null;
                self.onProgress = null;
            };
            uploader = new Uploader();
            return uploader;
        };

        wijuploadFrm = function (uploaderId, fileRow, action) {
            var uploader, inputFile = $("input", fileRow), inputFileId = inputFile.attr("id"), formId = "wijUploadForm_" + uploaderId, form = $("#" + formId), iframeId = "wijUploadIfm_" + inputFileId, isFirstLoad = true, iframe = $("<iframe id=\"" + iframeId + "\" name=\"" + iframeId + "\">"), _upload = function (ifm, iptFile) {
                form.empty();
                form.attr("target", ifm.attr("name"));
                if (iptFile) {
                    iptFile.parent().append(iptFile.clone());
                    form.append(iptFile);
                }
                form.submit();
            }, _cancel = function (ifm) {
                // to cancel request set src to something else
                // we use src="javascript:false;" because it doesn't
                // trigger ie6 prompt on https
                ifm.attr("src", "javascript".concat(":false;"));
            }, _destroy = function (ifm, removeForm) {
                if (removeForm && form) {
                    form.remove();
                    form = null;
                }
                if (ifm) {
                    ifm.remove();
                    ifm = null;
                }
            }, Uploader;

            if (form.length === 0) {
                form = $("<form method=\"post\" enctype=\"multipart/form-data\"></form>");
                form.attr("action", action).attr("id", formId).attr("name", formId).appendTo("body");
            }
            iframe.css("position", "absolute").css("top", "-1000px").css("left", "-1000px");
            iframe.appendTo("body");

            Uploader = function () {
                var self = this;
                self.fileRow = fileRow;
                self.iframe = iframe;
                self.inputFile = inputFile;
                self.upload = function () {
                    var obj;
                    _upload(iframe, inputFile);
                    if ($.isFunction(self.onProgress)) {
                        obj = {
                            supportProgress: false,
                            loaded: 1,
                            total: 1
                        };
                        self.onProgress(obj);
                    }
                };
                self.doPost = function () {
                    _upload(iframe);
                };
                self.cancel = function () {
                    _cancel(iframe);
                    if ($.isFunction(self.onCancel)) {
                        self.onCancel();
                    }
                };
                self.updateAction = function (act) {
                    action = act;
                    form.attr("action", act);
                };
                self.destroy = function (removeForm) {
                    _destroy(iframe, removeForm);
                };
                self.onCancel = null;
                self.onComplete = null;
                self.onProgress = null;

                iframe.bind("load", function (e) {
                    if (!$.browser.safari) {
                        if (isFirstLoad && !self.autoSubmit) {
                            isFirstLoad = false;
                            return;
                        }
                    }
                    if (iframe.attr("src") === "javascript".concat(":false;")) {
                        return;
                    }
                    var target = e.target, response, doc, obj;
                    try  {
                        doc = target.contentDocument ? target.contentDocument : window.frames[0].document;

                        //if (doc.readyState && doc.readyState !== "complete") {
                        //	return;
                        //}
                        if (doc.XMLDocument) {
                            response = doc.XMLDocument;
                        } else if (doc.body) {
                            response = doc.body.innerHTML;
                        } else {
                            response = doc;
                        }
                        if ($.isFunction(self.onComplete)) {
                            obj = {
                                e: e,
                                response: response,
                                supportProgress: false
                            };
                            self.onComplete(obj);
                        }
                    } catch (ex) {
                        response = "";
                    } finally {
                        //iframe.unbind("load");
                    }
                });
            };
            uploader = new Uploader();
            return uploader;
        };

        /** @widget */
        var wijupload = (function (_super) {
            __extends(wijupload, _super);
            function wijupload() {
                _super.apply(this, arguments);
            }
            wijupload.prototype._swfAppendAddtionalData = function (swfupload) {
                swfupload.queueData = {
                    files: {},
                    filesSelected: 0,
                    filesQueued: 0,
                    filesReplaced: 0,
                    filesCancelled: 0,
                    filesErrored: 0,
                    uploadsSuccessful: 0,
                    uploadsErrored: 0,
                    averageSpeed: 0,
                    queueLength: 0,
                    queueSize: 0,
                    uploadSize: 0,
                    queueBytesUploaded: 0,
                    uploadQueue: [],
                    errorMsg: ''
                };
                swfupload.widget = this;
            };

            wijupload.prototype._swfGetHandlers = function () {
                var widget = this, el = widget.element;
                return {
                    onSelect: function (file) {
                        var swfupload = this;
                        var queuedFile = {};
                        if (widget._trigger("change", null, file) === false) {
                            // NOTE: cancelUpload() only dequeue one file, not clear the whole queue.
                            swfupload.cancelUpload(file.id);
                            return false;
                        }
                        widget._createFileRow(file);
                        widget._setAddBtnState();
                        this.queueData.queueSize += file.size;
                        this.queueData.files[file.id] = file;
                    },
                    onSelectError: function (file, errorCode) {
                        if (errorCode == SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT) {
                            alert("File size exceeds the limitation!");
                        } else if (errorCode == SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED) {
                            alert("Too many files!");
                        }
                    },
                    onDialogOpen: function () {
                        //prepare
                        this.queueData.filesReplaced = 0;
                        this.queueData.filesCancelled = 0;
                    },
                    onDialogClose: function (filesSelected, filesQueued, queueLength) {
                        // start upload
                        var settings = this.settings;

                        // Update the queue information
                        this.queueData.filesErrored = filesSelected - filesQueued;
                        this.queueData.filesSelected = filesSelected;
                        this.queueData.filesQueued = filesQueued - this.queueData.filesCancelled;
                        this.queueData.queueLength = queueLength;

                        widget.isStartUpload = false;

                        // Call the user-defined event handler
                        if (widget.options.autoSubmit) {
                            widget.uploadAll = true;
                            widget._swfUploadFile();
                        }
                        if (settings.onDialogClose)
                            settings.onDialogClose.call(this, this.queueData);
                    },
                    onUploadStart: function (file) {
                        this.bytesLoaded = 0;
                        if (this.queueData.uploadQueue.length == 0) {
                            this.queueData.uploadSize = file.size;
                        }

                        if (!widget.isStartUpload && widget.uploadAll) {
                            if (widget._trigger("totalUpload", null, null) === false) {
                                this.cancelUpload();
                                return false;
                            }
                            widget.isStartUpload = true;
                        }

                        if (widget._trigger("upload", null, file) === false) {
                            this.cancelUpload(file.id);
                            return false;
                        }
                    },
                    onUploadProgress: function (file, fileBytesLoaded, fileTotalBytes) {
                        var fileRow = $("#" + file.id, el), loaded, total, percentage = Math.round(fileBytesLoaded / fileTotalBytes * 100), progressSpan = $("." + uploadProgressClass, fileRow), data = {
                            sender: file.name,
                            loaded: fileBytesLoaded,
                            total: fileTotalBytes
                        }, queue = this.queueData;
                        progressSpan.html(percentage + "%");
                        widget._trigger("progress", null, data);

                        loaded = queue.queueBytesUploaded + fileBytesLoaded;
                        total = queue.queueSize;

                        widget._updateSwfProgress(loaded, total);
                        widget._trigger("totalProgress", null, {
                            loaded: loaded,
                            total: total
                        });
                    },
                    onUploadError: function (file, errorCode, errorMsg) {
                        // Load the swfupload settings
                        var settings = this.settings, fileRow = $("#" + file.id, el), progressSpan = $("." + uploadProgressClass, fileRow);

                        // Set the error string
                        var errorString = 'Error';
                        switch (errorCode) {
                            case SWFUpload.UPLOAD_ERROR.HTTP_ERROR:
                                errorString = 'HTTP Error (' + errorMsg + ')';
                                break;
                            case SWFUpload.UPLOAD_ERROR.MISSING_UPLOAD_URL:
                                errorString = 'Missing Upload URL';
                                break;
                            case SWFUpload.UPLOAD_ERROR.IO_ERROR:
                                errorString = 'IO Error';
                                break;
                            case SWFUpload.UPLOAD_ERROR.SECURITY_ERROR:
                                errorString = 'Security Error';
                                break;
                            case SWFUpload.UPLOAD_ERROR.UPLOAD_LIMIT_EXCEEDED:
                                alert('The upload limit has been reached (' + errorMsg + ').');
                                errorString = 'Exceeds Upload Limit';
                                break;
                            case SWFUpload.UPLOAD_ERROR.UPLOAD_FAILED:
                                errorString = 'Failed';
                                break;
                            case SWFUpload.UPLOAD_ERROR.SPECIFIED_FILE_ID_NOT_FOUND:
                                break;
                            case SWFUpload.UPLOAD_ERROR.FILE_VALIDATION_FAILED:
                                errorString = 'Validation Error';
                                break;
                            case SWFUpload.UPLOAD_ERROR.FILE_CANCELLED:
                                errorString = 'Cancelled';
                                this.queueData.queueSize -= file.size;
                                this.queueData.queueLength -= 1;
                                if (file.status == SWFUpload.FILE_STATUS.IN_PROGRESS || $.inArray(file.id, this.queueData.uploadQueue) >= 0) {
                                    this.queueData.uploadSize -= file.size;
                                }

                                // Trigger the onCancel event
                                if (settings.onCancel)
                                    settings.onCancel.call(this, file);
                                delete this.queueData.files[file.id];
                                break;
                            case SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED:
                                errorString = 'Stopped';
                                break;
                        }

                        progressSpan.text(errorString);
                        var stats = this.getStats();
                        this.queueData.uploadsErrored = stats.upload_errors;
                    },
                    onUploadSuccess: function (file, data, response) {
                        var stats = this.getStats();
                        this.queueData.uploadsSuccessful = stats.successful_uploads;
                        this.queueData.queueBytesUploaded += file.size;
                        this.queueData.response = response;

                        var fileRow = $("#" + file.id, el), self = this;
                        self.queueData.queueLength -= 1;

                        fileRow.fadeOut(1500, function () {
                            fileRow.remove();
                            if (widget.options.showUploadedFiles) {
                                widget._createUploadedFiles(file.name);
                            }
                            if (!self.queueData.queueLength) {
                                widget.commandRow.hide();
                            }
                            widget._setAddBtnState();
                        });

                        widget._trigger("complete", null, { response: response });
                    },
                    onUploadComplete: function (file, data, response) {
                        var self = this;

                        if (!self.queueData.queueLength && widget.uploadAll) {
                            widget._cleanSwfProgress();
                            widget._trigger("totalComplete", null, self.queueData);
                        }
                        if (widget.uploadAll) {
                            widget._swfUploadFile();
                        }
                    }
                };
            };
            wijupload.prototype._cleanSwfProgress = function () {
            };
            wijupload.prototype._updateSwfProgress = function (loaded, total) {
            };

            wijupload.prototype._initSwfUploadOptions = function (w, h) {
                var self = this, el = self.element, settings, handlers = self._swfGetHandlers(), o = self.options, swfOptions = self.options.swfUploadOptions, id = el.attr("id"), inputId = id + "_SWFUpload";

                $("<input type='file' id='" + inputId + "'>").appendTo(el);

                //uploadify
                settings = $.extend({
                    id: inputId,
                    swf: 'SWFUpload.swf',
                    // Options
                    auto: false,
                    buttonClass: '',
                    buttonCursor: 'hand',
                    buttonImage: null,
                    checkExisting: false,
                    debug: false,
                    fileObjName: 'Filedata',
                    fileSizeLimit: o.maximumFileSize ? o.maximumFileSize : 0,
                    fileTypeDesc: 'All Files',
                    fileTypeExts: o.accept ? o.accept : '*.*',
                    height: h,
                    itemTemplate: false,
                    method: 'post',
                    multi: o.multiple,
                    formData: {},
                    preventCaching: true,
                    progressData: 'percentage',
                    queueID: false,
                    queueSizeLimit: o.maximumFiles ? o.maximumFiles : 999,
                    removeCompleted: true,
                    removeTimeout: 3,
                    requeueErrors: false,
                    successTimeout: 30,
                    uploadLimit: 0,
                    width: w,
                    uploader: o.action,
                    // Events
                    overrideEvents: []
                }, swfOptions);

                return {
                    assume_success_timeout: settings.successTimeout,
                    button_placeholder_id: settings.id,
                    button_width: settings.width,
                    button_height: settings.height,
                    button_text: null,
                    button_text_style: null,
                    button_text_top_padding: 0,
                    button_text_left_padding: 0,
                    button_action: (o.multiple ? SWFUpload.BUTTON_ACTION.SELECT_FILES : SWFUpload.BUTTON_ACTION.SELECT_FILE),
                    button_disabled: false,
                    button_cursor: (settings.buttonCursor == 'arrow' ? SWFUpload.CURSOR.ARROW : SWFUpload.CURSOR.HAND),
                    button_window_mode: SWFUpload.WINDOW_MODE.TRANSPARENT,
                    debug: settings.debug,
                    requeue_on_error: settings.requeueErrors,
                    file_post_name: settings.fileObjName,
                    file_size_limit: settings.fileSizeLimit,
                    file_types: settings.fileTypeExts,
                    file_types_description: settings.fileTypeDesc,
                    file_queue_limit: settings.queueSizeLimit,
                    file_upload_limit: settings.uploadLimit,
                    flash_url: settings.swf,
                    prevent_swf_caching: settings.preventCaching,
                    post_params: settings.formData,
                    upload_url: settings.uploader,
                    use_query_string: (settings.method == 'get'),
                    // Event Handlers
                    file_dialog_complete_handler: handlers.onDialogClose,
                    file_dialog_start_handler: handlers.onDialogOpen,
                    file_queued_handler: handlers.onSelect,
                    file_queue_error_handler: handlers.onSelectError,
                    swfupload_loaded_handler: settings.onSWFReady,
                    upload_complete_handler: handlers.onUploadComplete,
                    upload_error_handler: handlers.onUploadError,
                    upload_progress_handler: handlers.onUploadProgress,
                    upload_start_handler: handlers.onUploadStart,
                    upload_success_handler: handlers.onUploadSuccess
                };
            };

            wijupload.prototype._createSWFUpload = function () {
                var self = this, el = self.element, btn = self.addBtn, swfOptions, settings = self.options.swfUploadOptions, swfupload, w = btn.width(), h = btn.height();

                var playerVersion = swfobject.getFlashPlayerVersion();
                var flashInstalled = (playerVersion.major >= 9);

                if (flashInstalled) {
                    swfOptions = self._initSwfUploadOptions(w, h);
                    swfupload = new SWFUpload(swfOptions);

                    // Add the SWFUpload object to the elements data object
                    self.swfupload = swfupload;

                    $('#' + swfupload.movieName).css({
                        'position': 'absolute',
                        'z-index': 100,
                        'top': 0,
                        'left': 0,
                        'width': w,
                        'height': h
                    });

                    self._swfAppendAddtionalData(swfupload);
                } else {
                    alert("Please install flash player.");
                    if (settings && settings.onFallback)
                        settings.onFallback.call();
                }
            };

            wijupload.prototype._create = function () {
                var self = this, o = self.options, id = new Date().getTime(), useXhr = self.supportXhr();

                // enable touch support:
                if (window.wijmoApplyWijTouchUtilEvents) {
                    $ = window.wijmoApplyWijTouchUtilEvents($);
                }

                self.filesLen = 0;
                self.totalUploadFiles = 0;
                self.useXhr = useXhr;
                self.id = id;

                self._createContainers();
                self._createUploadButton();
                if ((o.enableSWFUploadOnIE && $.browser.msie) || o.enableSWFUpload) {
                    self._createSWFUpload();
                } else {
                    self._createFileInput();
                }

                self._bindEvents();

                if (self.element.is(":hidden") && self.element.wijAddVisibilityObserver) {
                    self.element.wijAddVisibilityObserver(function () {
                        self._applyInputPosition();
                        if (self.element.wijRemoveVisibilityObserver) {
                            self.element.wijRemoveVisibilityObserver();
                        }
                    }, "wijupload");
                }

                _super.prototype._create.call(this);
            };

            wijupload.prototype._setOption = function (key, value) {
                var self = this;

                _super.prototype._setOption.call(this, key, value);

                if (key === "accept") {
                    if (self.input) {
                        self.input.attr("accept", value);
                    }
                }
            };

            wijupload.prototype._innerDisable = function () {
                _super.prototype._innerDisable.call(this);
                this._handleDisabledOption(true, this.upload);
            };

            wijupload.prototype._innerEnable = function () {
                _super.prototype._innerEnable.call(this);
                this._handleDisabledOption(false, this.upload);
            };

            wijupload.prototype._handleDisabledOption = function (disabled, ele) {
                var self = this;

                if (disabled) {
                    if (!self.disabledDiv) {
                        self.disabledDiv = self._createDisabledDiv(ele);
                    }
                    self.disabledDiv.appendTo("body");
                } else {
                    if (self.disabledDiv) {
                        self.disabledDiv.remove();
                        self.disabledDiv = null;
                    }
                }
            };

            wijupload.prototype._createDisabledDiv = function (outerEle) {
                var self = this, div, ele = outerEle ? outerEle : self.upload, eleOffset = ele.offset(), disabledWidth = ele.outerWidth(), disabledHeight = ele.outerHeight();

                div = $("<div></div>").addClass(self.options.wijCSS.stateDisabled).css({
                    "z-index": "99999",
                    position: "absolute",
                    width: disabledWidth,
                    height: disabledHeight,
                    left: eleOffset.left,
                    top: eleOffset.top
                });

                if ($.browser.msie) {
                    div.css("background-color", "white");
                    if (parseInt($.browser.version) >= 9) {
                        div.css("opacity", "0.1");
                    }
                }
                return div;
            };

            /**
            * Removes the wijupload functionality completely.This will return the element back to its pre - init state.
            * @example $(" selector ").wijupload("destroy");
            */
            wijupload.prototype.destroy = function () {
                var self = this;
                self.upload.removeClass(uploadClass);
                self.upload.undelegate(self.widgetName).undelegate("." + self.widgetName);
                if (self.input) {
                    self.input.remove();
                }
                if (self.addBtn) {
                    self.addBtn.remove();
                }
                if (self.filesList) {
                    self.filesList.remove();
                }
                if (self.commandRow) {
                    self.commandRow.remove();
                }

                if (self.isCreateByInput === true) {
                    self.element.css({
                        display: ""
                    }).unwrap();
                }

                if (self.uploaders) {
                    $.each(self.uploaders, function (idx, uploader) {
                        if (uploader.destroy) {
                            uploader.destroy(true);
                        }
                        uploader = null;
                    });
                    self.uploaders = null;
                }

                if (self.swfupload) {
                    if (self.swfupload.destroy) {
                        self.swfupload.destroy();
                    }
                    self.swfupload = null;
                }

                //Add for support disabled option at 2011/7/8
                if (self.disabledDiv) {
                    self.disabledDiv.remove();
                    self.disabledDiv = null;
                }
                _super.prototype.destroy.call(this);
                //end for disabled option
            };

            /**
            * Returns the.wijmo - wijupload element.
            * @example $(" selector ").wijupload("widget");
            */
            wijupload.prototype.widget = function () {
                return this.upload;
            };

            /** @ignore */
            wijupload.prototype.supportXhr = function () {
                var useXhr = false;
                if (typeof (new XMLHttpRequest().upload) === "undefined") {
                    useXhr = false;
                } else {
                    useXhr = true;
                }
                return useXhr;
            };

            wijupload.prototype._createContainers = function () {
                var self = this, filesList, commandRow, el = self.element;

                if (el.is(":input") && el.attr("type") === "file") {
                    self.isCreateByInput = true;
                    self.maxDisplay = (el.attr("multiple") || self.options.multiple) ? 0 : 1;

                    self.upload = el.css({
                        display: "none"
                    }).wrap("<div>").parent();
                } else if (self.element.is("div")) {
                    self.maxDisplay = self.options.multiple ? 0 : 1;
                    self.upload = el;
                } else {
                    throw 'The initial markup must be "DIV", "INPUT[type=file]"';
                }

                self.upload.addClass(uploadClass);

                filesList = $("<ul>").addClass(uploadFilesListClass).appendTo(self.upload);
                commandRow = $("<div>").addClass(uploadCommandRowClass).appendTo(self.upload);
                self.filesList = filesList;
                commandRow.hide();
                self.commandRow = commandRow;
                self._createCommandRow(commandRow);
            };

            wijupload.prototype._createCommandRow = function (commandRow) {
                var self = this, o = self.options, uploadAllBtn = $("<a>").attr("href", "#").text("uploadAll").addClass(uploadUploadAllClass).button({
                    icons: {
                        primary: o.wijCSS.iconCircleArrowN
                    },
                    label: self._getLocalization("uploadAll", "Upload All")
                }).button("widget").addClass(o.wijCSS.stateDefault), cancelAllBtn = $("<a>").attr("href", "#").text("cancelAll").addClass(uploadCancelAllClass).button({
                    icons: {
                        primary: o.wijCSS.iconCancel
                    },
                    label: self._getLocalization("cancelAll", "Cancel All")
                }).button("widget").addClass(o.wijCSS.stateDefault);
                commandRow.append(uploadAllBtn).append(cancelAllBtn);
            };

            wijupload.prototype._getLocalization = function (key, defaultVal) {
                var lo = this.options.localization;
                return (lo && lo[key]) || defaultVal;
            };

            wijupload.prototype._createUploadButton = function () {
                var self = this, o = self.options, addBtn = $("<a>").attr("href", "javascript:void(0);").button({
                    label: self._getLocalization("uploadFiles", "Upload files")
                }).button("widget").addClass(o.wijCSS.stateDefault);

                addBtn.mousemove(function (e) {
                    var disabled = addBtn.data("ui-button").options.disabled;
                    if (self.input) {
                        var pageX = e.pageX, pageY = e.pageY;

                        if (!disabled) {
                            self.input.offset({
                                left: pageX + 10 - self.input.width(),
                                top: pageY + 10 - self.input.height()
                            });
                        }
                    }
                });
                self.addBtn = addBtn;
                self.upload.prepend(addBtn);
            };

            wijupload.prototype._applyInputPosition = function () {
                var self = this, addBtn = self.addBtn, addBtnOffset = addBtn.offset(), fileInput = self.cuurentInput;

                fileInput.offset({
                    left: addBtnOffset.left + addBtn.width() - fileInput.width(),
                    top: addBtnOffset.top
                }).height(addBtn.height());
            };

            wijupload.prototype._createFileInput = function () {
                var self = this, addBtn = self.addBtn, addBtnOffset = addBtn.offset(), accept = self.element.attr("accept") || self.options.accept, id = "wijUpload_" + self.id + "_input" + self.filesLen, fileInput = $("<input>").attr("type", "file").prependTo(self.upload), maxFiles = self.options.maximumFiles || self.maxDisplay;

                if (maxFiles !== 1 && self.maxDisplay === 0) {
                    fileInput.attr("multiple", "multiple");
                }

                if (accept) {
                    fileInput.attr("accept", accept);
                }

                fileInput.attribute("aria-label", "wijupload");

                self.cuurentInput = fileInput;
                self.filesLen++;
                fileInput.attr("id", id).attr("name", id).css("position", "absolute").offset({
                    left: addBtnOffset.left + addBtn.width() - fileInput.width(),
                    top: addBtnOffset.top
                }).css("z-index", "9999").css("opacity", 0).height(addBtn.height()).css("cursor", "pointer");

                self.input = fileInput;
                fileInput.bind("change", function (e) {
                    var fileRow, uploadBtn;
                    if (self._trigger("change", e, $(this)) === false) {
                        return false;
                    }
                    self._createFileInput();
                    fileRow = self._createFileRow($(this));
                    self._setAddBtnState();
                    if (self.options.autoSubmit) {
                        uploadBtn = $(isUploadUpload, fileRow);
                        if (uploadBtn) {
                            uploadBtn.click();
                        }
                    }
                    fileInput.unbind("change");
                });
                self.uploadAll = false;
            };

            wijupload.prototype._createUploadedFiles = function (name) {
            };

            wijupload.prototype._setAddBtnState = function () {
                var self = this, o = self.options, maxFiles = self.options.maximumFiles || self.maxDisplay, addBtn = self.addBtn, files;
                if (!maxFiles) {
                    return;
                }
                if (!addBtn) {
                    return;
                }
                if (!self.maskDiv) {
                    self.maskDiv = $("<div></div>").css("position", "absolute").css("z-index", "9999").width(addBtn.outerWidth()).height(addBtn.outerHeight()).appendTo(self.upload).offset(addBtn.offset());
                }
                files = $("li", self.filesList);
                if (files.length >= maxFiles) {
                    addBtn.button({ disabled: true });
                    self.maskDiv.show();
                    if ((o.enableSWFUploadOnIE || o.enableSWFUpload) && $.browser.msie && parseInt($.browser.version) <= 10) {
                        self.maskDiv.bgiframe({ opacity: true, conditional: true });
                    }
                    if (self.input) {
                        self.input.css("left", "-1000px");
                    }
                } else {
                    addBtn.button({ disabled: false });
                    self.maskDiv.hide();
                    if ((o.enableSWFUploadOnIE || o.enableSWFUpload) && $.browser.msie && parseInt($.browser.version) <= 10) {
                        self.maskDiv.find("iframe.bgiframe").remove();
                    }
                }
            };

            wijupload.prototype._createFileRow = function (uploadFile) {
                var self = this, o = self.options, fileRow = $("<li>"), fileName = '', file, progress, fileRows, buttonContainer = $("<span>").addClass(uploadButtonContainer), uploadBtn = $("<a>").attr("href", "#").text("upload").addClass(uploadUploadClass).button({
                    text: false,
                    icons: {
                        primary: o.wijCSS.iconCircleArrowN
                    },
                    label: self._getLocalization("upload", "upload")
                }).button("widget").addClass(o.wijCSS.stateDefault), cancelBtn = $("<a>").attr("href", "#").text("cancel").addClass(uploadCancelClass).button({
                    text: false,
                    icons: {
                        primary: o.wijCSS.iconCancel
                    },
                    label: self._getLocalization("cancel", "cancel")
                }).button("widget").addClass(o.wijCSS.stateDefault);
                fileRow.addClass(uploadFileRowClass).addClass(o.wijCSS.content).addClass(o.wijCSS.cornerAll);

                if ((o.enableSWFUploadOnIE && $.browser.msie) || o.enableSWFUpload) {
                    fileName = uploadFile.name;
                    fileRow.attr("id", uploadFile.id).data("file", uploadFile);
                } else {
                    fileRow.append(uploadFile);
                    uploadFile.hide();
                    fileName = _getFileNameByInput(uploadFile[0]);
                }

                file = $("<span>" + fileName + "</span>").addClass(uploadFileClass).addClass(o.wijCSS.stateHighlight).addClass(o.wijCSS.cornerAll);
                fileRow.append(file);
                fileRow.append(buttonContainer);
                progress = $("<span />").addClass(uploadProgressClass);
                buttonContainer.append(progress);
                buttonContainer.append(uploadBtn).append(cancelBtn);
                fileRow.appendTo(self.filesList);

                fileRows = $(isUploadFileRow, self.upload);
                if (fileRows.length) {
                    self.commandRow.show();
                    if ((!o.enableSWFUploadOnIE || !$.browser.msie) && !o.enableSWFUpload) {
                        self._createUploader(fileRow);
                    }
                    self._resetProgressAll();
                }
                return fileRow;
            };

            wijupload.prototype._createUploader = function (fileRow) {
                var self = this, inputFile = $("input", fileRow), action = self.options.action, hr = self.options.handleRequest, uploader;
                if (self.useXhr) {
                    uploader = wijuploadXhr(self.id, fileRow, action);
                    uploader.handleRequest = function (xhr, file) {
                        if ($.isFunction(hr)) {
                            hr.call(self, xhr, file);
                        }
                    };
                } else {
                    uploader = wijuploadFrm(self.id, fileRow, action);
                }
                uploader.onCancel = function () {
                    var t = this;
                    self._trigger("cancel", null, t.inputFile);

                    //self.totalUploadFiles--;
                    if (self.totalUploadFiles === 0 && self.uploadAll) {
                        self._trigger("totalComplete");
                    }
                };
                if (self._wijUpload()) {
                    uploader.onProgress = function (obj) {
                        var progressSpan = $("." + uploadProgressClass, this.fileRow), data = {
                            sender: obj.fileName,
                            loaded: obj.loaded,
                            total: obj.total,
                            fileNameList: undefined
                        }, id = this.inputFile.attr("id");
                        if (obj.supportProgress) {
                            progressSpan.html(Math.round(1000 * obj.loaded / obj.total) / 10 + "%");
                            if (obj.fileNameList) {
                                data.fileNameList = obj.fileNameList;
                            }
                            self._trigger("progress", null, data);
                            self._progressTotal(id, obj.loaded);
                        } else {
                            progressSpan.addClass(uploadLoadingClass);
                        }
                    };
                    uploader.onComplete = function (obj) {
                        var t = this, id = t.inputFile.attr("id"), uploader = self.uploaders[id], fileSize = _getFileSize(t.inputFile[0]), progressSpan = $("." + uploadProgressClass, t.fileRow);

                        // xhr = obj.e.currentTarget;
                        // if (xhr.status != 200) {
                        //     throw xhr;
                        // }
                        self._trigger("complete", obj.e, $.extend(true, t.inputFile, obj));
                        progressSpan.removeClass(uploadLoadingClass);
                        progressSpan.html("100%");
                        self._removeFileRow(t.fileRow, uploader, true);
                        self._progressTotal(id, fileSize);
                        self.totalUploadFiles--;
                        if (self.totalUploadFiles === 0 && (self.uploadAll || self.options.autoSubmit)) {
                            self._trigger("totalComplete", obj.e, obj);
                        }
                    };
                }
                if (typeof (self.uploaders) === "undefined") {
                    self.uploaders = {};
                }
                self.uploaders[inputFile.attr("id")] = uploader;
            };

            wijupload.prototype._progressTotal = function (fileName, loadedSize) {
                var self = this, progressAll = self.progressAll, loaded, total;
                if (!self.uploadAll) {
                    return;
                }
                if (progressAll && progressAll.loadedSize) {
                    progressAll.loadedSize[fileName] = loadedSize;
                    loaded = self._getLoadedSize(progressAll.loadedSize);
                    total = progressAll.totalSize;
                }
                self._trigger("totalProgress", null, {
                    loaded: loaded,
                    total: total
                });
            };

            wijupload.prototype._getLoadedSize = function (loadedSize) {
                var loaded = 0;
                $.each(loadedSize, function (key, value) {
                    loaded += value;
                });
                return loaded;
            };

            wijupload.prototype._getTotalSize = function () {
                var self = this, total = 0;
                if (self.uploaders) {
                    $.each(self.uploaders, function (key, uploader) {
                        total += _getFileSize(uploader.inputFile[0]);
                    });
                }
                return total;
            };

            wijupload.prototype._resetProgressAll = function () {
                this.progressAll = {
                    totalSize: 0,
                    loadedSize: {}
                };
            };

            wijupload.prototype._wijUpload = function () {
                //return this.widgetName === "wijupload";
                return true;
            };

            wijupload.prototype._wijcancel = function (fileInput) {
            };

            wijupload.prototype._upload = function (fileRow, isUpload) {
            };

            wijupload.prototype._swfUploadFile = function (fileName) {
                this.swfupload.startUpload(fileName);
            };

            wijupload.prototype._bindEvents = function () {
                var self = this, o = self.options, progressAll = self.progressAll;
                self.upload.delegate(isUploadCancel, "click." + self.widgetName, function (e) {
                    var cancelBtn = $(this), fileRow = cancelBtn.parents(isUploadFileRow), fileInput, uploader;

                    e.preventDefault();
                    if ((o.enableSWFUploadOnIE && $.browser.msie) || o.enableSWFUpload) {
                        var file = fileRow.data("file");

                        //self.swfupload.queueData.queueSize -= file.size;
                        //self.swfupload.queueData.queueLength -= 1;
                        self.swfupload.cancelUpload(file.id);
                        fileRow.fadeOut(1500, function () {
                            fileRow.remove();
                            self._setAddBtnState();
                            if (self.swfupload.queueData.queueLength == 0) {
                                self.commandRow.hide();
                            }
                        });
                    } else {
                        fileInput = $("input", fileRow[0]);
                        uploader = self.uploaders[fileInput.attr("id")];
                        self._wijcancel(fileInput);
                        if (self._wijUpload() && uploader) {
                            uploader.cancel();
                        }

                        if (progressAll) {
                            progressAll.totalSize -= _getFileSize(fileInput[0]);
                            if (progressAll.loadedSize[fileInput.val()]) {
                                delete progressAll.loadedSize[fileInput.val()];
                            }
                        }
                        self._removeFileRow(fileRow, uploader, false);
                    }
                });
                self.upload.delegate(isUploadUpload, "click." + self.widgetName, function (e) {
                    var uploadBtn = $(this), fileRow = uploadBtn.parents(isUploadFileRow), fileInput, uploader;

                    uploadBtn.button({ "disabled": true });
                    e.preventDefault();
                    if ((o.enableSWFUploadOnIE && $.browser.msie) || o.enableSWFUpload) {
                        var file = fileRow.data("file");
                        self.uploadAll = false;

                        if (self._wijUpload()) {
                            self._swfUploadFile(file.id);
                        } else {
                            self._upload(file.id, true);
                        }
                        self._removeFileRowSetButtonStates();
                    } else {
                        fileInput = $("input", fileRow[0]);
                        uploader = self.uploaders[fileInput.attr("id")];
                        if (self._trigger("upload", e, fileInput) === false) {
                            return false;
                        }
                        if (self.options.autoSubmit) {
                            //when autoSubmit set to "true", will trigger "totalUpload" immediately.
                            //self.uploadAll = true; //fixed bug 23877
                            uploader.autoSubmit = true;
                            if (self._trigger("totalUpload", e, null) === false) {
                                return false;
                            }
                        }
                        self.totalUploadFiles++;
                        self._upload(fileRow);
                        if (uploader && self._wijUpload()) {
                            uploader.upload();
                        }
                    }
                });
                self.upload.delegate("." + uploadUploadAllClass, "click." + self.widgetName, function (e) {
                    e.preventDefault();
                    if ((o.enableSWFUploadOnIE && $.browser.msie) || o.enableSWFUpload) {
                        self.uploadAll = true;
                        if (self._wijUpload()) {
                            self._swfUploadFile();
                        } else {
                            self._upload(true, true);
                        }
                    } else {
                        self.uploadAll = true;
                        if (!self.progressAll) {
                            self._resetProgressAll();
                        }
                        if (self._trigger("totalUpload", e, null) === false) {
                            return false;
                        }
                        self.progressAll.totalSize = self._getTotalSize();
                        self._wijuploadAll($(isUploadUpload, self.filesList[0]));
                        if (self._wijUpload()) {
                            $(isUploadUpload, self.filesList[0]).each(function (idx, uploadBtn) {
                                $(uploadBtn).click();
                                return idx;
                            });
                        }
                    }
                });
                self.upload.delegate("." + uploadCancelAllClass, "click." + self.widgetName, function (e) {
                    e.preventDefault();
                    if ((o.enableSWFUploadOnIE && $.browser.msie) || o.enableSWFUpload) {
                        $.each(self.swfupload.queueData.files, function (key, v) {
                            self.swfupload.cancelUpload(key);
                        });
                        $(isUploadFileRow, self.element).fadeOut(1500, function () {
                            $(this).remove();
                            self.commandRow.hide();
                            self._setAddBtnState();
                        });
                    } else {
                        self._resetProgressAll();
                        $(isUploadCancel, self.filesList[0]).each(function (idx, cancelBtn) {
                            $(cancelBtn).click();
                        });
                    }
                });
            };

            wijupload.prototype._removeFileRowSetButtonStates = function () {
                var self = this;
                $(self).parents(isUploadFileRow).remove();
                self._setAddBtnState();
                if ($(isUploadFileRow, self.element).length === 0) {
                    self.commandRow.hide();
                }
            };

            wijupload.prototype._wijuploadAll = function (uploadBtns) {
            };

            wijupload.prototype._wijFileRowRemoved = function (fileRow, fileInput, isComplete) {
                this._setAddBtnState();
            };

            wijupload.prototype._removeFileRow = function (fileRow, uploader, isComplete) {
                var self = this, inputFileId, files;
                if (uploader) {
                    inputFileId = uploader.inputFile.attr("id");
                }
                fileRow.fadeOut(1500, function () {
                    fileRow.remove();
                    self._wijFileRowRemoved(fileRow, uploader.inputFile, isComplete);
                    if (self.uploaders[inputFileId]) {
                        delete self.uploaders[inputFileId];
                    }
                    files = $(isUploadFileRow, self.upload);
                    if (files.length) {
                        self.commandRow.show();
                        if (uploader && uploader.destroy) {
                            uploader.destroy();
                        }
                    } else {
                        self.commandRow.hide();
                        self.totalUploadFiles = 0;
                        self._resetProgressAll();
                        if (uploader && uploader.destroy) {
                            uploader.destroy(true);
                        }
                    }
                });
            };

            // Used by C1Upload.
            wijupload.prototype._getFileName = function (fileName) {
                return _getFileName(fileName);
            };

            wijupload.prototype._getFileNameByInput = function (fileInput) {
                return _getFileNameByInput(fileInput);
            };

            wijupload.prototype._getFileSize = function (fileInput) {
                return _getFileSize(fileInput);
            };
            return wijupload;
        })(wijmo.wijmoWidget);
        upload.wijupload = wijupload;

        var wijupload_options = (function () {
            function wijupload_options() {
                /**
                * @ignore
                */
                this.wijCSS = {
                    iconCircleArrowN: "ui-icon-circle-arrow-n",
                    iconCancel: "ui-icon-cancel"
                };
                /** Specifies the URL path of the server-side handler that handles the post request, validates file size and type, renames files, and saves the file to the server disk.
                * @example
                * For php:
                * $(".selector").wijupload("option", "action", "../upload.php")
                * For asp.net:
                * $(".selector").wijupload("option", "action", "../handlers/uploadHandler.ashx")
                */
                this.action = "";
                /** The value indicates whether to upload the file as soon as it is selected in the "Choose File to Upload" dialog box.
                */
                this.autoSubmit = false;
                /** Fires when user selects a file. This event can be cancelled.
                * "return false;" to cancel the event.
                * @event
                * @param {jQuery.Event} e jQuery Event object
                * @param {object} data An object that contains the input file.
                */
                this.change = null;
                /** Fires before the file is uploaded.  This event can be cancelled.
                * "return false;" to cancel the event.
                * @event
                * @param {jQuery.Event} e jQuery Event object
                * @param {object} data An object that contains the input file.
                */
                this.upload = null;
                /** Fires when the uploadAll button is clicked. This event can be cancelled.
                * "return false;" to cancel the event.
                * @event
                */
                this.totalUpload = null;
                /** Fires when a file is uploading.
                * @event
                * @param {jQuery.Event} e jQuery Event object
                * @param {object} data An object that contains the file info, loadedSize and totalSize.
                */
                this.progress = null;
                /** Fires when the uploadAll button is clicked and file upload is complete.
                * @event
                * @dataKey {number} loadedSize The size of loaded files.
                * @dataKey {number} totalSize The size of total files.
                */
                this.totalProgress = null;
                /** Fires when file upload is complete.
                * @event
                * @param {jQuery.Event} e jQuery Event object
                * @param {object} data An object that contains the file info.
                */
                this.complete = null;
                /** Fires when the uploadAll button is clicked and file upload is complete.
                * @event
                */
                this.totalComplete = null;
                /** Specifies the maximum number of files that can be uploaded.
                */
                this.maximumFiles = 0;
                /** Determines whether multiple selection is supported.
                */
                this.multiple = true;
                /** Specifies the accept attribute of upload. This is an attribute of the file input.
                * @remarks
                * It is a filter that allows the "Choose File to Upload" dialog box to show the file list with the specified type.
                * Possible values:
                * audio/* - All sound files are accepted.
                * video/* - All video files are accepted.
                * image/* - All image files are accepted.
                * MIME_type - A valid MIME type with no parameters.
                * @example
                *     $(".selector").wijupload("accept", "image/*")
                */
                this.accept = "";
                /** upload with SWFupload.swf,
                * this option is used for multiple-select in IE.
                */
                this.enableSWFUploadOnIE = false;
                /** upload with SWFupload.swf in all browsers.
                */
                this.enableSWFUpload = false;
                /** @ignore
                * For web control
                */
                this.swfUploadOptions = {};
                /** @ignore
                * For web control
                */
                this.localization = {};
                /** @ignore
                * For web control
                */
                this.handleRequest = null;
            }
            return wijupload_options;
        })();

        var mainClass = "wijmo-wijupload", classPrefix = mainClass + "-";
        wijupload.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijupload_options());

        $.wijmo.registerWidget("wijupload", wijupload.prototype);
    })(wijmo.upload || (wijmo.upload = {}));
    var upload = wijmo.upload;
})(wijmo || (wijmo = {}));

;
/// <reference path="../Base/jquery.wijmo.widget.ts" />
/// <reference path="../wijsuperpanel/jquery.wijmo.wijsuperpanel.ts" />
/// <reference path="../wijpopup/jquery.wijmo.wijpopup.ts" />
/// <reference path="../External/declarations/jquery.cookie.d.ts" />
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*
    * Depends:
    *  jquery-1.4.2.js
    *  jquery.ui.core.js
    *  jquery.ui.widget.js
    *  jquery.ui.position.js
    *  jquery.effects.core.js
    *  jquery.cookie.js
    *  jquery.wijmo.wijsuperpanel.js
    *  jquery.wijmo.wijutil.js
    *
    */
    (function (wizard) {
        var $ = jQuery, configStr = {
            WIJWIZARD: "wijwizard",
            LOADWIJWIZARD: "load.wijwizard",
            CACHEWIJWIZARD: "cache.wijwizard",
            SPINNERWIJWIZARD: "spinner.wijwizard",
            INTIDWIZARD: "intId.wijwizard",
            DESTROYWIJWIZARD: "destroy.wijwizard"
        }, defaults = {
            stepHeaderTemplate: '<li><h1>#{title}</h1>#{desc}</li>',
            panelTemplate: '<div></div>',
            spinner: '<em>Loading&#8230;</em>'
        };

        /** @widget*/
        var wijwizard = (function (_super) {
            __extends(wijwizard, _super);
            function wijwizard() {
                _super.apply(this, arguments);
            }
            wijwizard.prototype._create = function () {
                var _this = this;
                this._defaults = defaults;
                this._configStr = configStr;
                this._isPlaying = false;
                if (this.element.is(":hidden") && this.element.wijAddVisibilityObserver) {
                    this.element.wijAddVisibilityObserver(function () {
                        if (_this.element.wijRemoveVisibilityObserver) {
                            _this.element.wijRemoveVisibilityObserver();
                        }
                        _this._pageLize(false);
                    }, this._configStr.WIJWIZARD);
                    //return;
                }
                this._pageLize(true);

                _super.prototype._create.call(this);
            };

            wijwizard.prototype._init = function () {
                var o = this.options;
                if (!this._isDisabled() && o.autoPlay) {
                    this.play();
                }
            };

            wijwizard.prototype._setOption = function (key, value) {
                _super.prototype._setOption.call(this, key, value);

                switch (key) {
                    case 'activeIndex':
                        this.show(value);
                        break;
                    case 'navButtons':
                    case 'backBtnText':
                    case 'nextBtnText':
                        this._createButtons();
                        break;
                    case 'delay':
                        if (this._isPlaying) {
                            this.stop();
                            this.play();
                        }
                        break;
                    case 'autoPlay':
                        if (value === true) {
                            this.play();
                        } else {
                            this.stop();
                        }
                    default:
                        this._pageLize(false);
                        break;
                }
            };

            /** Removes the wijwizard functionality completely.
            * This returns the element back to its pre-init state.
            */
            wijwizard.prototype.destroy = function () {
                var o = this.options, self = this, elementCls = [o.wijCSS.wijwizard, o.wijCSS.widget, o.wijCSS.helperClearFix].join(" "), listCls = [o.wijCSS.widget, o.wijCSS.helperReset, o.wijCSS.wijwizardSteps, o.wijCSS.helperClearFix].join(" "), lisCls = [o.wijCSS.header, o.wijCSS.cornerAll, o.wijCSS.priorityPrimary, o.wijCSS.prioritySecondary].join(" "), panelsCls = [o.wijCSS.stateDefault, o.wijCSS.wijwizardActived, o.wijCSS.stateActive, o.wijCSS.stateHover, o.wijCSS.stateFocus, o.wijCSS.stateDisabled, o.wijCSS.wijwizardPanel, o.wijCSS.content, o.wijCSS.wijwizardHide].join(" ");

                this.abort();
                this.stop();
                this._removeScroller();
                this._removeButtons();
                this.element.unbind('.wijwizard').removeClass(elementCls).removeData(this._configStr.WIJWIZARD);

                if (this.list) {
                    this.list.removeClass(listCls).removeAttr('role');
                }

                if (this.lis) {
                    this.lis.removeClass(lisCls).removeAttr('role');
                    $.each(this.lis, function () {
                        if ($.data(this, self._configStr.DESTROYWIJWIZARD)) {
                            $(this).remove();
                        } else {
                            $(this).removeAttribute('aria-selected');
                        }
                    });
                }

                $.each(this.panels, function () {
                    var $this = $(this).unbind('.wijwizard');
                    $this.removeAttr("role");
                    $.each(['load', 'cache'], function (i, prefix) {
                        $this.removeData(prefix + '.wijwizard');
                    });

                    if ($.data(this, self._configStr.DESTROYWIJWIZARD)) {
                        $this.remove();
                    } else {
                        $this.removeClass(panelsCls).css({ position: '', left: '', top: '' }).removeAttribute('aria-hidden');
                    }
                });

                this.container.replaceWith(this.container.contents());

                if (o.cookie) {
                    this._cookie(null, o.cookie);
                }

                _super.prototype.destroy.call(this);
            };

            wijwizard.prototype._pageLize = function (init) {
                var o = this.options, self = this, fragmentId = /^#.+/;

                //Fix a bug that when no title and has ul li element in its content
                this.list = this.element.children('ol,ul').eq(0);
                if (this.list && this.list.length === 0) {
                    this.list = this.element.find("." + o.wijCSS.wijwizardSteps).eq(0);
                    if (this.list && this.list.length === 0) {
                        this.list = null;
                    }
                }
                if (this.list) {
                    this.lis = $('li', this.list);
                }

                if (init) {
                    this.panels = $('> div', this.element);

                    $.each(this.panels, function (i, p) {
                        var url = $(p).attr('src');

                        // inline
                        if (url && !fragmentId.test(url)) {
                            // mutable data
                            $.data(p, self._configStr.LOADWIJWIZARD, url.replace(/#.*$/, ''));
                        }
                    });

                    var elementCls = [o.wijCSS.wijwizard, o.wijCSS.widget, o.wijCSS.helperClearFix].join(" "), listCls = [o.wijCSS.widget, o.wijCSS.helperReset, o.wijCSS.wijwizardSteps, o.wijCSS.helperClearFix].join(" "), lisCls = [o.wijCSS.header, o.wijCSS.cornerAll].join(" "), containCls = [o.wijCSS.wijwizardContent, o.wijCSS.widget, o.wijCSS.content, o.wijCSS.cornerAll].join(" "), panelCls = [o.wijCSS.wijwizardPanel, o.wijCSS.content].join(" ");
                    this.element.addClass(elementCls);
                    if (this.list) {
                        this.list.addClass(listCls).attr("role", "tablist");
                        this.lis.addClass(lisCls).attr("role", "tab");
                    }
                    this.container = $('<div/>');
                    this.container.addClass(containCls);
                    this.container.append(this.panels);
                    this.container.appendTo(this.element);
                    this.panels.addClass(panelCls).attr("role", "tabpanel");

                    // Active a panel
                    // use "activeIndex" option or try to retrieve:
                    // 1. from cookie
                    // 2. from actived class attribute on panel
                    if (o.activeIndex === undefined) {
                        if (typeof o.activeIndex !== 'number' && o.cookie) {
                            o.activeIndex = parseInt(this._cookie(undefined, undefined), 10);
                        }
                        if (typeof o.activeIndex !== 'number' && this.panels.filter('.' + o.wijCSS.wijwizardActived).length) {
                            o.activeIndex = this.panels.index(this.panels.filter('.' + o.wijCSS.wijwizardActived));
                        }
                        o.activeIndex = o.activeIndex || (this.panels.length ? 0 : -1);
                    } else if (o.activeIndex === null) {
                        // usage of null is deprecated, TODO remove in next release
                        o.activeIndex = -1;
                    }

                    // sanity check - default to first page...
                    o.activeIndex = ((o.activeIndex >= 0 && this.panels[o.activeIndex]) || o.activeIndex < 0) ? o.activeIndex : 0;

                    this.panels.addClass(o.wijCSS.wijwizardHide).attribute('aria-hidden', true);
                    if (o.activeIndex >= 0 && this.panels.length) {
                        // check for length avoids error when initializing empty pages
                        this.panels.eq(o.activeIndex).removeClass(o.wijCSS.wijwizardHide).addClass(o.wijCSS.wijwizardActived).attribute('aria-hidden', false);
                        this.load(o.activeIndex);
                    }

                    this._createButtons();
                } else {
                    this.panels = $('> div', this.container);
                    o.activeIndex = this.panels.index(this.panels.filter('.' + o.wijCSS.wijwizardActived));
                }
                this._addScrollForContent();

                this._refreshStep();
                this._initScroller();

                // set or update cookie after init and add/remove respectively
                if (o.cookie) {
                    this._cookie(o.activeIndex, o.cookie);
                }

                // reset cache if switching from cached to not cached
                if (o.cache === false) {
                    this.panels.removeData(this._configStr.CACHEWIJWIZARD);
                }

                if (o.showOption === undefined || o.showOption === null) {
                    o.showOption = {};
                }
                this._normalizeBlindOption(o.showOption);

                if (o.hideOption === undefined || o.hideOption === null) {
                    o.hideOption = {};
                }
                this._normalizeBlindOption(o.hideOption);

                // remove all handlers
                this.panels.unbind('.wijwizard');
            };

            wijwizard.prototype._removeButtons = function () {
                if (this.backBtn) {
                    this.backBtn.unbind(".wijwizard");
                }
                if (this.nextBtn) {
                    this.nextBtn.unbind(".wijwizard");
                }
                if (this.buttons) {
                    this.buttons.remove();
                    this.buttons = undefined;
                }
            };

            wijwizard.prototype._createButtons = function () {
                var self = this, o = this.options, bt, backBtnText = o.backBtnText, nextBtnText = o.nextBtnText, commonCls = [o.wijCSS.widget, o.wijCSS.stateDefault, o.wijCSS.cornerAll, o.wijCSS.button, o.wijCSS.buttonTextOnly].join(" "), backBtCls = [o.wijCSS.wijwizardPrev, o.wijCSS.stateDefault, o.wijCSS.cornerRight].join(" "), nextBtlCls = [o.wijCSS.wijwizardNext, o.wijCSS.stateDefault, o.wijCSS.cornerLeft].join(" ");

                this._removeButtons();
                if (o.navButtons === 'none') {
                    return;
                }

                if (!this.buttons) {
                    bt = o.navButtons;
                    if (bt === 'auto') {
                        bt = this.list ? 'common' : 'edge';
                    }

                    this.buttons = $('<div/>');
                    this.buttons.addClass(o.wijCSS.wijwizardButtons);

                    if (bt === 'common') {
                        this.backBtn = $("<a href='#'/>").addClass(commonCls).append("<span class='" + o.wijCSS.buttonText + "'>" + backBtnText + "</span>").appendTo(this.buttons).attr("role", "button");

                        this.nextBtn = $("<a href='#'/>").addClass(commonCls).append("<span class='" + o.wijCSS.buttonText + "'>" + nextBtnText + "</span>").appendTo(this.buttons).attr("role", "button");
                    } else {
                        this.backBtn = $("<a href='#'/>").addClass(backBtCls).append("<span class='" + o.wijCSS.icon + " " + o.wijCSS.iconArrowLeft + "'></span>").appendTo(this.buttons).attr("role", "button");

                        this.nextBtn = $("<a href='#'/>").addClass(nextBtlCls).append("<span class='" + o.wijCSS.icon + " " + o.wijCSS.iconArrowRight + "'></span>").appendTo(this.buttons).attr("role", "button");
                    }

                    this.buttons.appendTo(this.element);
                }

                this._setupEvent();
            };

            wijwizard.prototype._setupEvent = function (backBtn, nextBtn) {
                var self = this, o = this.options, currentBackBtn = backBtn || this.backBtn, currentNextBtn = nextBtn || this.nextBtn;

                if (!currentBackBtn || !currentNextBtn) {
                    return;
                }
                currentBackBtn.bind({
                    'click.wijwizard': function () {
                        self.back();
                        return false;
                    },
                    'mouseover.wijwizard': self._eventHandler().addState(o.wijCSS.stateHover, currentBackBtn),
                    'mouseout.wijwizard': self._eventHandler().removeState(o.wijCSS.stateHover, currentBackBtn),
                    'mousedown.wijwizard': self._eventHandler().addState(o.wijCSS.stateActive, currentBackBtn),
                    'mouseup.wijwizard': self._eventHandler().removeState(o.wijCSS.stateActive, currentBackBtn)
                });
                currentNextBtn.bind({
                    'click.wijwizard': function () {
                        self.next();
                        return false;
                    },
                    'mouseover.wijwizard': self._eventHandler().addState(o.wijCSS.stateHover, currentNextBtn),
                    'mouseout.wijwizard': self._eventHandler().removeState(o.wijCSS.stateHover, currentNextBtn),
                    'mousedown.wijwizard': self._eventHandler().addState(o.wijCSS.stateActive, currentNextBtn),
                    'mouseup.wijwizard': self._eventHandler().removeState(o.wijCSS.stateActive, currentNextBtn)
                });
            };

            wijwizard.prototype._eventHandler = function () {
                var self = this, o = this.options, addState = function (state, el) {
                    return function () {
                        if (self._isDisabled()) {
                            return;
                        }
                        if (el.is(':not(.' + o.wijCSS.stateDisabled + ')')) {
                            el.addClass(state);
                        }
                    };
                }, removeState = function (state, el) {
                    return function () {
                        if (self._isDisabled()) {
                            return;
                        }
                        el.removeClass(state);
                    };
                };

                return {
                    addState: addState,
                    removeState: removeState
                };
            };

            wijwizard.prototype._refreshStep = function () {
                var o = this.options;

                if (this.lis) {
                    this.lis.removeClass(o.wijCSS.priorityPrimary).addClass(o.wijCSS.prioritySecondary).attribute('aria-selected', false);
                    if (o.activeIndex >= 0 && o.activeIndex <= this.lis.length - 1) {
                        if (this.lis) {
                            this.lis.eq(o.activeIndex).removeClass(o.wijCSS.prioritySecondary).addClass(o.wijCSS.priorityPrimary).attribute('aria-selected', true);
                        }
                        if (this.scrollWrap) {
                            this.scrollWrap.wijsuperpanel('scrollChildIntoView', this.lis.eq(o.activeIndex));
                        }
                    }
                }

                if (this.buttons && !o.loop) {
                    this.backBtn[o.activeIndex <= 0 ? 'addClass' : 'removeClass'](o.wijCSS.stateDisabled).attribute('aria-disabled', o.activeIndex === 0);
                    this.nextBtn[o.activeIndex >= this.panels.length - 1 ? 'addClass' : 'removeClass'](o.wijCSS.stateDisabled).attribute('aria-disabled', (o.activeIndex >= this.panels.length - 1));
                }
            };

            wijwizard.prototype._initScroller = function () {
                if (!this.lis || !this.element.is(":visible")) {
                    return;
                }

                var width = 0;
                $.each(this.lis, function () {
                    width += $(this).outerWidth(true);
                });

                if (this.element.innerWidth() < width) {
                    if (this.scrollWrap === undefined) {
                        this.list.wrap("<div class='scrollWrap'></div>");
                        this.scrollWrap = this.list.parent();
                        if ($.effects && $.effects.save) {
                            $.effects.save(this.list, ['width', 'height', 'overflow']);
                        } else if ($.save) {
                            $.save(this.list, ['width', 'height', 'overflow']);
                        }
                    }

                    this.list.width(width + 8);
                    this.scrollWrap.height(this.list.outerHeight(true));

                    this.scrollWrap.wijsuperpanel({
                        allowResize: false,
                        hScroller: {
                            scrollBarVisibility: 'hidden'
                        },
                        vScroller: {
                            scrollBarVisibility: 'hidden'
                        }
                    });
                } else {
                    this._removeScroller();
                }
            };

            wijwizard.prototype._removeScroller = function () {
                if (this.scrollWrap) {
                    this.scrollWrap.wijsuperpanel('destroy').replaceWith(this.scrollWrap.contents());
                    this.scrollWrap = undefined;
                    if ($.effects && $.effects.restore) {
                        $.effects.restore(this.list, ['width', 'height', 'overflow']);
                    } else if ($.restore) {
                        $.restore(this.list, ['width', 'height', 'overflow']);
                    }
                }
            };

            wijwizard.prototype._cookie = function (index, c) {
                var cookie = this.cookie || (this.cookie = this.options.cookie.name);
                return $.cookie.apply(null, [cookie].concat($.makeArray(arguments)));
            };

            wijwizard.prototype._normalizeBlindOption = function (o) {
                if (o.blind === undefined) {
                    o.blind = false;
                }
                if (o.fade === undefined) {
                    o.fade = false;
                }
                if (o.duration === undefined) {
                    o.duration = 200;
                }
                if (typeof o.duration === 'string') {
                    try  {
                        o.duration = parseInt(o.duration, 10);
                    } catch (e) {
                        o.duration = 200;
                    }
                }
            };

            wijwizard.prototype._ui = function (panel) {
                return {
                    panel: panel,
                    index: this.panels.index(panel)
                };
            };

            wijwizard.prototype._removeSpinner = function () {
                // restore all former loading wijwizard labels
                this.element.removeClass(this.options.wijCSS.tabsLoading);
                var spinner = this.element.data(this._configStr.SPINNERWIJWIZARD);
                if (spinner) {
                    this.element.removeData(this._configStr.SPINNERWIJWIZARD);
                    spinner.remove();
                }
            };

            wijwizard.prototype._showPanel = function (p) {
                var _this = this;
                var o = this.options, $show = p, props;

                $show.addClass(o.wijCSS.wijwizardActived);
                if ((o.showOption.blind || o.showOption.fade) && o.showOption.duration > 0) {
                    props = { duration: o.showOption.duration };
                    if (o.showOption.blind) {
                        props.height = 'toggle';
                    }
                    if (o.showOption.fade) {
                        props.opacity = 'toggle';
                    }
                    $show.hide().removeClass(o.wijCSS.wijwizardHide).animate(props, o.showOption.duration || 'normal', "linear", function () {
                        _this._resetStyle($show);
                        if ($show.wijTriggerVisibility) {
                            $show.wijTriggerVisibility();
                        }
                        _this._trigger('show', null, _this._ui($show[0]));
                        _this._removeSpinner();
                        $show.attribute('aria-hidden', false);
                        _this._trigger('activeIndexChanged', null, _this._ui($show[0]));
                    });
                } else {
                    $show.removeClass(o.wijCSS.wijwizardHide).attribute('aria-hidden', false);
                    if ($show.wijTriggerVisibility) {
                        $show.wijTriggerVisibility();
                    }
                    this._trigger('show', null, this._ui($show[0]));
                    this._removeSpinner();
                    this._trigger('activeIndexChanged', null, this._ui($show[0]));
                }
            };

            wijwizard.prototype._hidePanel = function (p) {
                var _this = this;
                var self = this, o = this.options, $hide = p, props;

                $hide.removeClass(o.wijCSS.wijwizardActived);
                if ((o.hideOption.blind || o.hideOption.fade) && o.hideOption.duration > 0) {
                    props = { duration: o.hideOption.duration };
                    if (o.hideOption.blind) {
                        props.height = 'toggle';
                    }
                    if (o.hideOption.fade) {
                        props.opacity = 'toggle';
                    }
                    $hide.animate(props, o.hideOption.duration || 'normal', "linear", function () {
                        $hide.addClass(o.wijCSS.wijwizardHide).attribute('aria-hidden', true);
                        _this._resetStyle($hide);
                        _this.element.dequeue(_this._configStr.WIJWIZARD);
                    });
                } else {
                    $hide.addClass(o.wijCSS.wijwizardHide).attribute('aria-hidden', true);
                    this.element.dequeue(this._configStr.WIJWIZARD);
                }
            };

            // Reset certain styles left over from animation
            // and prevent IE's ClearType bug...
            wijwizard.prototype._resetStyle = function ($el) {
                $el.css({ display: '' });

                if (!$.support.opacity) {
                    $el[0].style.removeAttribute('filter');
                }
            };

            wijwizard.prototype._addScrollForContent = function () {
                var self = this, contentHeight = self.element.height();

                if (!this.element.is(":visible")) {
                    return;
                }

                // fix the issue 42962, if there is no buttons or pageer list in the wizard, it will throw exception.
                if (self.buttons) {
                    contentHeight -= self.buttons.outerHeight(true);
                }
                if (self.list) {
                    contentHeight -= self.list.outerHeight(true);
                }
                contentHeight -= (self.container.outerHeight(true) - self.container.innerHeight()) - (self.container.innerHeight() - self.container.height());

                if (contentHeight < self.container.height()) {
                    self.container.height(contentHeight);
                }

                self.container.css("overflow", "auto");
            };

            /** The add method adds a new panel.
            * @param {number} index Zero-based position where to insert the new panel.
            * @param {string} title The step title.
            * @param {string} desc The step description.
            * @example
            * // Add a new panel to be the second step.
            * // It's title is "New Panel", description is "New Panel Description".
            * $("#wizard").wijwizard("add", 1, "New Panel", "New Panel Description");
            */
            wijwizard.prototype.add = function (index, title, desc) {
                if (index === undefined) {
                    index = this.panels.length; // append by default
                }

                if (title === undefined) {
                    title = "Step " + index;
                }

                var self = this, o = this.options, $panel = $(o.panelTemplate || self._defaults.panelTemplate).data(this._configStr.DESTROYWIJWIZARD, true), panelCls = [o.wijCSS.wijwizardPanel, o.wijCSS.content, o.wijCSS.cornerAll, o.wijCSS.wijwizardHide].join(" "), liCls = [o.wijCSS.header, o.wijCSS.cornerAll, o.wijCSS.prioritySecondary].join(" "), $li;

                $panel.addClass(panelCls).attribute('aria-hidden', true);

                if (index >= this.panels.length) {
                    if (this.panels.length > 0) {
                        $panel.insertAfter(this.panels[this.panels.length - 1]);
                    } else {
                        $panel.appendTo(this.container);
                    }
                } else {
                    $panel.insertBefore(this.panels[index]);
                }

                if (this.list && this.lis) {
                    $li = $((o.stepHeaderTemplate || self._defaults.stepHeaderTemplate).replace(/#\{title\}/g, title).replace(/#\{desc\}/g, desc));
                    $li.addClass(liCls).data(this._configStr.DESTROYWIJWIZARD, true);

                    if (index >= this.lis.length) {
                        $li.appendTo(this.list);
                    } else {
                        $li.insertBefore(this.lis[index]);
                    }
                }

                this._pageLize(false);

                if (this.panels.length === 1) {
                    o.activeIndex = 0;
                    $li.addClass(o.wijCSS.priorityPrimary);
                    $panel.removeClass(o.wijCSS.wijwizardHide).addClass(o.wijCSS.wijwizardActived).attribute('aria-hidden', false);
                    this.element.queue(this._configStr.WIJWIZARD, function () {
                        self._trigger('show', null, self._ui(self.panels[0]));
                    });

                    this._refreshStep();
                    this.load(0);
                }

                // callback
                this._trigger('add', null, this._ui(this.panels[index]));
                return this;
            };

            /** The remove method removes a panel.
            * @param {number} index The zero-based index of the panel to be removed.
            * @example
            * // Remove the second step.
            * $("#wizard").wijwizard("remove", 1);
            */
            wijwizard.prototype.remove = function (index) {
                var o = this.options, $panel = this.panels.eq(index).remove();

                this.lis.eq(index).remove();
                if (index < o.activeIndex) {
                    o.activeIndex--;
                }

                this._pageLize(false);

                //Ajust the active panel index in some case
                if ($panel.hasClass(o.wijCSS.wijwizardActived) && this.panels.length >= 1) {
                    this.show(index + (index < this.panels.length ? 0 : -1));
                }

                // callback
                this._trigger('remove', null, this._ui($panel[0]));
                return this;
            };

            /** The show method selects an active panel and displays the panel at a specified position.
            * @param {number} index The zero-based index of the panel to be actived.
            * @example
            * // Show the second step.
            * $("#wizard").wijwizard("show", 1);
            */
            wijwizard.prototype.show = function (index) {
                var _this = this;
                if (index < 0 || index >= this.panels.length) {
                    return this;
                }

                // previous animation is still processing
                if (this.element.queue(this._configStr.WIJWIZARD).length > 0) {
                    return this;
                }

                var o = this.options, args = {
                    nextIndex: 0,
                    nextPanel: null
                }, $hide, $show;

                $.extend(args, this._ui(this.panels[o.activeIndex]));
                args.nextIndex = index;
                args.nextPanel = this.panels[index];
                if (this._trigger('validating', null, args) === false) {
                    return this;
                }

                $hide = this.panels.filter(':not(.' + o.wijCSS.wijwizardHide + ')');
                $show = this.panels.eq(index);
                o.activeIndex = index;

                this.abort();

                if (o.cookie) {
                    this._cookie(o.activeIndex, o.cookie);
                }

                this._refreshStep();

                // show new panel
                if ($show.length) {
                    if ($hide.length) {
                        this.element.queue(this._configStr.WIJWIZARD, function () {
                            _this._hidePanel($hide);
                        });
                    }

                    this.element.queue(this._configStr.WIJWIZARD, function () {
                        _this._showPanel($show);
                    });

                    this.load(index);
                } else {
                    throw 'jQuery UI wijwizard: Mismatching fragment identifier.';
                }

                return this;
            };

            /** The next method moves to the next panel. */
            wijwizard.prototype.next = function () {
                var o = this.options, index = o.activeIndex + 1;

                if (this._isDisabled()) {
                    return false;
                }
                if (o.loop) {
                    index = index % this.panels.length;
                }

                if (index < this.panels.length) {
                    this.show(index);
                    return true;
                }
                return false;
            };

            /** The back method moves to the previous panel. */
            wijwizard.prototype.back = function () {
                var o = this.options, index = o.activeIndex - 1;

                if (this._isDisabled()) {
                    return false;
                }
                if (o.loop) {
                    index = index < 0 ? this.panels.length - 1 : index;
                }

                if (index >= 0) {
                    this.show(index);
                    return true;
                }
                return false;
            };

            wijwizard.prototype._popupSpinner = function () {
                var self = this, ele = self.element, o = self.options, spinner;

                // load remote from here on
                ele.addClass(o.wijCSS.tabsLoading);
                if (!o.spinner) {
                    return;
                }
                spinner = ele.data(self._configStr.SPINNERWIJWIZARD);
                if (!spinner) {
                    spinner = $('<div/>');
                    spinner.addClass(o.wijCSS.wijwizardSpinner);
                    spinner.html(o.spinner || self._defaults.spinner);
                    spinner.appendTo(document.body);
                    ele.data(self._configStr.SPINNERWIJWIZARD, spinner);
                    spinner.wijpopup({
                        showEffect: 'blind',
                        hideEffect: 'blind'
                    });
                }

                spinner.wijpopup('show', {
                    of: ele,
                    my: 'center center',
                    at: 'center center'
                });
            };

            /** The load method reload the content of an Ajax panel programmatically.
            * @param {number} index The zero-based index of the panel to be loaded.
            * @example
            * // Reload the content of second step.
            * $("#wizard").wijwizard("load", 1);
            */
            wijwizard.prototype.load = function (index) {
                var self = this, o = self.options, p = self.panels.eq(index)[0], ele = self.element, url = $.data(p, self._configStr.LOADWIJWIZARD);

                self.abort();

                // not remote or from cache
                if (!url || ele.queue(self._configStr.WIJWIZARD).length !== 0 && $.data(p, self._configStr.CACHEWIJWIZARD)) {
                    ele.dequeue(self._configStr.WIJWIZARD);
                    return self;
                }

                self._popupSpinner();

                self.xhr = $.ajax($.extend({}, o.ajaxOptions, {
                    url: url,
                    dataType: 'html',
                    success: function (r, s) {
                        $(p).html(r);

                        if (o.cache) {
                            // if loaded once do not load them again
                            $.data(p, self._configStr.CACHEWIJWIZARD, true);
                        }

                        // callbacks
                        self._trigger('load', null, self._ui(self.panels[index]));
                        try  {
                            if (o.ajaxOptions && o.ajaxOptions.success) {
                                o.ajaxOptions.success(r, s);
                            }
                        } catch (e1) {
                        }
                    },
                    error: function (xhr, s) {
                        // callbacks
                        self._trigger('load', null, self._ui(self.panels[index]));
                        try  {
                            // Passing index avoid a race condition when this method is
                            // called after the user has selected another panel.
                            if (o.ajaxOptions && o.ajaxOptions.error) {
                                o.ajaxOptions.error(xhr, s, index, p);
                            }
                        } catch (e2) {
                        }
                    }
                }));

                // last, so that load event is fired before show...
                ele.dequeue(self._configStr.WIJWIZARD);

                return self;
            };

            /** The abort method terminates all running panel ajax requests and animations. */
            wijwizard.prototype.abort = function () {
                this.element.queue([]);
                this.panels.stop(false, true);

                // configStr.WIJWIZARD queue must not contain more than two elements,
                // which are the callbacks for hide and show
                this.element.queue(this._configStr.WIJWIZARD, this.element.queue(this._configStr.WIJWIZARD).splice(-2, 2));

                // terminate pending requests from other wijwizard
                if (this.xhr) {
                    this.xhr.abort();
                    delete this.xhr;
                }

                // take care of spinners
                this._removeSpinner();
                return this;
            };

            /** The url method changes the url from which an Ajax (remote) panel will be loaded.
            * @param {number} index The zero-based index of the panel of which its URL is to be updated.
            * @param {string} url A URL the content of the panel is loaded from.
            * @example
            * // Change the url content of second step.
            * $("#wizard").wijwizard("url", 1, "http://wijmo.com/newurl.html");
            */
            wijwizard.prototype.url = function (index, url) {
                this.panels.eq(index).removeData(this._configStr.CACHEWIJWIZARD).data(this._configStr.LOADWIJWIZARD, url);
                return this;
            };

            /**
            * The count method retrieves the number panels.
            * @returns {number} the pabels's length
            */
            wijwizard.prototype.count = function () {
                return this.panels.length;
            };

            /** The stop method stops displaying the panels in order automatically. */
            wijwizard.prototype.stop = function () {
                var id = this.element.data(this._configStr.INTIDWIZARD);
                if (id) {
                    window.clearInterval(id);
                    this.element.removeData(this._configStr.INTIDWIZARD);
                }

                this._isPlaying = false;
            };

            /** The play method begins displaying the panels in order automatically. */
            wijwizard.prototype.play = function () {
                var _this = this;
                var o = this.options, id, len = this.panels.length;

                if (!this.element.data(this._configStr.INTIDWIZARD)) {
                    id = window.setInterval(function () {
                        var index = o.activeIndex + 1;
                        _this._isPlaying = true;
                        if (index >= len) {
                            if (o.loop) {
                                index = 0;
                            } else {
                                _this.stop();
                                return;
                            }
                        }
                        _this.show(index);
                    }, o.delay);

                    this.element.data(this._configStr.INTIDWIZARD, id);
                }
            };
            return wijwizard;
        })(wijmo.wijmoWidget);
        wizard.wijwizard = wijwizard;

        

        

        

        

        

        

        

        

        var wijwizard_options = (function () {
            function wijwizard_options() {
                /** All CSS classes used in widgets.
                * @ignore
                */
                this.wijCSS = {
                    wijwizard: "wijmo-wijwizard",
                    wijwizardButtons: "wijmo-wijwizard-buttons",
                    wijwizardPrev: "wijmo-wijwizard-prev",
                    wijwizardNext: "wijmo-wijwizard-next",
                    wijwizardSteps: "wijmo-wijwizard-steps",
                    wijwizardContent: "wijmo-wijwizard-content",
                    wijwizardPanel: "wijmo-wijwizard-panel",
                    wijwizardActived: "wijmo-wijwizard-actived",
                    wijwizardHide: "wijmo-wijwizard-hide",
                    wijwizardSpinner: "wijmo-wijwizard-spinner"
                };
                /** @ignore*/
                this.wijMobileCSS = {
                    header: "ui-header ui-bar-a",
                    content: "ui-body-b",
                    stateDefault: "ui-btn ui-btn-a",
                    stateHover: "ui-btn-down-a",
                    stateActive: "ui-btn-down-a"
                };
                /** The navButtons option defines the type of navigation buttons used with the wijwizard.
                * @remarks The possible values are 'auto', 'common', 'edge' and 'none'.
                */
                this.navButtons = 'auto';
                /** The autoPlay option allows the panels to automatically display in order. */
                this.autoPlay = false;
                /** The delay option determines the time span between displaying panels in autoplay mode. */
                this.delay = 3000;
                /** The loop option allows the wijwizard to begin again from the first panel
                * when reaching the last panel in autoPlay mode. */
                this.loop = false;
                /** The hideOption option defines the animation effects
                * when hiding the panel content.
                * @example
                * //Set hide animation to blind and duration to 500.
                * $(".selector").wijwizard({
                *		hideOption: {fade: false, blind: true, duration: 500}
                * });
                */
                this.hideOption = { fade: true };
                /** The showOption option defines the animation effects
                * when showing the panel content.
                * @example
                * //Set show animation to blind and duration to 500.
                * $(".selector").wijwizard({
                *		showOption: {fade: false, blind: true, duration: 500}
                * });
                */
                this.showOption = { fade: true, duration: 400 };
                /** A value that indicates additional Ajax options to consider when
                * loading panel content (see $.ajax).
                * @type {object}
                * @remarks Please see following link for more details,
                * http://api.jquery.com/jQuery.ajax/ .
                *
                */
                this.ajaxOptions = null;
                /** An option that determines whether to cache emote wijwizard content.
                * @remarks Cached content is being lazy loaded,
                * for example only and only once for the panel is displayed.
                * Note that to prevent the actual Ajax requests from being cached by the browser,
                * you need to provide an extra cache: false flag to ajaxOptions.
                */
                this.cache = false;
                /** The cookie option is a value that stores the latest active index in a cookie.
                * The cookie is then used to determine the initially active index
                * if the activeIndex option is not defined.
                * @remarks This option requires a cookie plugin.
                * The object needs to have key/value pairs
                * of the form the cookie plugin expects as options.
                * @type {object}
                * @example
                * $(".selector").wijwizard({cookie:{expires: 7, path: '/', domain:  'jquery.com';, secure: true }})
                */
                this.cookie = null;
                /** The stepHeaderTemplate option creates an HTML template
                * for the step header when a new panel is added with the
                * add method or when creating a panel for a remote panel on the fly.
                */
                this.stepHeaderTemplate = '';
                /** The panelTemplate option is an HTML template from which a new panel is created.
                * The new panel is created by adding a panel with the add method or when creating
                * a panel from a remote panel on the fly.
                */
                this.panelTemplate = '';
                /** The HTML content of this string is shown in a panel
                * while remote content is loading.
                * Pass the option in empty string to deactivate that behavior. */
                this.spinner = '';
                /** The backBtnText option defines the text for the wizard back button. */
                this.backBtnText = 'back';
                /** The nextBtnText option defines the text for the wijwizard next button. */
                this.nextBtnText = 'next';
                /** The add event handler is a function called when a panel is added.
                * @event
                * @param {Object} e The jQuery.Event object.
                * @param {IWijWizardEventArgs} args The data with this event.
                */
                this.add = null;
                /** The remove event handler is a function called when a panel is removed.
                * @event
                * @param {Object} e The jQuery.Event object.
                * @param {IWijWizardEventArgs} args The data with this event.
                */
                this.remove = null;
                /** The activeIndexChanged event handler is a function called when the activeIndex is changed.
                * @event
                * @param {Object} e The jQuery.Event object.
                * @param {IWijWizardEventArgs} args The data with this event.
                */
                this.activeIndexChanged = null;
                /** The show event handler is a function called when a panel is shown.
                * @event
                * @param {Object} e The jQuery.Event object.
                * @param {IWijWizardEventArgs} args The data with this event.
                */
                this.show = null;
                /** The load event handler is a function called after the content of a remote panel has been loaded.
                * @event
                * @param {Object} e The jQuery.Event object.
                * @param {IWijWizardEventArgs} args The data with this event.
                */
                this.load = null;
                /** The validating event handler is a function called before moving to next panel.
                * This event is Cancellable.
                * @event
                * @param {Object} e The jQuery.Event object.
                * @param {IWijWizardValidatingEventArgs} args The data with this event.
                */
                this.validating = null;
            }
            return wijwizard_options;
        })();
        ;

        wijwizard.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijwizard_options());

        $.wijmo.registerWidget("wijwizard", wijwizard.prototype);

        ;

        ;
    })(wijmo.wizard || (wijmo.wizard = {}));
    var wizard = wijmo.wizard;
})(wijmo || (wijmo = {}));

;
/// <reference path="../external/declarations/globalize.d.ts"/>
/// <reference path="../Base/jquery.wijmo.widget.ts" />
/// <reference path="../wijtabs/jquery.wijmo.wijtabs.ts" />
/// <reference path="../wijmenu/jquery.wijmo.wijmenu.ts" />
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*globals jQuery,window,document*/
    /*
    * Depends:
    *     jquery.ui.core.js
    *     jquery.ui.widget.js
    *     jquery.wijmo.wijtooltip.js
    */
    (function (ribbon) {
        var $ = jQuery, widgetName = "wijribbon";

        var css_ribbon = "wijmo-wijribbon", css_ribbon_disabled = css_ribbon + "-disabled", css_ribbon_bigbutton = css_ribbon + "-bigbutton", css_ribbon_panel = css_ribbon + "-panel", css_ribbon_groups = css_ribbon + "-groups", css_ribbon_group = css_ribbon + "-group", css_ribbon_groupcontent = css_ribbon_group + "-content", css_ribbon_grouplabel = css_ribbon_group + "-label", css_ribbon_dropdown = css_ribbon + "-dropdown", css_ribbon_dropdowngroup = css_ribbon + "-dropdowngroup", css_ribbon_abbrev = css_ribbon + "-abbrev", css_ribbon_abbrevgroup = css_ribbon_abbrev + "group", css_ribbon_text = css_ribbon + "-text", css_ribbon_icon = css_ribbon + "-icon", css_ribbon_abbrevicon = css_ribbon + "-abbrevicon", css_button = "ui-button", css_active_state = "ui-state-active", css_ribbon_accesstoolbar = "wijmo-wijribbon-accesstoolbar", css_ribbon_startmenulinkcontainer = "wijmo-wijribbon-startmenulinkcontainer", css_ribbon_startmenulink = "wijmo-wijribbon-startmenulink", css_ribbon_startmenu = "wijmo-wijribbon-startmenu", css_ribbon_startmenuindicator = "wijmo-wijribbon-startmenuindicator", css_ribbon_accesstoolbarmenuitemchecked = "wijmo-wijribbon-accesstoolbarmenuitemchecked", css_ribbon_accesstoolbarmenuitemunchecked = "wijmo-wijribbon-accesstoolbarmenuitemunchecked", css_ribbon_accesstoolbarmenu = "wijmo-wijribbon-accesstoolbarmenu", css_ribbon_accesstoolbarmenutitleitem = "wijmo-wijribbon-accesstoolbarmenutitleitem", StringBuilder = function () {
            var self = this, strs = [];

            self.append = function (str) {
                strs.push(str);
            };

            self.toString = function () {
                return strs.join("");
            };

            self.dispose = function () {
                strs = null;
            };
        }, HtmlElement = function (tagName, innerText, attributes) {
            var self = this, halfTags = { br: true, img: true, hr: true, input: true };

            self.tagName = tagName || "div";
            self.attributes = attributes || {};
            self.innerText = innerText || "";
            self.children = [];

            if ($.isPlainObject(innerText)) {
                self.innerText = "";
                self.attributes = innerText;
            }

            self._isShortTag = false;

            if (halfTags[self.tagName] === true) {
                self._isShortTag = true;
            }

            self.render = function () {
                var sb = new StringBuilder(), html = "";

                sb.append(self._renderBeginTag(self.tagName, self.attributes));
                if (self.innerText !== "") {
                    sb.append(self.innerText);
                }

                if (self.children.length > 0) {
                    $.each(self.children, function (index, ele) {
                        sb.append(ele.render());
                    });
                }

                sb.append(self._renderEndTag(self.tagName));
                html = sb.toString();
                sb.dispose();

                return html;
            };

            self.add = function (ele) {
                this.children.push(ele);
            };

            self._renderBeginTag = function (tagName, attributes) {
                var sb = new StringBuilder(), strRet = "";
                sb.append("<");
                sb.append(tagName);
                $.each(attributes, function (key, value) {
                    sb.append(" ");
                    sb.append(key);
                    sb.append("=");
                    sb.append("\"");
                    sb.append(value ? value.toString() : "");
                    sb.append("\"");
                });

                if (this._isShortTag) {
                    sb.append(" ");
                } else {
                    sb.append(">");
                }

                strRet = sb.toString();
                sb.dispose();

                return strRet;
            };

            self._renderEndTag = function (tagName) {
                var sb = new StringBuilder(), strRet = "";

                if (this._isShortTag) {
                    sb.append("/>");
                } else {
                    sb.append("</");
                    sb.append(tagName);
                    sb.append(">");
                }
                strRet = sb.toString();
                sb.dispose();
                return strRet;
            };
        };

        /** @widget */
        var wijribbon = (function (_super) {
            __extends(wijribbon, _super);
            function wijribbon() {
                _super.apply(this, arguments);
            }
            wijribbon.prototype._create = function () {
                var self = this;

                // enable touch support:
                if (window.wijmoApplyWijTouchUtilEvents) {
                    $ = window.wijmoApplyWijTouchUtilEvents($);
                }
                this.nativeMarkup = this.element.html();
                this.nativeClass = this.element.attr("class");

                if (self.options.data) {
                    self._initMarkupByData();
                }

                self._ribbonify();
                $(window).bind("resize.wijribbon", function () {
                    //maybe need to remove the updateribbon size from editor resize
                    if (self.element.is(":visible") && !self.options.compactMode) {
                        self.updateRibbonSize();
                    }
                });

                if (self.element.is(":hidden") && self.element.wijAddVisibilityObserver) {
                    self.element.wijAddVisibilityObserver(function () {
                        self.updateRibbonSize();
                        if (self._isDisabled()) {
                            self._setDisabled(true);
                        }
                        if (self.element.wijRemoveVisibilityObserver) {
                            self.element.wijRemoveVisibilityObserver();
                        }
                    }, "wijribbon");
                }
                _super.prototype._create.call(this);
            };

            wijribbon.prototype._initMarkupByData = function () {
                var dataRender = new wijribbonDataRender(this.element.attr("id"), this.options.data), markup = dataRender.getMarkupWithData();
                this.actions = dataRender.getActions();
                this.element.html(markup);
                dataRender.clearRes();
                dataRender = null;
            };

            wijribbon.prototype._setOption = function (key, value) {
                $.wijmo.widget.prototype._setOption.apply(this, arguments);

                // for there is an error throw on editor
                $("." + css_ribbon_startmenulink, this.element).unbind("click.tabs");
            };

            wijribbon.prototype._innerDisable = function () {
                _super.prototype._innerDisable.call(this);
                this._setDisabled(true);
            };

            wijribbon.prototype._innerEnable = function () {
                _super.prototype._innerEnable.call(this);
                this._setDisabled(false);
            };

            wijribbon.prototype._setDisabled = function (value) {
                var self = this, element = self.element, eleOffset = element.offset(), offsetTop = eleOffset.top, offsetLeft = eleOffset.left, offsetParent = $("body"), wijCSS = this.options.wijCSS, disabledModal = self.disabledModal;

                if (element.data("wijmo-wijtabs")) {
                    element.wijtabs("option", "disabled", value);
                }

                if (element.closest(".wijmo-wijeditor").length !== 0) {
                    offsetTop = 0;
                    offsetLeft = 0;
                    offsetParent = element.parent();
                }

                if (value) {
                    if (!disabledModal) {
                        disabledModal = $("<div></div>").addClass(wijCSS.stateDisabled + " " + css_ribbon_disabled).css({
                            top: offsetTop,
                            left: offsetLeft,
                            //for ie can't disabled, so add background-color attribute
                            "background-color": "lightgray",
                            "position": "absolute"
                        }).appendTo(offsetParent).bind("click mousedown mouseup mouseover mouseout " + "focus keydown keypress", function (e) {
                            self._preventDefaultEvent(e);
                            return false;
                        });
                        self.disabledModal = disabledModal;
                    }

                    self.disabledModal.width(element.width()).height(element.outerHeight()).show();
                } else {
                    if (self.disabledModal) {
                        self.disabledModal.hide();
                    }
                }
            };

            wijribbon.prototype._preventDefaultEvent = function (e) {
                e.stopPropagation();
                e.preventDefault();
            };

            wijribbon.prototype._initCustomButtons = function () {
                var self = this, customtype;
                $.each($("[customtype]", self.element), function (index, ele) {
                    customtype = $(ele).attr("customtype");
                    if (customtype && self.options.custombuttons[customtype]) {
                        self.options.custombuttons[customtype].create($(ele));
                    }
                });
            };

            wijribbon.prototype._ribbonify = function () {
                var self = this, wijCSS = this.options.wijCSS;

                self.buttons = {};
                self.listUis = {};
                self.accessbarBtns = {};

                self._initCustomButtons();

                self._createAccessToolBar();

                self._getButtonSets();
                self._createButtons();

                self._createGroup();
                self._createSplit();
                self._createDropdwon();
                self._createInputDropdown();
                self._createGallery();
                self._hideShowedList();
                self._createTab();

                $("." + wijCSS.helperReset + ":not(." + css_ribbon_groups + ", ." + wijCSS.tabsNav + ", .wijmo-wijmenu-list)", self.element).hover(function () {
                    $(this).toggleClass(wijCSS.stateHover);
                });

                //for bootstrap, the jquery-ui button will not append wijcss class
                $("." + css_button, self.element).bind("mouseenter", function () {
                    $("." + wijCSS.buttonText, this).addClass(wijCSS.stateHover);
                }).bind("mouseleave", function () {
                    $("." + wijCSS.buttonText, this).removeClass(wijCSS.stateHover);
                });

                //for bootstrap, the jquery-ui button will not append wijcss class
                $("button." + css_button, self.element).bind("mousedown mouseup", function () {
                    self._addActiveClassToButtonText(this);
                });

                //for bootstrap, the jquery-ui button will not append wijcss class
                //update for 36511 issue for jquery ui 1.10: button interface changed
                $("label." + css_button, self.element).bind("click", function () {
                    if ($("span", this) && $("span", this).length === 1) {
                        //for dropdown button, only text button need to handler
                        //for bold,italic, underline button, icon button, need to do nothing
                        self._addActiveClassToLabelButtonText(this);
                    }
                });
            };

            wijribbon.prototype._addActiveClassToButtonText = function (button) {
                var wijCSS = this.options.wijCSS, activeState;
                if (button) {
                    //for bootstrap, the jquery-ui button will not append
                    // wijcss.stateactive
                    activeState = $(button).hasAllClasses(css_active_state);
                    $("." + wijCSS.buttonText, button).toggleClass(wijCSS.stateActive, activeState).toggleClass(wijCSS.stateDefault, activeState);
                }
            };

            wijribbon.prototype._addActiveClassToLabelButtonText = function (button) {
                var self = this, oriEle, oriEleID, eleGroup;
                if (button) {
                    oriEleID = $(button).attr("for");
                    oriEle = $("#" + oriEleID, self.element);
                    if (oriEle.is(":checkbox")) {
                        self._addActiveClassToButtonText(button);
                    } else if ((oriEle.is(":radio"))) {
                        eleGroup = self.element.find("[name='" + oriEle.attr("name") + "']");
                        $.each(eleGroup, function () {
                            self._updateGroupElementTextState(this);
                        });
                    }
                }
            };

            wijribbon.prototype._updateGroupElementTextState = function (button) {
                var radioLabelEle, wijCSS = this.options.wijCSS, activeState;
                if (!button) {
                    return;
                }

                radioLabelEle = $("[for='" + $(button).attr("id") + "']", $(button).parent());
                if (radioLabelEle) {
                    activeState = radioLabelEle.hasAllClasses(css_active_state);
                    radioLabelEle.children("." + wijCSS.buttonText).toggleClass(wijCSS.stateActive, activeState).toggleClass(wijCSS.stateDefault, activeState);
                }
            };

            wijribbon.prototype._getButtonSets = function () {
                var self = this, span;

                self.groups = [];
                self.splits = [];
                self.dropdowns = [];
                self.inputDropdowns = [];

                $("span>button, span>:checkbox, span>:radio, div>button, div>:checkbox," + " div>:radio, div>:text", self.element).each(function (i, btn) {
                    if ($(btn).parents("[customtype]") && $(btn).parents("[customtype]").length !== 0) {
                        return;
                    }
                    span = $(btn).parent();
                    if ($(">ul", span).length === 0 && !span.hasClass(css_ribbon_accesstoolbar)) {
                        //for access bar: it need not to be groups
                        self.groups.push(span);
                    } else {
                        if ($(">button", span).length === 2) {
                            self.splits.push(span);
                        } else if ($(">button", span).length === 1) {
                            self.dropdowns.push(span);
                        } else if ($(">input[type='text']", span).length === 1) {
                            self.inputDropdowns.push(span);
                        }
                    }
                    return this;
                });
                self.groups = self._unique(self.groups);
                self.splits = self._unique(self.splits);
            };

            wijribbon.prototype._unique = function (group) {
                var array = $.makeArray($.map(group, function (n) {
                    return n.get(0);
                }));
                return $.map($.unique(array), function (n) {
                    return $(n);
                });
            };

            wijribbon.prototype._createButtons = function () {
                var self = this, element = self.element;

                $(":checkbox", element).each(function () {
                    if (self._isCustomTypeEle($(this))) {
                        return;
                    }
                    self._createButton($(this), "checkbox");

                    //update for 36511 issue for jquery ui 1.10: button interface changed
                    $(this).bind("change", function () {
                        self._addActiveClassToLabelButtonText($(this).button("widget")[0]);
                    });

                    return this;
                });

                $(":radio", element).each(function () {
                    if (self._isCustomTypeEle($(this))) {
                        return;
                    }
                    self._createButton($(this), "radio");
                    $(this).bind("change", function () {
                        self._addActiveClassToLabelButtonText($(this).button("widget")[0]);
                    });
                    return this;
                });

                $("button", element).each(function () {
                    if (self._isCustomTypeEle($(this))) {
                        return;
                    }
                    self._createButton($(this), "button");

                    return this;
                });
            };

            wijribbon.prototype._isCustomTypeEle = function (ele) {
                if (!ele)
                    return false;

                return ele.parents("[customtype]") && ele.parents("[customtype]").length !== 0;
            };

            wijribbon.prototype._createButton = function (button, type) {
                var self = this, wijCSS = this.options.wijCSS, options = self._buildButtonOption(button, type), name = button.data("commandName"), labelEle;

                button.button(options);
                if (!options.text) {
                    if (type === "button") {
                        button.children("." + wijCSS.buttonText).text(name);
                    } else {
                        labelEle = $("[for='" + button.attr("id") + "']", button.parent());
                        if (labelEle) {
                            labelEle.children("." + wijCSS.buttonText).text(name);
                        }
                    }
                }

                //for access toolbar buttons
                if (button.parent().is("." + css_ribbon_accesstoolbar) && button.attr("canlocateonaccesstoolbar") === "true") {
                    button.button("widget").hide();
                }

                self._triggerEvent(button);
            };

            wijribbon.prototype._createGroup = function () {
                $.each(this.groups, function (i, group) {
                    group.buttonset();
                });
            };

            wijribbon.prototype._createSplit = function () {
                var self = this, wijCSS = this.options.wijCSS;

                $.each(self.splits, function (i, split) {
                    var list = split.children("ul"), content = split.children("button:eq(0)"), splitName = content.data("commandName"), triggerEle = split.children("button:eq(1)"), splitObj;

                    list.children("li").addClass(wijCSS.cornerAll);
                    split.addClass(css_ribbon + "-" + splitName);

                    triggerEle.button({ icons: { primary: wijCSS.iconArrowDown }, text: false }).data("list", list).unbind("click").bind("click", function (e) {
                        self._preventDefaultEvent(e);
                    }).bind("mouseup", function (e) {
                        list = $(this).data("list");
                        if (list.is(":visible")) {
                            self.showList.hide().css("z-index", "");
                            self.showList = null;
                        } else {
                            list.show().position({
                                my: 'left top', at: 'left bottom',
                                of: split
                            }).css("z-index", 9999);
                            self.showList = list;
                        }
                        self._preventDefaultEvent(e);
                    });

                    triggerEle.children("." + wijCSS.buttonText).text("foo");

                    split.after(list);
                    list.css("position", "absolute").addClass(wijCSS.helperReset + " " + wijCSS.helperClearFix + " " + wijCSS.cornerAll + " " + css_ribbon_dropdown).hide();
                    split.buttonset();

                    splitObj = {
                        ui: content,
                        defaultValue: content.button("option", "label"),
                        buttons: [],
                        type: "split",
                        trigger: triggerEle,
                        list: list
                    };

                    $("button, :checkbox, :radio", list).bind("click", function (e) {
                        list.hide().css("z-index", "");
                        self.showList = null;
                        e.preventDefault();
                    });

                    list.find(">li>button,>li>:radio,>li>:checkbox").each(function (i, button) {
                        var commandName = $(button).data("commandName");
                        if (commandName !== "" && self.buttons[commandName]) {
                            self.buttons[commandName].parent = content;
                            self.buttons[commandName].type = "split";
                        }
                        splitObj.buttons.push($(button));
                    });

                    if (splitName !== "") {
                        self.listUis[splitName] = splitObj;
                    }
                });
            };

            wijribbon.prototype._createDropdwon = function () {
                var self = this, wijCSS = this.options.wijCSS, code, keyCode;

                self.dropdownLabels = {};
                $.each(self.dropdowns, function (i, dropdown) {
                    var list = dropdown.children("ul"), button = dropdown.children("button:eq(0)"), dropdownName = button.data("commandName"), dropdownObj;

                    list.children("li").addClass(wijCSS.cornerAll + " " + wijCSS.stateDefault);

                    dropdown.addClass(css_ribbon + "-" + dropdownName);

                    button.button({ icons: { secondary: wijCSS.iconArrowDown } }).unbind("click").bind("click", function (e) {
                        self._preventDefaultEvent(e);
                    }).bind("mouseup", function (e) {
                        self._showDropDownList(list, button);
                        self._preventDefaultEvent(e);
                    }).bind("keydown", function (e) {
                        if (!list.is(":visible")) {
                            return;
                        }
                        self._dropdownListKeyHandler(e, list, button);
                    });

                    dropdownObj = {
                        ui: button,
                        defaultValue: button.button("option", "label"),
                        buttons: [],
                        type: "dropdown",
                        list: list
                    };

                    $("button, :checkbox, :radio", list).bind("click", function (e) {
                        var name = $(this).data("commandName"), label, width = button.children("." + wijCSS.buttonText).width();
                        if (!self.dropdownLabels[name]) {
                            self.dropdownLabels[name] = self._getDropdownLabelSubstr($(this).button("option", "label"), button.children("." + wijCSS.buttonText), width);
                        }
                        label = self.dropdownLabels[name];
                        button.button("option", "label", label);
                        button.attr("title", $(this).button("option", "label"));
                        list.hide().css("z-index", "");
                        self.showList = null;
                        e.preventDefault();
                    });

                    //dropdown.after(list);
                    list.css("position", "absolute").addClass(wijCSS.helperReset + " " + wijCSS.helperClearFix + " " + wijCSS.cornerAll + " " + css_ribbon_dropdown).hide();

                    dropdown.buttonset({ items: " >button, >:checkbox, >:radio" });
                    self._collectDropDownButtons(list, button, dropdownObj, dropdownName);
                });
            };

            wijribbon.prototype._createInputDropdown = function () {
                var self = this, wijCSS = this.options.wijCSS;

                self.dropdownLabels = {};

                //create input dropdown
                $.each(self.inputDropdowns, function (i, dropdown) {
                    var list = dropdown.children("ul"), inputEle = dropdown.children("input[type='text']:eq(0)"), inputDropDownWrapper = self._createInputDropDownWrapper(inputEle), dropdownName = inputEle.prop("name"), dropdownObj;

                    dropdown.prepend(inputDropDownWrapper);
                    list.children("li").addClass(wijCSS.cornerAll + " " + wijCSS.stateDefault);

                    dropdown.addClass(css_ribbon + "-" + dropdownName);
                    inputEle.removeProp("name").data("commandName", dropdownName).addClass(wijCSS.stateDefault + " " + wijCSS.content + " " + wijCSS.cornerLeft);

                    inputDropDownWrapper.find("a").bind("mouseup", function (e) {
                        self._showDropDownList(list, inputEle);
                        inputEle.focus();
                        self._preventDefaultEvent(e);
                    }).bind("keydown", function (e) {
                        self._dropdownListKeyHandler(e, list, inputDropDownWrapper);
                    });

                    self._bindInputEvent(inputEle, list);

                    dropdownObj = {
                        ui: inputEle,
                        defaultValue: inputEle.val(),
                        buttons: [],
                        type: "dropdown",
                        list: list
                    };

                    $("button, :checkbox, :radio", list).bind("click", function (e) {
                        var name = $(this).data("commandName"), label;

                        /*TODO: remove the code*/
                        if (!self.dropdownLabels[name]) {
                            self.dropdownLabels[name] = $(this).button("option", "label");
                        }

                        label = self.dropdownLabels[name];
                        inputEle.val($(this).button("option", "label")).attr("title", $(this).button("option", "label"));
                        list.hide().css("z-index", "");
                        self.showList = null;
                        self._preventDefaultEvent(e);
                    });

                    //dropdown.after(list);
                    list.css("position", "absolute").addClass(wijCSS.helperReset + " " + wijCSS.helperClearFix + " " + wijCSS.cornerAll + " " + css_ribbon_dropdown).hide();

                    //dropdown.buttonset();
                    self._collectDropDownButtons(list, inputEle, dropdownObj, dropdownName);
                });
            };

            wijribbon.prototype._collectDropDownButtons = function (list, parentEle, dropdownObj, dropdownName) {
                var self = this;

                list.find(">li>button,>li>:radio,>li>:checkbox").each(function (i, btn) {
                    var commandName = $(btn).data("commandName");
                    if (commandName !== "" && self.buttons[commandName]) {
                        self.buttons[commandName].parent = parentEle;
                        self.buttons[commandName].type = "dropdown";
                    }
                    dropdownObj.buttons.push($(btn));
                });

                // cache a hash to save the dropdown.
                if (dropdownName !== "") {
                    self.listUis[dropdownName] = dropdownObj;
                }
            };

            wijribbon.prototype._showDropDownList = function (list, buttonEle) {
                var self = this;

                if (list.is(":visible") && !list.find("li." + self.options.wijCSS.stateActive)) {
                    self.showList.hide().css("z-index", "");
                    self.showList = null;
                } else {
                    if (self.showList) {
                        self.showList.hide();
                        self.showList = null;
                    }
                    list.show().position({ my: 'left top', at: 'left bottom', of: buttonEle }).css("z-index", 9999);
                    self.showList = list;
                    self.isShow = true;
                }
            };

            wijribbon.prototype._bindInputEvent = function (inputEle, list) {
                var self = this, code, keyCode;

                //bind input change event
                inputEle.bind("change", function (e) {
                    var obj = { name: undefined, commandName: undefined };

                    obj.name = inputEle.prop("name");
                    obj.commandName = inputEle.val();
                    self._trigger("click", e, obj);
                }).bind("keydown", function (event) {
                    self._dropdownListKeyHandler(event, list, inputEle);
                });
            };

            wijribbon.prototype._dropdownListKeyHandler = function (event, list, container) {
                var self = this, code = event.keyCode, keyCode = self._getKeyCodeEnum();

                switch (code) {
                    case keyCode.UP:
                        self._activeDropDownListElement(false, list, container);
                        event.preventDefault();
                        break;
                    case keyCode.DOWN:
                        self._activeDropDownListElement(true, list, container);
                        event.preventDefault();
                        break;
                    case keyCode.ENTER:
                        list.find("label." + self.options.wijCSS.stateActive).parent("li").find("input").trigger("click");
                        event.preventDefault();
                        break;
                }
            };

            wijribbon.prototype._activeDropDownListElement = function (down, list, inputEle) {
                var self = this, len = list.find("li").length, activeIndex, activeItem;

                if (!list.is(":visible")) {
                    self._showDropDownList(list, inputEle);
                    return;
                }
                activeItem = list.find("label." + self.options.wijCSS.stateActive).parent("li");
                if (activeItem && activeItem.length > 0) {
                    activeIndex = list.find("li").index(activeItem);
                }

                //list.find("li").removeClass("ui-state-active");
                self._changeListItemActiveState(activeItem, false);
                if (activeIndex === undefined) {
                    activeIndex = 0;
                } else {
                    if (down) {
                        activeIndex++;
                        if (activeIndex == len) {
                            activeIndex = undefined;
                        }
                    } else {
                        activeIndex--;
                        if (activeIndex == -1) {
                            activeIndex = len - 1;
                        }
                    }
                }
                self._changeListItemActiveState($(list.find("li")[activeIndex]), true);
            };

            wijribbon.prototype._changeListItemActiveState = function (listitem, activate) {
                var wijCSS = this.options.wijCSS;

                if (!listitem) {
                    return;
                }
                $("label", listitem).toggleClass(wijCSS.stateActive, activate);
                $("span", listitem).toggleClass(wijCSS.stateActive, activate);
            };

            wijribbon.prototype._createGallery = function () {
                var self = this, wijCSS = self.options.wijCSS;

                // create the style gallery
                $(".wijmo-wijribbon-gallery", self.element).each(function (i, gallery) {
                    $(gallery).children("div").each(function (i, unitDiv) {
                        $(unitDiv).bind("mouseenter", function (e) {
                            if ($(unitDiv).hasAllClasses(wijCSS.stateDisabled)) {
                                return;
                            }
                            $(unitDiv).addClass(wijCSS.stateHover);
                        }).bind("mouseleave", function (e) {
                            if ($(unitDiv).hasAllClasses(wijCSS.stateDisabled)) {
                                return;
                            }
                            $(unitDiv).removeClass(wijCSS.stateHover);
                        }).bind("click", function (e) {
                            if ($(unitDiv).hasAllClasses(wijCSS.stateDisabled)) {
                                return;
                            }
                            $(unitDiv).parent("div.wijmo-wijribbon-gallery").children("div").removeClass(wijCSS.stateActive);
                            $(unitDiv).addClass(wijCSS.stateActive);
                            var obj = { name: undefined, commandName: undefined };
                            obj.name = $(unitDiv).parent("div.wijmo-wijribbon-gallery").attr("name");
                            obj.commandName = $(unitDiv).attr("name");
                            self._trigger("click", e, obj);
                        });

                        //add button to self.buttons for update state
                        self.buttons[$(unitDiv).attr("name")] = { button: $(unitDiv), type: "galleryBtn" };
                    });
                });
            };

            wijribbon.prototype._getKeyCodeEnum = function () {
                if ($.ui && $.ui.keyCode) {
                    return $.ui.keyCode;
                }

                if ($.mobile && $.mobile.keyCode) {
                    return $.mobile.keyCode;
                }

                throw "keyCode object is not found";
            };

            wijribbon.prototype._createInputDropDownWrapper = function (inputEle) {
                var wijCSS = this.options.wijCSS;
                var inputDropDownWrapper = $("<span class='wijmo-wijribbon-inputdropdownwrapper'></span>").append(inputEle);
                $("<a></a>").appendTo(inputDropDownWrapper).button({
                    icons: {
                        primary: wijCSS.iconArrowDown
                    },
                    text: false
                }).removeClass(wijCSS.cornerAll).addClass("wijmo-wijribbon-inputdropdownbtn " + wijCSS.cornerRight);

                return inputDropDownWrapper;
            };

            wijribbon.prototype._createTab = function () {
                var self = this, wijCSS = this.options.wijCSS, element = self.element, startMenu = $("." + css_ribbon_startmenu, element);

                element.addClass(css_ribbon);
                self.tabEle = element;

                if ($(">ul", element).length > 0) {
                    element.wijtabs({
                        select: function (e, args) {
                            self._hideAllMenus();
                        }
                    });
                    self._createRibbonGroups();
                    element.wijtabs({
                        show: function (e, args) {
                            self.updateRibbonSize();
                        }
                    });
                    if (startMenu && startMenu.length > 0) {
                        element.wijtabs("option", "selected", 1);
                        self._createStartMenu();
                    }
                    return true;
                } else {
                    element.addClass(css_ribbon + "-simple" + " " + wijCSS.stateDefault + " " + wijCSS.helperClearFix);
                }

                return false;
            };

            wijribbon.prototype._createAccessToolBar = function () {
                var self = this, newId, accessBarDiv = $("<div class='" + css_ribbon_accesstoolbar + "'></div>"), menuBtn;

                if ($("*[canlocateonaccesstoolbar='true']", self.element).length === 0 && $("*[locateonaccesstoolbar='true']", self.element).length === 0) {
                    return;
                }

                //collect accessbar button
                $("input[canlocateonaccesstoolbar='true'],input[locateonaccesstoolbar='true']", self.element).each(function () {
                    newId = $(this).attr("id") + "_accessbar";
                    var labelEle = $("label[for=" + $(this).attr("id") + "]");
                    self.accessbarBtns[labelEle.attr("title")] = {
                        button: $(this).clone().attr("id", newId),
                        type: $(this).attr("type"),
                        labelEle: labelEle.clone().attr("for", newId),
                        selected: $(this).attr("locateonaccesstoolbar") === "true" ? true : false
                    };
                });

                $("button[canlocateonaccesstoolbar='true'],button[locateonaccesstoolbar='true']", self.element).each(function () {
                    newId = $(this).attr("id") + "_accessbar";
                    self.accessbarBtns[$(this).attr("title")] = {
                        button: $(this).clone(),
                        type: 'button',
                        selected: $(this).attr("locateonaccesstoolbar") === "true" ? true : false
                    };
                });

                $.each(self.accessbarBtns, function (key, btnObj) {
                    accessBarDiv.append(btnObj.button);
                    if (btnObj.labelEle) {
                        accessBarDiv.append(btnObj.labelEle);
                    }
                });

                //show menu button
                menuBtn = $('<button title="Customize Access Toolbar" class ="wijmo-wijribbon-accesstoolbarbtn ' + self.options.wijCSS.iconArrowDown + '"' + ' name="quicktoolbar"></button>');
                accessBarDiv.append(menuBtn);

                //TODO: check null: there is no button on accessbar
                if (self.accessbarBtns) {
                    self.element.prepend(accessBarDiv);
                }

                //create menu
                self._createCustomQuickToolbarMenu(menuBtn, accessBarDiv);
            };

            wijribbon.prototype._createCustomQuickToolbarMenu = function (triggerEle, appendToEle) {
                var self = this, liEle, checkedCss, wijCSS = self.options.wijCSS, customQuickToolbarMenu = $('<ul class="' + css_ribbon_accesstoolbarmenu + '"></ul>');

                $.each(self.accessbarBtns, function (key, item) {
                    checkedCss = item.selected ? ' ' + css_ribbon_accesstoolbarmenuitemchecked : ' ' + css_ribbon_accesstoolbarmenuitemunchecked;
                    liEle = $('<li><a class="' + wijCSS.cornerAll + '" tabindex="-1">' + '<span class="' + wijCSS.icon + checkedCss + '"></span><span' + ' class="wijmo-wijmenu-text">' + key + '</span></a></li>');
                    liEle.data("accessbarcommand", key);
                    customQuickToolbarMenu.append(liEle);
                });

                //set title
                customQuickToolbarMenu.prepend("<li class='" + css_ribbon_accesstoolbarmenutitleitem + "'><a>Customize Access Toolbar</a></li>");

                appendToEle.append(customQuickToolbarMenu);

                // select the start menu function
                customQuickToolbarMenu.wijmenu({
                    trigger: triggerEle,
                    triggerEvent: "click",
                    orientation: "vertical",
                    select: function (e, item) {
                        var liEle = item.item, btnName = liEle.element.data("accessbarcommand"), iconSpan = $("span." + wijCSS.icon, liEle.element), accessBarBtn = self.accessbarBtns[btnName].button, btnWidget = accessBarBtn.button("widget"), itemChecked = iconSpan.hasClass(css_ribbon_accesstoolbarmenuitemchecked);

                        iconSpan.toggleClass(css_ribbon_accesstoolbarmenuitemchecked, !itemChecked).toggleClass(css_ribbon_accesstoolbarmenuitemunchecked, itemChecked);

                        if (itemChecked) {
                            btnWidget.hide().removeAttr("canlocateonaccesstoolbar").attr("locateonaccesstoolbar", "true");
                        } else {
                            btnWidget.show().removeAttr("locateonaccesstoolbar").attr("canlocateonaccesstoolbar", "true");
                        }

                        //deactivate
                        customQuickToolbarMenu.wijmenu("deactivate", null);
                    }
                });

                customQuickToolbarMenu.wijmenu("setItemDisabled", $("." + css_ribbon_accesstoolbarmenutitleitem), true);
            };

            /** @ignore */
            wijribbon.prototype.updateRibbonSize = function () {
                var self = this, groupDropDown, wijCSS = this.options.wijCSS, abbrevgroupContainer;

                self.tabEle.children("div").not(".wijmo-wijmenu").each(function (i, tabPage) {
                    var $tabPage = $(tabPage), isTabVisible = $tabPage.is(":visible"), groups = $tabPage.find(">ul>li:not(.wijmo-wijmenu-item)"), groupInfos = [], pageWidth = $tabPage.width();

                    if (!isTabVisible) {
                        self._showTabPage($tabPage);
                        pageWidth = $tabPage.width();
                    }

                    groups.each(function (j, li) {
                        var group = $(li), lblDiv = group.find(">div:last"), text = self._getGroupLabel(lblDiv);
                        groupDropDown = group.children("." + css_ribbon_dropdowngroup);
                        abbrevgroupContainer = group.children("." + css_ribbon_abbrevgroup);
                        if (groupDropDown) {
                            group.addClass(css_ribbon + "-" + text.toLowerCase()).prepend(groupDropDown.children());
                            groupDropDown.remove();
                            if (abbrevgroupContainer) {
                                abbrevgroupContainer.remove();
                            }
                        }

                        //end
                        groupInfos.push({
                            width: group.outerWidth(true),
                            text: text
                        });
                        return this;
                    });

                    self._adjustRibbonGroupIfNeeded(groups, groupInfos, pageWidth);

                    if (!isTabVisible) {
                        self._hideTabPage($tabPage);
                    }
                    return this;
                });

                if (self._isDisabled()) {
                    self._setDisabled(true);
                }
            };

            wijribbon.prototype._createRibbonGroups = function () {
                var self = this, wijCSS = this.options.wijCSS;

                self.tabEle.children("div").each(function (i, tabPage) {
                    var $tabPage = $(tabPage), isTabVisible = $tabPage.is(":visible"), groups = $tabPage.find(">ul:not(." + css_ribbon_accesstoolbarmenu + ")>li"), groupInfos = [], pageWidth;

                    //update for fixed issue 21292 by wh at 2012/5/8
                    if ($tabPage.data("destroy.tabs")) {
                        $tabPage.remove();
                        return;
                    }

                    //end
                    if (!isTabVisible) {
                        self._showTabPage($tabPage);
                    }

                    pageWidth = $tabPage.width();

                    $tabPage.addClass(css_ribbon_panel);

                    // remove for use another method to create
                    //add for access toolbar mark
                    if (!$tabPage.hasAllClasses(wijCSS.tabsPanel)) {
                        $tabPage.addClass(css_ribbon_accesstoolbar);
                        self.tabEle.prepend($tabPage);
                    }
                    $tabPage.find(">ul").addClass(wijCSS.helperReset + " " + wijCSS.helperClearFix + " " + wijCSS.content + " " + wijCSS.cornerAll + " " + css_ribbon_groups);

                    groups.each(function (j, li) {
                        var group = $(li), lblDiv = group.find(">div:last"), groupSpanText = lblDiv.find("span"), css = wijCSS.stateDefault + " " + css_ribbon_group, text = self._getGroupLabel(lblDiv);

                        if (lblDiv) {
                            css += " " + css_ribbon + "-" + text.toLowerCase();
                        }
                        group.addClass(css);

                        lblDiv.addClass(css_ribbon_grouplabel).bind("click", function () {
                            return false;
                        });
                        group.wrapInner("<div class = '" + css_ribbon_groupcontent + "'></div>");
                        group.children().bind("mouseover", function () {
                            $(this).addClass(wijCSS.stateHover);
                        }).bind("mouseout", function () {
                            $(this).removeClass(wijCSS.stateHover);
                        });
                        lblDiv.appendTo(group);
                        groupInfos.push({
                            width: group.outerWidth(true),
                            text: text
                        });
                        return this;
                    });

                    self._originalGroupInfo = groupInfos;

                    self._adjustRibbonGroupIfNeeded(groups, groupInfos, pageWidth);

                    if (!isTabVisible) {
                        self._hideTabPage($tabPage);
                    }
                    return this;
                });
            };

            wijribbon.prototype._createStartMenu = function () {
                var self = this, startMenuLink = $("." + css_ribbon_startmenulink, self.element), wijCSS = self.options.wijCSS;

                startMenuLink.unbind("click");

                // mark the tab as a start menu link
                startMenuLink.parent("li").addClass(css_ribbon_startmenulinkcontainer).hover(function () {
                    $(this).toggleClass(css_ribbon_startmenulinkcontainer);
                });

                //add start menu indicator
                $("." + css_ribbon_startmenuindicator, self.element).addClass(wijCSS.icon + " " + wijCSS.iconArrowDown);

                // select the start menu function
                $("." + css_ribbon_startmenu, self.element).wijmenu({
                    trigger: startMenuLink.parent(),
                    triggerEvent: "click",
                    orientation: "vertical",
                    select: function (e, item) {
                        var obj = { name: undefined, commandName: undefined };
                        obj.commandName = item.item._link.attr("name");
                        self._trigger("click", e, obj);
                    },
                    hidden: function (e, item) {
                        if (item.activeItem) {
                            item.activeItem._link.removeClass(wijCSS.stateFocus);
                        }
                    }
                });
            };

            wijribbon.prototype._getGroupLabel = function (lblDiv, findText) {
                var groupSpanText, text;
                if (lblDiv) {
                    groupSpanText = lblDiv.find("span");
                    if (lblDiv.attr("displayname") && !findText) {
                        text = lblDiv.attr("displayname");
                    } else {
                        if (groupSpanText && groupSpanText.length > 0 && !lblDiv.hasAllClasses(css_ribbon_abbrevgroup)) {
                            text = $(groupSpanText[0]).text();
                        } else {
                            text = $.trim(lblDiv.text());
                        }
                    }
                }
                return text;
            };

            wijribbon.prototype._adjustRibbonGroupIfNeeded = function (groups, groupInfos, pageWidth) {
                var self = this, i = groups.length - 1, j = 0, iWidth = 0, jWidth = 0, groupDropDown, abbrevgroupContainer, gi;

                for (; i >= 0; i--) {
                    jWidth = 0;
                    for (j = 0; j < i; j++) {
                        jWidth += groupInfos[j].width;
                    }

                    if (jWidth + iWidth + groupInfos[i].width <= pageWidth && !self.options.compactMode) {
                        //remove the dropdowngroup and add dropdowngroup's children to group
                        groupDropDown = $(groups[i]).children("." + css_ribbon_dropdowngroup);
                        abbrevgroupContainer = $(groups[i]).children("." + css_ribbon_abbrevgroup);
                        if (groupDropDown) {
                            $(groups[i]).addClass(css_ribbon + "-" + groupInfos[i].text.toLowerCase()).prepend(groupDropDown.children());
                            groupDropDown.remove();
                            if (abbrevgroupContainer) {
                                abbrevgroupContainer.remove();
                            }
                            //continue;
                        }
                    } else {
                        gi = groupInfos[i];
                        iWidth += self._createDropDownRibbonGroup(gi.text, groups[i]);
                    }
                }
            };

            wijribbon.prototype._createDropDownRibbonGroup = function (text, group) {
                var self = this, grpClass = css_ribbon + "-" + text.toLowerCase(), wijCSS = this.options.wijCSS, $group = $(group).removeClass(grpClass), displayName = self._getGroupLabel($group.find(">div:last")) || text, displayText = self._getGroupLabel($group.find(">div:last"), true) || text, $abbrevgrp;

                $group.wrapInner("<div class='" + css_ribbon_dropdowngroup + " " + css_ribbon_group + "'></div>").children().hide().addClass(grpClass).bind("mouseup." + self.widget, function (e) {
                    if (self.showDrpDwnGroup !== null) {
                        self.showDrpDwnGroup.hide().css("z-index", "");
                        self.showDrpDwnGroup = null;
                    }
                });

                $abbrevgrp = $("<div class='" + css_ribbon_abbrevgroup + "'>" + "<span class='" + css_ribbon_abbrev + displayName.toLowerCase() + " " + css_ribbon_icon + " " + css_ribbon_abbrevicon + "'></span>" + "<span class='" + css_ribbon_text + "'>" + displayText + "</span>" + "<span class='" + wijCSS.icon + " " + wijCSS.iconArrowDown + " " + css_ribbon_icon + "'></span></div>").appendTo($group).unbind(self.widget).bind("mouseover." + self.widget, function (e) {
                    $(this).addClass(wijCSS.stateHover);
                }).bind("mouseout." + self.widget, function (e) {
                    $(this).removeClass(wijCSS.stateHover);
                }).bind("click." + self.widget, function (e) {
                    var $drpGroup = $(this).siblings("." + css_ribbon_dropdowngroup);

                    if ($drpGroup.is(":visible")) {
                        $drpGroup.hide().css("z-index", "");
                        self.showDrpDwnGroup = null;
                    } else {
                        if (self.showDrpDwnGroup) {
                            self.showDrpDwnGroup.hide().css("z-index", "");
                        }

                        $drpGroup.show().position({
                            my: "left top",
                            at: "left bottom",
                            of: this
                        }).css("z-index", "10000");
                        self.showDrpDwnGroup = $drpGroup;
                        e.stopPropagation();
                    }
                });
                return $group.outerWidth(true);
            };

            wijribbon.prototype._hideShowedList = function () {
                var self = this;
                $(document).bind("mouseup", function (e) {
                    var target = e.target;

                    if (self.showList) {
                        if ($(target).is(document) || !$.contains(self.showList.get(0), target)) {
                            self.showList.hide().css("z-index", "");
                            self.showList = null;
                        }
                    }

                    if (self.showDrpDwnGroup) {
                        if ($(target).is(document) || !$.contains(self.showDrpDwnGroup.get(0), target)) {
                            self.showDrpDwnGroup.hide().css("z-index", "");
                            self.showDrpDwnGroup = null;
                        }
                    }
                });
            };

            wijribbon.prototype._hideTabPage = function (tabPage) {
                if (tabPage) {
                    tabPage.hide();
                }
            };

            wijribbon.prototype._showTabPage = function (tabPage) {
                if (tabPage) {
                    tabPage.show();
                }
            };

            wijribbon.prototype._buildButtonOption = function (node, type) {
                var text = true, self = this, nodeClass = node.attr("class"), spans, iconClass, iconEle, imagePosition, label, labelEle, name;

                // only icon
                if (nodeClass && nodeClass !== "" && nodeClass !== css_ribbon_bigbutton) {
                    iconClass = nodeClass.split(" ")[0];
                    node.removeClass(iconClass);
                    label = $.trim(node.text());
                    if (label === "") {
                        text = false;
                    }
                } else {
                    if (type === "checkbox" || type === "radio") {
                        if ($.trim(node.attr("id")) === "") {
                            return;
                        }
                        labelEle = $("[for='" + node.attr("id") + "']", node.parent());
                        if (!labelEle.is("label")) {
                            return;
                        }

                        nodeClass = labelEle.attr("class");
                        if (nodeClass && nodeClass !== "" && nodeClass !== css_ribbon_bigbutton) {
                            iconClass = nodeClass.split(" ")[0];
                            labelEle.removeClass(iconClass);
                            label = $.trim(labelEle.text());
                            if (label === "") {
                                text = false;
                            }
                        } else {
                            //TODO only text
                            spans = labelEle.children("span,div");
                        }
                    } else if (type === "button") {
                        spans = node.children("span,div");
                    }

                    if (spans) {
                        if (spans.length === 1) {
                            //only image
                            if (spans.eq(0).attr("class") !== "") {
                                iconEle = spans.eq(0);
                                iconClass = iconEle.attr("class");
                                text = false;
                            }
                            // to do only text
                        } else if (spans.length === 2) {
                            if (spans.eq(0).attr("class")) {
                                iconEle = spans.eq(0);
                                iconClass = iconEle.attr("class");
                                if (iconEle.is("span")) {
                                    imagePosition = "left";
                                } else if (iconEle.is("div")) {
                                    imagePosition = "top";
                                }

                                label = spans.eq(1).text();
                            }
                            // TODO: Text before image.
                            // TODO: Text above image.
                        } else {
                            if (type === "button" && $.trim(node.text()) !== "") {
                                label = $.trim(node.text());
                            }
                        }
                    }
                }

                if (type === "button") {
                    node.empty();
                    name = $.trim(node.attr("name"));
                    if (name !== "") {
                        node.removeAttr("name");
                    }
                } else {
                    name = $.trim(labelEle.attr("name"));
                    if (name !== "") {
                        labelEle.removeAttr("name");
                    }
                }

                if (name !== "") {
                    node.data("commandName", name);
                    if (!self.buttons[name]) {
                        self.buttons[name] = { button: undefined, accessToolbarButton: undefined };
                    }
                    if (node.parent().is("." + css_ribbon_accesstoolbar)) {
                        self.buttons[name].accessToolbarButton = node;
                    } else {
                        self.buttons[name].button = node;
                    }
                }

                return {
                    label: label, icons: { primary: iconClass },
                    position: imagePosition, text: text
                };
            };

            wijribbon.prototype._triggerEvent = function (button) {
                var self = this, sameBtn, btnWidget, wijCSS = self.options.wijCSS;
                button.bind("click", function (e) {
                    if (self._isDisabled()) {
                        self._preventDefaultEvent(e);
                        return;
                    }

                    self._hideAllMenus();

                    var checked = true, commandName = button.data("commandName"), buttonObj = self.buttons[commandName], obj = { name: undefined, commandName: undefined };

                    if (self.actions && self.actions[commandName]) {
                        self.actions[commandName]();
                    } else {
                        if (buttonObj && buttonObj.parent) {
                            obj.name = buttonObj.parent.data("commandName");
                        }
                        obj.commandName = commandName;
                        self._trigger("click", e, obj);
                    }

                    if (button.parent().is("." + css_ribbon_accesstoolbar)) {
                        sameBtn = self.buttons[commandName].button;
                    } else {
                        sameBtn = self.buttons[commandName].accessToolbarButton;
                    }

                    if (sameBtn) {
                        btnWidget = sameBtn.button("widget");
                        if (!sameBtn.is("button")) {
                            //for bootstrap, the jquery-ui button will not append
                            //if (btnWidget && btnWidget.hasAllClasses(wijCSS.stateActive))
                            if (btnWidget && btnWidget.hasAllClasses(css_active_state)) {
                                checked = false;
                            }
                            self._setBtnWidgetCheckedStyle(sameBtn, checked);
                        }
                    }

                    // if is button to prevent submit form
                    if (button.is("button")) {
                        self._preventDefaultEvent(e);
                    }
                });
            };

            wijribbon.prototype._getDropdownLabelSubstr = function (text, label, width) {
                var self = this, length = text.length, start = 0, end = length, mid = Math.floor((start + end) / 2), newLabel = $("<span></span>"), str = text.substr(0, mid), midWidth;

                newLabel.appendTo(label.parent());
                midWidth = self._calculateWidth(str, newLabel);

                while (midWidth !== width && end > start) {
                    str = text.substr(0, mid + 1);
                    midWidth = self._calculateWidth(str, newLabel);
                    if (midWidth > width) {
                        end = mid - 1;
                    } else if (midWidth < width) {
                        start = mid + 1;
                    }
                    mid = Math.floor((start + end) / 2);
                }
                newLabel.remove();
                return str;
            };

            wijribbon.prototype._calculateWidth = function (str, span) {
                span.text(str);
                return span.width();
            };

            /** @ignore */
            wijribbon.prototype.hideDropdown = function (name) {
                var self = this, dropdown = self.listUis[name];

                if (dropdown && dropdown.list) {
                    dropdown.list.hide();
                }
            };

            /** @ignore */
            wijribbon.prototype._hideAllMenus = function () {
                var self = this;

                $(".wijmo-wijmenu", self.tabEle).hide();
            };

            /** Sets a ribbon tab page as visible or not.
            * @param {string} id The id of the tab page.
            * @param {boolean} visible The visible state of the tab page.
            */
            wijribbon.prototype.setTabPageVisible = function (id, visible) {
                var self = this, tabpage = $("a[href=#" + id + "]", self.element).parent("li"), tab = tabpage.parent("ul"), selectedIndex;

                if (tabpage && tabpage.length > 0) {
                    if (visible) {
                        tabpage.show();

                        //set the current show tab to selected
                        selectedIndex = $('li', tab).index(tabpage);
                    } else {
                        tabpage.hide();

                        //then change to select first visible tab
                        selectedIndex = $('li', tab).index($('li:visible:not(".' + css_ribbon_startmenulinkcontainer + '")', tab));
                    }
                }
                self.element.wijtabs("option", "selected", selectedIndex);
            };

            /**
            * Remove the functionality completely. This will return the element back to its pre-init state.
            */
            wijribbon.prototype.destroy = function () {
                if (this.disabledModal) {
                    this.disabledModal.remove();
                }
                if (this.element.data("wijmo-wijtabs")) {
                    this.element.wijtabs("destroy");
                }
                this.element.removeClass().html(this.nativeMarkup);
                this.element.attr("class", this.nativeClass ? this.nativeClass : "");
                this.nativeMarkup = null;
                this.nativeClass = null;
                $(window).unbind("resize.wijribbon");
                _super.prototype.destroy.call(this);
            };

            /** @ignore */
            wijribbon.prototype.getDropdownList = function (name) {
                var self = this, dropdown = self.listUis[name], retrunObj = {};

                if (dropdown) {
                    $.each(dropdown.buttons, function (i, button) {
                        retrunObj[button.data("commandName")] = button.button("option", "label");
                    });
                }

                return retrunObj;
            };

            /** The method sets the chosen button as enabled or disabled according to the command name.
            * @param {string} commandName The name of the command.
            * @param {boolean} disabled The disabled state of the button, true or false.
            */
            wijribbon.prototype.setButtonDisabled = function (commandName, disabled) {
                var buttonObj = this.buttons[commandName], wijCSS = this.options.wijCSS, btnText, accessBarBtnText, isButtonEle = false, button, accessBarBtn, splitUi, childButton, caption;

                //for custom button
                if (buttonObj && buttonObj.disabled) {
                    buttonObj.disabled(disabled);
                    return;
                }

                if (buttonObj && buttonObj.button && buttonObj.type === "galleryBtn") {
                    buttonObj.button.addClass(wijCSS.stateDisabled);
                }
                if (buttonObj && buttonObj.button) {
                    button = buttonObj.button;
                    accessBarBtn = buttonObj.accessToolbarButton;
                    isButtonEle = button.is("button");

                    //for gallery btn
                    if (buttonObj.type === "galleryBtn") {
                        button.toggleClass(wijCSS.stateDisabled, disabled);
                        return;
                    }

                    button.button("option", "disabled", disabled);
                    btnText = $("." + wijCSS.buttonText, button);
                    if (btnText) {
                        btnText.removeClass(wijCSS.stateHover);
                    }
                    if (accessBarBtn) {
                        accessBarBtn.button("option", "disabled", disabled);
                        accessBarBtnText = $("." + wijCSS.buttonText, accessBarBtn);
                        if (accessBarBtnText) {
                            accessBarBtnText.removeClass(wijCSS.stateHover);
                        }
                    }
                    if (isButtonEle) {
                        // when the keypress, the button text will be happen change
                        // For "Save" to "save"
                        if (commandName !== "save") {
                            childButton = button.children("." + wijCSS.buttonText), caption = childButton.text();
                            if (!caption) {
                                caption = commandName;
                            }

                            childButton.text(caption);
                            if (accessBarBtn) {
                                childButton.text(caption);
                            }
                        }
                    } else {
                        childButton = $("[for='" + button.attr("id") + "']", button.parent()).children("." + wijCSS.buttonText), caption = childButton.text();
                        if (!caption) {
                            caption = commandName;
                        }
                        childButton.text(caption);
                    }

                    splitUi = this.listUis[commandName];
                    if (splitUi && splitUi.type === "split") {
                        childButton = splitUi.trigger.children("." + wijCSS.buttonText), caption = childButton.text();
                        if (!caption) {
                            caption = commandName;
                        }
                        splitUi.trigger.button("option", "disabled", disabled);
                        childButton.text(caption);
                    }
                }
            };

            /** The method sets the ribbon buttons as enabled or disabled according to the command name.
            * @param {object} commands An object that contains commands infos that need to change state,
            *               key is command name, value is button disabled state, true or false.
            */
            wijribbon.prototype.setButtonsDisabled = function (commands) {
                var self = this;

                $.each(commands, function (key, value) {
                    self.setButtonDisabled(key, value);
                });
            };

            /** The method sets sets the buttons as checked or not checked.
            * @param {object} commands An object that contains commands infos that need to change state,
            *               key is command name, value is button checked state, true or false.
            */
            wijribbon.prototype.setButtonsChecked = function (commands) {
                var self = this;

                $.each(commands, function (key, value) {
                    if ($.isPlainObject(value)) {
                        self.setButtonChecked(key, value.checked, value.name);
                    } else {
                        self.setButtonChecked(key, value, null);
                    }
                });
            };

            /** The method used to push the custom button to button collection.
            * @param {string} cmdName The command of the button.
            * @param {Object} eleObj The object of the button information.
            */
            wijribbon.prototype.registerButtonInformation = function (cmdName, eleObj) {
                if (cmdName && eleObj) {
                    return this.buttons[cmdName] = eleObj;
                }
            };

            /** The custom button trigger ribbon click
            * @param {e} e the event information.
            * @param {obj} eleObj The data information.
            */
            wijribbon.prototype.ribbonClick = function (e, obj) {
                this._trigger("click", e, obj);
            };

            wijribbon.prototype._setBtnWidgetCheckedStyle = function (buttonEle, checked) {
                var self = this, buttonEle, wijCSS = self.options.wijCSS;

                if (buttonEle.is("button")) {
                    buttonEle.toggleClass(wijCSS.stateActive, checked);
                } else if (!buttonEle.is("input[type='text']")) {
                    buttonEle.prop("checked", checked).button("refresh");
                }
                self._addActiveClassToButtonText(buttonEle.button("widget"));
            };

            /**
            @ignore
            */
            wijribbon.prototype.removeButtonHoverState = function (commandName) {
                var self = this, buttonEle, wijCSS = this.options.wijCSS, buttonObj = self.buttons[commandName];
                if (buttonObj && buttonObj.button) {
                    buttonEle = buttonObj.button;
                    if (buttonEle.is("button")) {
                        buttonEle.removeClass(wijCSS.stateHover).removeClass(wijCSS.stateFocus);
                        $("span", buttonEle).removeClass(wijCSS.stateHover);
                    }
                }
            };

            /** Sets a ribbon button as checked or not checked.
            * @param {string} commandName The command name of the button.
            * @param {boolean} checked The checked state of the button.
            * @param {string} name The parent name of the button.
            */
            wijribbon.prototype.setButtonChecked = function (commandName, checked, name) {
                var self = this, radios, buttonObj = self.buttons[commandName], wijCSS = this.options.wijCSS, buttonEle, accessBarBtnEle, listUi, label;

                //for custom button
                if (buttonObj && buttonObj.checked) {
                    buttonObj.checked(checked);
                    return;
                }

                if (buttonObj && buttonObj.button) {
                    buttonEle = buttonObj.button;
                    accessBarBtnEle = buttonObj.accessToolbarButton;
                    if (buttonEle.is("button")) {
                        buttonEle.toggleClass(wijCSS.stateActive, checked);
                        if (accessBarBtnEle) {
                            accessBarBtnEle.toggleClass(wijCSS.stateActive, checked);
                        }
                    } else if (buttonObj.type === "galleryBtn") {
                        var galleryEle = buttonEle.parent("div");
                        $("div", galleryEle).removeClass(wijCSS.stateActive);
                        buttonEle.toggleClass(wijCSS.stateActive, checked);
                        return;
                    } else if (!buttonEle.is("input[type='text']")) {
                        buttonEle.prop("checked", checked).button("refresh");
                        if (accessBarBtnEle) {
                            accessBarBtnEle.prop("checked", checked).button("refresh");
                        }
                    }

                    if (buttonObj.parent) {
                        if (buttonObj.type === "dropdown") {
                            // checked
                            if (checked) {
                                if (!self.dropdownLabels[commandName]) {
                                    self.dropdownLabels[commandName] = self._getDropdownLabelSubstr(buttonEle.button("option", "label"), buttonObj.parent.children("." + wijCSS.buttonText), buttonObj.parent.children("." + wijCSS.buttonText).width());
                                }
                                label = self.dropdownLabels[commandName];
                                if (buttonObj.parent.is("input[type='text']")) {
                                    buttonObj.parent.val(label).attr("title", label);
                                } else {
                                    buttonObj.parent.button("option", "label", label);
                                    buttonObj.parent.attr("title", buttonEle.button("option", "label"));
                                }
                                radios = $(":radio", buttonObj.button.closest("ul"));
                                if (radios) {
                                    $.each(radios, function () {
                                        self._updateGroupElementTextState(this);
                                    });
                                }
                                //end for active class
                            }
                        }
                        //TODO split
                    } else {
                        self._addActiveClassToButtonText(buttonEle.button("widget"));
                        if (accessBarBtnEle) {
                            self._addActiveClassToButtonText(accessBarBtnEle.button("widget"));
                        }
                    }
                } else if (name) {
                    // handle dropdown
                    listUi = self.listUis[name];
                    if (listUi) {
                        // update for input dropdown
                        if (listUi.ui.is("input[type='text']")) {
                            listUi.ui.val(listUi.defaultValue);
                        } else {
                            listUi.ui.button("option", "label", listUi.defaultValue);
                        }

                        if (listUi.buttons) {
                            $.each(listUi.buttons, function (i, btn) {
                                btn.prop("checked", false).button("refresh");
                                self._addActiveClassToButtonText(btn.button("widget"));
                            });
                        }
                    }
                }
            };
            return wijribbon;
        })(wijmo.wijmoWidget);
        ribbon.wijribbon = wijribbon;

        var wijribbon_options = (function () {
            function wijribbon_options() {
                /** Selector option for auto self initialization. This option is internal.
                * @ignore
                */
                this.initSelector = ":jqmData(role='wijribbon')";
                /** All CSS classes used in widgets.
                * @ignore
                */
                this.wijCSS = {
                    wijtabsHide: "wijmo-wijtabs-hide"
                };
                /**  If the compactMode option is true and ribbon is not simple,it will show
                *   compact mode.
                */
                this.compactMode = false;
                /** The wijRibbonClick event is a function that is called
                * when the ribbon command button is clicked.
                * @event
                * @dataKey {string} commandName the command name of the button.
                * @dataKey {string} name the parent name of the button which means if the drop down item is clicked,
                *                     then the name specifies the command name of the drop down button.
                */
                this.click = null;
                /** Using this option to create customize ribbon: ribbon tabs, groups, buttons.
                *   Can define the ribbon data like this:
                *	var ribbonData = [];
                *    // format tab definition
                *     ribbonData[0] = {
                *         id: "format",
                *         text: "format",
                *         groups:[
                *         // Actions group definition
                *         {
                *             id:"Actions",
                *             text: "Actions",
                *             css: "wijmo-wijribbon-actions",
                *             // group's buttons definition
                *             buttons:[
                *                 //big button definition: save
                *                 { name: "save", tip: 'Save', text: 'Save Button', css: "wijmo-wijribbon-save", buttonType: "bigButton", action: function (e) { alert("Save"); } },
                *                //redo and undo in one set
                *                 [
                *                   { name: "undo", tip: 'Undo', css: "wijmo-wijribbon-undo", buttonType: "button" },
                *                   { name: "redo", tip: 'Redo', css: "wijmo-wijribbon-redo", buttonType: "button" }
                *                 ],
                *                  //preview and cleanup in one set
                *                 [
                *                   { name: "preview", tip: 'Preview', css: "wijmo-wijribbon-preview" },
                *                   { name: "cleanup", tip: 'Clean up', css: "wijmo-wijribbon-cleanup" }
                *                 ]
                *             ]
                *        }];
                *  Now the supported button's type is: "button", "buttonWithText", "bigButton", "checkbox", "dropdownButton",  "radio", "splitButton".
                *  User can define button's text, tooltip, class and click function; if some buttons in one group, put them in array.
                *  Some details refer the customizeribbonbydata.html and customizesimpleribbonbydata.html.
                */
                this.data = null;
                /** Define custom buttons(TODO).
                * @ignore
                */
                this.custombuttons = null;
            }
            return wijribbon_options;
        })();
        ;
        wijribbon.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijribbon_options());
        $.wijmo.registerWidget("wijribbon", wijribbon.prototype);

        /**
        * @ignore
        */
        var wijribbonDataRender = (function () {
            function wijribbonDataRender(id, data) {
                this.data = data;
                this.id = id;
                this.ribbon = wijribbonDataRender.createElement("div");
                this.actions = {};
            }
            wijribbonDataRender.prototype.getMarkupWithData = function () {
                var markup;
                this._createRibbonTabs();
                markup = this.ribbon.render();
                return markup.substring(5, markup.length - 6);
            };

            wijribbonDataRender.prototype.clearRes = function () {
                this.ribbon = null;
            };

            wijribbonDataRender.prototype.getActions = function () {
                return this.actions;
            };

            wijribbonDataRender.prototype._createRibbonTabs = function () {
                var _this = this;
                var ribbonbTabs, ribbonTab, ribbonPanel;
                if (!this._isSimpleRibbon()) {
                    // creating ribbon
                    if (this.data.length < 0) {
                        return;
                    }
                    ribbonbTabs = wijribbonDataRender.createElement("ul");
                    this.ribbon.add(ribbonbTabs);
                    $.each(this.data, function (index, tabItem) {
                        ribbonTab = wijribbonDataRender.createElement("li");
                        ribbonPanel = wijribbonDataRender.createElement("div", { id: _this.id + tabItem.id });
                        ribbonTab.add(wijribbonDataRender.createElement("a", tabItem.text, {
                            href: "#" + _this.id + tabItem.id
                        }));

                        ribbonbTabs.add(ribbonTab);
                        _this.ribbon.add(ribbonPanel);

                        //add group
                        if (tabItem.groups && tabItem.groups.length > 0) {
                            ribbonPanel.add(_this._createGroups(tabItem.groups));
                        }
                    });
                } else {
                    // creating simple
                    this._addButtonsToGroup(this.ribbon, this.data);
                }
                return ribbonbTabs;
            };

            wijribbonDataRender.prototype._isSimpleRibbon = function () {
                var groups = this.data[0].groups;
                return !groups;
            };

            wijribbonDataRender.prototype._createGroups = function (groups) {
                var _this = this;
                var groupsEle = wijribbonDataRender.createElement("ul"), groupEle, groupList;
                $.each(groups, function (index, group) {
                    groupEle = wijribbonDataRender.createElement("li", null, { "class": group.css, id: group.id });
                    if (group.buttons && group.buttons.length > 0) {
                        _this._addButtonsToGroup(groupEle, group.buttons);
                    }
                    groupEle.add(wijribbonDataRender.createElement("div", group.text));
                    groupsEle.add(groupEle);
                });

                return groupsEle;
            };

            wijribbonDataRender.prototype._addButtonsToGroup = function (groupEle, buttons) {
                var _this = this;
                var buttonEle, childBtn;
                $.each(buttons, function (index, button) {
                    buttonEle = _this._createGroupButton(button);
                    if ($.isArray(buttonEle)) {
                        $.each(buttonEle, function (index, childBtn) {
                            groupEle.add(childBtn);
                        });
                    } else {
                        groupEle.add(buttonEle);
                    }
                });
            };

            wijribbonDataRender.prototype._createGroupButton = function (button) {
                var _this = this;
                var buttonEle, childBtn, buttonType = button.buttonType ? button.buttonType : "button";
                if ($.isArray(button)) {
                    buttonEle = wijribbonDataRender.createRibbonList();
                    $.each(button, function (index, ele) {
                        childBtn = _this._createGroupButton(ele);
                        if ($.isArray(childBtn)) {
                            $.each(childBtn, function (index, btn) {
                                buttonEle.add(btn);
                            });
                        } else {
                            buttonEle.add(childBtn);
                        }
                    });

                    return buttonEle;
                }

                switch (buttonType) {
                    case "button":
                        buttonEle = wijribbonDataRender.createButton(button.tip, button.css, button.name);
                        break;
                    case "bigButton":
                        buttonEle = wijribbonDataRender.createBigButton(button.tip, button.css, button.name, button.text);
                        break;
                    case "dropdownButton":
                        buttonEle = this._createDropdownButton(button.tip, button.name, button.text, button.dropdownButtons, this.id);
                        break;
                    case "buttonWithText":
                        buttonEle = wijribbonDataRender.createButton(button.tip, button.css, button.name, button.text);
                        break;
                    case "checkbox":
                        buttonEle = wijribbonDataRender.createImageCheckButton(button.tip, this.id, button.css, button.name);
                        break;
                    case "radio":
                        buttonEle = wijribbonDataRender.createImageRadioButton(button.tip, this.id, button.css, button.name, button.grpname);
                        break;
                    case "textRadio":
                        buttonEle = wijribbonDataRender.createTextRadioButton(button.tip, this.id, button.name, button.grpname, button.text);
                        break;
                    case "splitButton":
                        buttonEle = this._createSplitButton(button.tip, button.css, button.name, button.text, button.buttons);
                        break;
                }
                ;
                if (button.action) {
                    this.actions[button.name] = button.action;
                }
                return buttonEle;
            };

            //helper methods
            wijribbonDataRender.createBigButton = function (tip, css, name, text) {
                var button = wijribbonDataRender.createElement("button", {
                    title: tip,
                    name: name,
                    "class": css_ribbon_bigbutton
                });

                button.add(wijribbonDataRender.createDiv(css));
                button.add(wijribbonDataRender.createSpan("", text));

                return button;
            };

            wijribbonDataRender.createTextButton = function (tip, name, text) {
                return wijribbonDataRender.createElement("button", text, {
                    title: tip,
                    name: name
                });
            };

            wijribbonDataRender.createButton = function (tip, css, name, text) {
                var button;

                if (!text) {
                    return wijribbonDataRender.createElement("button", {
                        title: tip,
                        name: name,
                        "class": css
                    });
                }

                button = wijribbonDataRender.createElement("button", {
                    title: tip,
                    name: name
                });
                button.add(wijribbonDataRender.createSpan(css));
                button.add(wijribbonDataRender.createSpan("", text));

                return button;
            };

            wijribbonDataRender.createTextRadioButton = function (tip, idPre, name, grpName, text) {
                var realName = name.replace(/ /g, ''), buttons = [];

                buttons.push(wijribbonDataRender.createElement("input", {
                    id: idPre + realName,
                    type: "radio",
                    name: grpName
                }));
                buttons.push(wijribbonDataRender.createElement("label", text, {
                    "for": idPre + realName,
                    title: tip,
                    name: name
                }));

                return buttons;
            };

            wijribbonDataRender.createImageRadioButton = function (tip, idPre, css, name, grpName) {
                var buttons = [];

                buttons.push(wijribbonDataRender.createElement("input", {
                    id: idPre + name,
                    type: "radio",
                    name: grpName
                }));
                buttons.push(wijribbonDataRender.createElement("label", {
                    "for": idPre + name,
                    title: tip,
                    name: name,
                    "class": css
                }));

                return buttons;
            };

            wijribbonDataRender.createImageCheckButton = function (tip, idPre, css, name) {
                var buttons = [];

                buttons.push(wijribbonDataRender.createElement("input", {
                    id: idPre + name,
                    type: "checkbox"
                }));
                buttons.push(wijribbonDataRender.createElement("label", {
                    "for": idPre + name,
                    title: tip,
                    name: name,
                    "class": css
                }));

                return buttons;
            };

            wijribbonDataRender.createRibbonList = function () {
                return wijribbonDataRender.createSpan("wijmo-wijribbon-list");
            };

            wijribbonDataRender.prototype._createDropdownButton = function (tip, name, text, items, idPrefix) {
                var _this = this;
                var divBtn = wijribbonDataRender.createElement("div", {
                    title: tip,
                    "class": "wijmo-wijribbon-dropdownbutton"
                }), ulDrpList = wijribbonDataRender.createElement("ul");

                divBtn.add(wijribbonDataRender.createTextButton(tip, name, text));
                divBtn.add(ulDrpList);

                $.each(items, function (idx, item) {
                    var liDrpBtn = wijribbonDataRender.createElement("li"), btns = _this._createGroupButton(item);
                    $.each(btns, function (i, btn) {
                        liDrpBtn.add(btn);
                    });

                    ulDrpList.add(liDrpBtn);
                });

                return divBtn;
            };

            wijribbonDataRender.prototype._createSplitButton = function (tip, css, name, text, items) {
                var _this = this;
                var divBtn = wijribbonDataRender.createElement("div", {
                    title: tip,
                    "class": "wijmo-wijribbon-splitbutton"
                }), ulDrpList = wijribbonDataRender.createElement("ul");

                divBtn.add(wijribbonDataRender.createBigButton(tip, css, name, text));
                divBtn.add(wijribbonDataRender.createElement("button", {
                    "class": css_ribbon_bigbutton
                }));
                divBtn.add(ulDrpList);

                $.each(items, function (idx, item) {
                    var liDrpBtn = wijribbonDataRender.createElement("li");
                    liDrpBtn.add(_this._createGroupButton(item));
                    ulDrpList.add(liDrpBtn);
                });

                return divBtn;
            };

            wijribbonDataRender.createElement = function (tagName, innerText, attribs) {
                return new HtmlElement(tagName, innerText, attribs);
            };

            wijribbonDataRender.createDiv = function (className, title) {
                return wijribbonDataRender.createElement("div", { "class": className });
            };

            wijribbonDataRender.createSpan = function (className, text) {
                if (!text) {
                    return wijribbonDataRender.createElement("span", { "class": className });
                }

                if (className.length === 0) {
                    return wijribbonDataRender.createElement("span", text);
                }

                return wijribbonDataRender.createElement("span", text, { "class": className });
            };

            wijribbonDataRender.createTextBox = function (className, text, label) {
                var attrs = { "class": className, "type": "text", "value": undefined, "aria-label": label || "text" };

                if (text) {
                    attrs.value = text;
                }

                return wijribbonDataRender.createElement("input", attrs);
            };

            wijribbonDataRender.createLabel = function (text, labelfor) {
                if (labelfor) {
                    return new HtmlElement("label", text, { "for": labelfor });
                }
                return new HtmlElement("label", text);
            };

            wijribbonDataRender.createRadio = function (id, name, value) {
                var attrs = { name: name, id: id, value: value, type: "radio" };
                return wijribbonDataRender.createElement("input", attrs);
            };

            wijribbonDataRender.createCheckbox = function (id) {
                var attrs = { "type": "checkbox", id: id };
                return wijribbonDataRender.createElement("input", "", attrs);
            };

            wijribbonDataRender.createSelect = function (classname, options) {
                var attrs = { "class": classname }, select = wijribbonDataRender.createElement("select", attrs);

                if (classname === "") {
                    select = wijribbonDataRender.createElement("select");
                }
                $.each(options, function (i, o) {
                    if ($.isPlainObject(o) && o.selected) {
                        select.add(wijribbonDataRender.createElement("option", o.text, {
                            selected: "selected"
                        }));
                    } else {
                        select.add(wijribbonDataRender.createElement("option", o));
                    }
                });
                return select;
            };

            wijribbonDataRender._createInputButton = function (className, text) {
                var attrs = { "class": className, "type": "button", "value": undefined };

                if (text) {
                    attrs.value = text;
                }

                return wijribbonDataRender.createElement("input", attrs);
            };
            return wijribbonDataRender;
        })();
        ribbon.wijribbonDataRender = wijribbonDataRender;
    })(wijmo.ribbon || (wijmo.ribbon = {}));
    var ribbon = wijmo.ribbon;
})(wijmo || (wijmo = {}));


;
/// <reference path="../Base/jquery.wijmo.widget.ts" />
/// <reference path="../wijsplitter/jquery.wijmo.wijsplitter.ts" />
/// <reference path="../wijdialog/jquery.wijmo.wijdialog.ts" />
/// <reference path="../external/declarations/globalize.d.ts" />
/// <reference path="../wijribbon/jquery.wijmo.wijribbon.ts" />
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*globals jQuery,window,document*/
    /*
    * Depends:
    *     jquery.ui.core.js
    *     jquery.ui.widget.js
    *     jquery.wijmo.wijtooltip.js
    */
    (function (editor) {
        var $ = jQuery, widgetName = "wijeditor";

        var wijAlert = alert, wijWindow = window, wijDoc = document, wijParseInt = parseInt, wijribbonDataRender = wijmo.ribbon.wijribbonDataRender, oriWidth, oriHeight, $oriParent, uniqueIds = [], isFontSizeCustomized = null, wordwrap = true, undoSteps = 0, undoBuffers = [], inspectElement = null, setButtonDisabled = "setButtonDisabled", setButtonsDisabled = "setButtonsDisabled", setButtonChecked = "setButtonChecked", setButtonsChecked = "setButtonsChecked", cmd_form = "form", cmd_imagebutton = "imagebutton", cmd_textarea = "textarea", cmd_button = "button", cmd_textbox = "textbox", cmd_listbox = "list", cmd_password = "passwordfield", cmd_dropdownlist = "dropdownlist", cmd_hiddenfield = "hiddenfield", cmd_radio = "radio", cmd_checkbox = "checkbox", cmd_insertcolumn = "insertcol", cmd_insertrow = "insertrow", cmd_insertcell = "insertcell", cmd_splitcell = "splitcell", cmd_mergecell = "mergecell", cmd_removecolumn = "deletecol", cmd_removerow = "deleterow", cmd_removecell = "deletecell", cmd_alignleft = "justifyleft", cmd_aligncenter = "justifycenter", cmd_alignright = "justifyright", cmd_alignfull = "justifyfull", cmd_borders = "borders", cmd_numberedlist = "insertorderedlist", cmd_bulletedlist = "insertunorderedlist", cmd_outdent = "outdent", cmd_indent = "indent", cmd_backcolor = "backcolor", cmd_fontcolor = "fontcolor", cmd_bold = "bold", cmd_italic = "italic", cmd_strike = "strikethrough", cmd_underline = "underline", cmd_subscript = "subscript", cmd_superscript = "superscript", cmd_template = "template", cmd_removeformat = "removeformat", cmd_insertbreak = "insertbreak", cmd_insertparagraph = "insertparagraph", cmd_insertprintbreak = "insertprintpagebreak", cmd_inserthr = "inserthorizontalrule", cmd_table = "tablebutton", cmd_inserttable = "inserttable", cmd_edittable = "edittable", cmd_designview = "wysiwyg", cmd_splitview = "split", cmd_sourceview = "code", cmd_wordwrap = "wordwrap", cmd_fullscreen = "fullscreen", cmd_undo = "undo", cmd_redo = "redo", cmd_preview = "preview", cmd_cleanup = "cleanup", cmd_cut = "cut", cmd_copy = "copy", cmd_paste = "paste", cmd_selectall = "selectall", cmd_media = "media", cmd_specialchar = "specialchar", cmd_date = "datetime", cmd_find = "find", cmd_inspect = "inspect", cmd_save = "save", cmd_spelling = "spelling", cmd_imagebrowser = "imagebrowser", cmd_link = "link", cmd_verysmall = "xx-small", cmd_smaller = "x-small", cmd_small = "small", cmd_medium = "medium", cmd_large = "large", cmd_larger = "x-large", cmd_verylarge = "xx-large", cmd_fontname = "fontname", cmd_fontsize = "fontsize", cmd_blockquote = "blockquote", cmd_insertcode = "insertcode", css_ribbon = "wijmo-wijribbon", css_ribbon_bigbutton = css_ribbon + "-bigbutton", css_ribbon_dropdownbutton = css_ribbon + "-dropdownbutton", css_ribbon_splitbutton = css_ribbon + "-splitbutton", css_ribbon_list = css_ribbon + "-list", css_ribbon_save = css_ribbon + "-save", css_ribbon_save16 = css_ribbon + "-save16", css_ribbon_undo = css_ribbon + "-undo", css_ribbon_redo = css_ribbon + "-redo", css_ribbon_preview = css_ribbon + "-preview", css_ribbon_cleanup = css_ribbon + "-cleanup", css_ribbon_cut = css_ribbon + "-cut", css_ribbon_copy = css_ribbon + "-copy", css_ribbon_paste = css_ribbon + "-paste", css_ribbon_selectall = css_ribbon + "-selectall", css_ribbon_bgcolor = css_ribbon + "-bgcolor", css_ribbon_color = css_ribbon + "-color", css_ribbon_bold = css_ribbon + "-bold", css_ribbon_italic = css_ribbon + "-italic", css_ribbon_underline = css_ribbon + "-underline", css_ribbon_strike = css_ribbon + "-strike", css_ribbon_sub = css_ribbon + "-sub", css_ribbon_sup = css_ribbon + "-sup", css_ribbon_template = css_ribbon + "-template", css_ribbon_removeformat = css_ribbon + "-removeformat", css_ribbon_justifyleft = css_ribbon + "-justifyleft", css_ribbon_justifycenter = css_ribbon + "-justifycenter", css_ribbon_justifyright = css_ribbon + "-justifyright", css_ribbon_justifyfull = css_ribbon + "-justifyfull", css_ribbon_borders = css_ribbon + "-borders", css_ribbon_orderlist = css_ribbon + "-orderlist", css_ribbon_unorderlist = css_ribbon + "-unorderlist", css_ribbon_outdent = css_ribbon + "-outdent", css_ribbon_indent = css_ribbon + "-indent", css_ribbon_inspect = css_ribbon + "-inspect", css_ribbon_find = css_ribbon + "-find", css_ribbon_table = css_ribbon + "-table", css_ribbon_inserttable = css_ribbon + "-inserttable", css_ribbon_edittable = css_ribbon + "-edittable", css_ribbon_insertcol = css_ribbon + "-insertcol", css_ribbon_insertrow = css_ribbon + "-insertrow", css_ribbon_insertcell = css_ribbon + "-insertcell", css_ribbon_splitcell = css_ribbon + "-splitcell", css_ribbon_mergecell = css_ribbon + "-mergecell", css_ribbon_deletecol = css_ribbon + "-deletecol", css_ribbon_deleterow = css_ribbon + "-deleterow", css_ribbon_deletecell = css_ribbon + "-deletecell", css_ribbon_insertbreak = css_ribbon + "-insertbreak", css_ribbon_insertparagraph = css_ribbon + "-insertparagraph", css_ribbon_insertprintpagebreak = css_ribbon + "-insertprintpagebreak", css_ribbon_inserthr = css_ribbon + "-inserthr", css_ribbon_form = css_ribbon + "-form", css_ribbon_textarea = css_ribbon + "-textarea", css_ribbon_textbox = css_ribbon + "-textbox", css_ribbon_password = css_ribbon + "-password", css_ribbon_hiddenfield = css_ribbon + "-hiddenfield", css_ribbon_imagebutton = css_ribbon + "-imagebutton", css_ribbon_button = css_ribbon + "-button", css_ribbon_listbox = css_ribbon + "-listbox", css_ribbon_dropdownlist = css_ribbon + "-dropdownlist", css_ribbon_radio = css_ribbon + "-radio", css_ribbon_checkbox = css_ribbon + "-checkbox", css_ribbon_link = css_ribbon + "-link", css_ribbon_link16 = css_ribbon + "-link16", css_ribbon_imagebrowser = css_ribbon + "-imagebrowser", css_ribbon_media = css_ribbon + "-media", css_ribbon_specialchar = css_ribbon + "-specialchar", css_ribbon_datetime = css_ribbon + "-datetime", css_ribbon_blockquote = css_ribbon + "-blockquote", css_ribbon_insertcode = css_ribbon + "-insertcode", css_ribbon_modes = css_ribbon + "-modes", css_ribbon_designview = css_ribbon + "-designview", css_ribbon_sourceview = css_ribbon + "-sourceview", css_ribbon_splitview = css_ribbon + "-splitview", css_ribbon_wordwrap = css_ribbon + "-wordwrap", css_ribbon_fullscreen = css_ribbon + "-fullscreen", css_editor = "wijmo-wijeditor", css_editor_container = css_editor + "-container", css_editor_header = css_editor + "-header", css_editor_content = css_editor + "-content", css_editor_footer = css_editor + "-footer", css_editor_pathselector = css_editor + "-pathselector", css_editor_fullscreen = css_editor + "-fullscreen", css_dlg = css_editor + "-dialog", css_dlg_hr = css_dlg + "-hr", css_dlg_buttons = css_dlg + "-buttons", css_dlg_button = css_dlg + "-button", css_dlg_text = css_dlg + "-text", css_imgdlg = css_editor + "-imagedlg", css_imgdlg_content = css_imgdlg + "-content", css_imgdlg_fields = css_imgdlg + "-fields", css_imgdlg_field = css_imgdlg + "-imagefield", css_imgdlg_list = css_imgdlg + "-imagelist", css_imgdlg_preview = css_imgdlg + "-preview", css_imgdlg_url = css_imgdlg + "-imagesrc", css_imgdlg_alt = css_imgdlg + "-imagealt", css_imgdlg_width = css_imgdlg + "-imagewidth", css_imgdlg_height = css_imgdlg + "-imageheight", css_imgdlg_css = css_imgdlg + "-css", css_imgdlg_hideimglist = css_imgdlg + "-hideimagelist", css_tpldlg = css_editor + "-templatedlg", css_tpl_labels = css_tpldlg + "-toplabels", css_tpl_tllabel = css_tpldlg + "-topleftlabel", css_tpl_trlabel = css_tpldlg + "-toprightlabel", css_tpl_content = css_tpldlg + "-content", css_tpl_list = css_tpldlg + "-templatelist", css_tpl_preview = css_tpldlg + "-preview", css_tpl_tplinfo = css_tpldlg + "-templateinfo", css_tpl_nameinfo = css_tpldlg + "-nameinfo", css_tpl_desinfo = css_tpldlg + "-descriptioninfo", css_tpl_fields = css_tpldlg + "-fields", css_tpl_namefield = css_tpldlg + "-name", css_tpl_desfield = css_tpldlg + "-description", css_tpl_buttons = css_tpldlg + "-buttons", css_tpl_delete = css_tpldlg + "-delete", css_tpl_save = css_tpldlg + "-save", css_linkdlg = css_editor + "-linkdlg", css_linkdlg_address = css_linkdlg + "-address", css_linkdlg_linktype = css_linkdlg + "-linktype", css_linkdlg_anchor = css_linkdlg + "-anchor", css_linkdlg_text = css_linkdlg + "-text", css_linkdlg_target = css_linkdlg + "-target", css_linkdlg_css = css_linkdlg + "-css", css_linkdlg_url = css_linkdlg + "-src", css_linkdlg_width = css_linkdlg + "-width", css_linkdlg_height = css_linkdlg + "-height", css_linkdlg_imagecontainer = css_linkdlg + "-imagecontainer", css_linkdlg_linkicontype = css_linkdlg + "-linkicontype", css_codedlg = css_editor + "-codedlg", css_codedlg_source = css_codedlg + "-source", css_codedlg_sourcelabel = css_codedlg + "-sourcelabel", css_taginsdlg = css_editor + "-taginsdlg", css_taginsdlg_caption = css_taginsdlg + "-caption", css_taginsdlg_taglabel = css_taginsdlg + "-taglabel", css_taginsdlg_tagtext = css_taginsdlg + "-tagtext", css_taginsdlg_filterempty = css_taginsdlg + "-filterempty", css_taginsdlg_attribs = css_taginsdlg + "-attribs", css_taginsdlg_attriblist = css_taginsdlg + "-attriblist", css_taginsdlg_innerhtml = css_taginsdlg + "-innerhtml", css_taginsdlg_css = css_taginsdlg + "-css", css_colordlg = css_editor + "-colordlg", css_colordlg_picker = css_colordlg + "-picker", css_colordlg_color = css_colordlg + "-color", css_tabledlg = css_editor + "-tabledlg", css_tabledlg_rows = css_tabledlg + "-rows", css_tabledlg_columns = css_tabledlg + "-columns", css_tabledlg_width = css_tabledlg + "-width", css_tabledlg_height = css_tabledlg + "-height", css_tabledlg_border = css_tabledlg + "-border", css_tabledlg_cellpadding = css_tabledlg + "-cellpadding", css_tabledlg_cellspacing = css_tabledlg + "-cellspacing", css_tabledlg_csstext = css_tabledlg + "-csstext", css_tabledlg_bgcolor = css_tabledlg + "-bgcolor", css_previewdlg = css_editor + "-previewdlg", css_previewdlg_caption = css_previewdlg + "-caption", css_previewdlg_navigator = css_previewdlg + "-navigator", css_previewdlg_prev = css_previewdlg + "-prev", css_previewdlg_next = css_previewdlg + "-next", css_previewdlg_printall = css_previewdlg + "-printall", css_previewdlg_printone = css_previewdlg + "-printone", css_previewdlg_ok = css_previewdlg + "-ok", css_previewdlg_printdocument = css_previewdlg + "-printdocument", css_previewdlg_previewiframe = css_previewdlg + "-previewiframe", css_cleanupdlg = css_editor + "-cleanupdlg", css_cleanupdlg_caption = css_cleanupdlg + "-caption", css_cleanupdlg_document = css_cleanupdlg + "-document", css_cleanupdlg_actions = css_cleanupdlg + "-actions", css_finddlg = css_editor + "-finddlg", css_finddlg_find = css_finddlg + "-find", css_finddlg_replace = css_finddlg + "-replace", css_mediadlg = css_editor + "-mediadlg", css_mediadlg_type = css_mediadlg + "-type", css_mediadlg_url = css_mediadlg + "-src", css_mediadlg_width = css_mediadlg + "-width", css_mediadlg_height = css_mediadlg + "-height", css_specialchardlg = css_editor + "-specialchardlg", css_specialchardlg_chars = css_specialchardlg + "-chars", css_specialchardlg_preview = css_specialchardlg + "-preview", css_specialchardlg_content = css_specialchardlg + "-content", css_specialchardlg_list = css_specialchardlg + "-list", css_specialchardlg_label = css_specialchardlg + "_label", css_specialchardlg_punctuation = css_specialchardlg + "-punctuation", css_specialchardlg_symbols = css_specialchardlg + "-symbols", css_specialchardlg_diacritics = css_specialchardlg + "-diacritics", css_formatspan = "wijmo-formatspan", selector_dlg_ok = "." + css_dlg_buttons + " input:first", selector_dlg_cancel = "." + css_dlg_buttons + " input:last", selector_input_ok = "." + css_dlg_buttons + " input[value='OK']", selector_input_cancel = "." + css_dlg_buttons + " input[engValue='Cancel']", imageTypeButton = [
            "Bold", "Italic", "UnderLine",
            "StrikeThrough", "SubScript", "SuperScript",
            "JustifyLeft", "JustifyCenter", "JustifyRight",
            "JustifyFull", "Border", "NumberedList",
            "BulletedList", "Outdent", "Indent"], defaultSimpleModeCommands = [
            "Bold", "Italic", "Link", "BlockQuote",
            "StrikeThrough", "InsertDate", "InsertImage",
            "NumberedList", "BulletedList", "InsertCode"], defaultBBCodeModeCommands = [
            "Bold", "Italic", "StrikeThrough",
            "UnderLine", "ForeColor", "FontSize",
            "Link", "InsertImage", "NumberedList",
            "BulletedList", "BlockQuote"], buttonInfoAsCommand = {
            Form: { name: "form", tip: 'Form', css: css_ribbon_form },
            Image: { name: "imagebutton", tip: 'Image Button', css: css_ribbon_imagebutton },
            TextArea: { name: "textarea", tip: 'TextArea', css: css_ribbon_textarea },
            Button: { name: "button", tip: 'Button', css: css_ribbon_button },
            TextBox: { name: "textbox", tip: 'TextBox', css: css_ribbon_textbox },
            List: { name: "list", tip: 'ListBox', css: css_ribbon_listbox },
            PasswordField: {
                name: "passwordfield", tip: 'Password Field',
                css: css_ribbon_password
            },
            DropDownList: {
                name: "dropdownlist", tip: 'DropDownList',
                css: css_ribbon_dropdownlist
            },
            HiddenField: {
                name: "hiddenfield", tip: 'Hidden Field',
                css: css_ribbon_hiddenfield
            },
            Radio: { name: "radio", tip: 'RadioButton', css: css_ribbon_radio },
            CheckBox: {
                name: "checkbox", tip: 'CheckBox',
                css: css_ribbon_checkbox
            },
            InsertColumn: {
                name: "insertcol", tip: 'Insert Column',
                css: css_ribbon_insertcol
            },
            InsertRow: {
                name: "insertrow", tip: 'Insert Row',
                css: css_ribbon_insertrow
            },
            InsertCell: {
                name: "insertcell", tip: 'Insert Cell',
                css: css_ribbon_insertcell
            },
            SplitCell: {
                name: "splitcell", tip: 'Split Cell',
                css: css_ribbon_splitcell
            },
            MergeCell: {
                name: "mergecell", tip: 'Merge Cell',
                css: css_ribbon_mergecell
            },
            DeleteColumn: {
                name: "deletecol", tip: 'Delete Column',
                css: css_ribbon_deletecol
            },
            DeleteRow: {
                name: "deleterow", tip: 'Delete Row',
                css: css_ribbon_deleterow
            },
            DeleteCell: {
                name: "deletecell", tip: 'Delete Cell',
                css: css_ribbon_deletecell
            },
            JustifyLeft: {
                name: "justifyleft", tip: 'Justify Left',
                css: css_ribbon_justifyleft, grpname: 'alignment'
            },
            JustifyCenter: {
                name: "justifycenter", tip: 'Justify Center',
                css: css_ribbon_justifycenter, grpname: 'alignment'
            },
            JustifyRight: {
                name: "justifyright", tip: 'Justify Right',
                css: css_ribbon_justifyright, grpname: 'alignment'
            },
            JustifyFull: {
                name: "justifyfull", tip: 'Justify Full',
                css: css_ribbon_justifyfull, grpname: 'alignment'
            },
            Border: { name: "borders", tip: 'Border', css: css_ribbon_borders },
            NumberedList: {
                name: "insertorderedlist", tip: 'Numbered List',
                css: css_ribbon_orderlist, grpname: 'list'
            },
            BulletedList: {
                name: "insertunorderedlist", tip: 'Bulleted List',
                css: css_ribbon_unorderlist, grpname: 'list'
            },
            Outdent: {
                name: "outdent", tip: 'Outdent',
                css: css_ribbon_outdent, grpname: 'block'
            },
            Indent: {
                name: "indent", tip: 'Indent',
                css: css_ribbon_indent, grpname: 'block'
            },
            BackColor: {
                name: "backcolor", tip: 'Background Color',
                css: css_ribbon_bgcolor
            },
            ForeColor: {
                name: "fontcolor", tip: 'Font Color',
                css: css_ribbon_color
            },
            Bold: {
                name: "bold", tip: 'Bold',
                css: css_ribbon_bold
            },
            Italic: { name: "italic", tip: 'Italic', css: css_ribbon_italic },
            StrikeThrough: {
                name: "strikethrough", tip: 'Strikethrough',
                css: css_ribbon_strike
            },
            UnderLine: {
                name: "underline", tip: 'Underline',
                css: css_ribbon_underline
            },
            SubScript: {
                name: "subscript", tip: 'Subscript',
                css: css_ribbon_sub
            },
            SuperScript: {
                name: "superscript", tip: 'Superscript',
                css: css_ribbon_sup
            },
            Template: {
                name: "template", tip: 'Template',
                css: css_ribbon_template
            },
            RemoveFormat: {
                name: "removeformat", tip: 'RemoveFormat',
                css: css_ribbon_removeformat
            },
            InsertBreak: {
                name: "insertbreak", tip: 'Insert Break',
                css: css_ribbon_insertbreak
            },
            InsertParagraph: {
                name: "insertparagraph", tip: 'Insert Paragraph',
                css: css_ribbon_insertparagraph
            },
            InsertPrint: {
                name: "insertprintpagebreak", tip: 'Insert Print Page Break',
                css: css_ribbon_insertprintpagebreak
            },
            InsertHR: {
                name: "inserthorizontalrule", tip: 'Insert Horizontal Line',
                css: css_ribbon_inserthr
            },
            Table: {
                name: "tablebutton", tip: 'Table',
                css: css_ribbon_table
            },
            InsertTable: {
                name: "inserttable", tip: 'Insert Table',
                css: css_ribbon_inserttable
            },
            EditTable: {
                name: "edittable", tip: 'Edit Table',
                css: css_ribbon_edittable
            },
            Wysiwyg: {
                name: "wysiwyg", tip: 'Design View',
                css: css_ribbon_designview, grpname: 'modes'
            },
            Split: {
                name: "split", tip: 'Split View',
                css: css_ribbon_splitview, grpname: 'modes'
            },
            Code: {
                name: "code", tip: 'Source View',
                css: css_ribbon_sourceview, grpname: 'modes'
            },
            Wordwrap: {
                name: "wordwrap", tip: 'Wordwrap',
                css: css_ribbon_wordwrap
            },
            FullScreen: {
                name: "fullscreen", tip: 'Fullscreen',
                css: css_ribbon_fullscreen
            },
            Undo: { name: "undo", tip: 'Undo', css: css_ribbon_undo },
            Redo: { name: "redo", tip: 'Redo', css: css_ribbon_redo },
            Preview: { name: "preview", tip: 'Preview', css: css_ribbon_preview },
            Cleanup: { name: "cleanup", tip: 'Clean up', css: css_ribbon_cleanup },
            Cut: { name: "cut", tip: 'Cut', css: css_ribbon_cut },
            Copy: { name: "copy", tip: 'Copy', css: css_ribbon_copy },
            Paste: { name: "paste", tip: 'Paste', css: css_ribbon_paste },
            SelectAll: {
                name: "selectall", tip: 'Select All',
                css: css_ribbon_selectall
            },
            Media: { name: "media", tip: 'Media', css: css_ribbon_media },
            InsertSpecialChar: {
                name: "specialchar", tip: 'Insert Special Character',
                css: css_ribbon_specialchar
            },
            InsertDate: {
                name: "datetime", tip: 'Insert Date Time',
                css: css_ribbon_datetime
            },
            Find: {
                name: "find", tip: 'Find And Replace',
                css: css_ribbon_find, text: 'Find'
            },
            Inspect: {
                name: "inspect", tip: 'Tag Inspect',
                css: css_ribbon_inspect, text: 'Inspect'
            },
            Save: { name: "save", tip: 'Save', css: css_ribbon_save, text: 'Save' },
            Spelling: { name: "spelling", tip: 'Form', css: '' },
            InsertImage: {
                name: "imagebrowser", tip: 'Image Browser',
                css: css_ribbon_imagebrowser
            },
            Link: { name: "link", tip: 'Link', css: css_ribbon_link, text: 'Link' },
            FontName: {
                name: "fontname", tip: 'Font Name', text: "Font Name",
                css: css_ribbon_dropdownbutton
            },
            FontSize: {
                name: "fontsize", tip: 'Font Size', text: "Font Size",
                css: css_ribbon_dropdownbutton
            },
            BlockQuote: {
                name: "blockquote", tip: 'Block Quote',
                css: css_ribbon_blockquote
            },
            InsertCode: {
                name: "insertcode", tip: 'Insert Code',
                css: css_ribbon_insertcode
            }
        }, formatGroupInfo = {
            "Actions": [
                "Save", "", "Undo", "Redo", "", "Preview",
                "Cleanup", "", "Cut", "Copy", "Paste", "SelectAll"],
            "Font": [
                "FontName", "FontSize", "", "BackColor", "ForeColor", "", "Bold",
                "Italic", "UnderLine", "StrikeThrough", "SubScript", "SuperScript", "",
                "Template", "", "RemoveFormat"],
            "Paragraph": [
                "", "JustifyLeft", "JustifyCenter", "JustifyRight",
                "JustifyFull", "", "Border", "", "NumberedList", "BulletedList", "", "Outdent", "Indent"],
            "Review": ["Inspect", "Find"]
        }, insertGroupInfo = {
            "Tables": [
                "Table", "", "InsertColumn", "InsertRow", "InsertCell",
                "", "SplitCell", "MergeCell", "", "DeleteColumn", "DeleteRow", "DeleteCell"],
            "Breaks": ["InsertBreak", "InsertParagraph", "InsertPrint", "InsertHR"],
            "Forms": [
                "", "Form", "", "TextArea", "TextBox", "PasswordField", "HiddenField",
                "", "Image", "Button", "", "List", "DropDownList", "Radio", "CheckBox"],
            "Special": ["Link", "InsertImage", "Media", "InsertSpecialChar", "InsertDate"]
        }, TextElement = function (text) {
            this.text = text;

            this.render = function () {
                return this.text;
            };
        };

        /** @widget */
        var wijeditor = (function (_super) {
            __extends(wijeditor, _super);
            function wijeditor() {
                _super.apply(this, arguments);
            }
            /**
            * @constructor
            * @ignore
            */
            wijeditor.prototype.wijeditor = function () {
                this._curPageIdx = 0;
                this.tRange = null;
                this.txtFoundInIE = false;
                this.txtFoundInNoneIE = false;
                this.rangeSelection = null;
            };

            wijeditor.prototype._create = function () {
                var self = this, uniqueid = self.element.attr("id");

                // enable touch support:
                if (window.wijmoApplyWijTouchUtilEvents) {
                    $ = window.wijmoApplyWijTouchUtilEvents($);
                }
                if (self.element.is("input")) {
                    return;
                }
                self.wijeditor();
                if (!uniqueid || uniqueid === "") {
                    self.element.uniqueId();
                    uniqueid = self.element.attr("id");
                }

                //if place two editors, it will be mess in ui and function
                self.id_prefix = "wijeditor-" + uniqueid + "-";
                self.$ribbon = undefined;
                self.$modes = undefined;
                self._isIE11 = $.browser.msie && $.browser.version && parseFloat($.browser.version) >= 11;
                self._isEdge = navigator.userAgent.indexOf("Edge/") > 0;
                self._editorify();
                self._initElements();

                wijWindow.setTimeout(function () {
                    if (self._isDisabled()) {
                        self._handleDisabledOption(true, self.editor);
                    }
                }, 40);

                self._continueSavingInputTextForUndo = false;
                self.element.attribute("aria-label", "wijeditor");
                if (self.element.is(":hidden") && self.editor.wijAddVisibilityObserver) {
                    self.editor.wijAddVisibilityObserver(function (e) {
                        if ($.contains(self.editor[0], e.target)) {
                            return;
                        }

                        self.refresh();
                        if (self.editor.wijRemoveVisibilityObserver) {
                            self.editor.wijRemoveVisibilityObserver();
                        }
                    }, "wijeditor");
                }
                _super.prototype._create.call(this);
            };

            wijeditor.prototype._contextMenuWidgetName = function () {
                return "wijmenu";
            };

            wijeditor.prototype._createDropdownButton = function (tip, name, text, items, idPrefix) {
                var self = this, divBtn = wijribbonDataRender.createElement("div", {
                    title: tip,
                    "class": css_ribbon_dropdownbutton
                }), ulDrpList = wijribbonDataRender.createElement("ul");

                divBtn.add(wijribbonDataRender.createTextButton(tip, name, text));
                divBtn.add(ulDrpList);

                $.each(items, function (idx, item) {
                    var liDrpBtn = wijribbonDataRender.createElement("li"), btns = wijribbonDataRender.createTextRadioButton(item.tip, idPrefix, item.name, name, item.text);

                    $.each(btns, function (i, btn) {
                        liDrpBtn.add(btn);
                    });

                    ulDrpList.add(liDrpBtn);
                });

                return divBtn;
            };

            wijeditor.prototype._createSplitButton = function (tip, css, name, text, items) {
                var self = this, divBtn = wijribbonDataRender.createElement("div", {
                    title: tip,
                    "class": css_ribbon_splitbutton
                }), ulDrpList = wijribbonDataRender.createElement("ul");

                divBtn.add(wijribbonDataRender.createBigButton(tip, css, name, text));
                divBtn.add(wijribbonDataRender.createElement("button", {
                    "class": css_ribbon_bigbutton
                }));
                divBtn.add(ulDrpList);

                $.each(items, function (idx, item) {
                    var liDrpBtn = wijribbonDataRender.createElement("li");

                    liDrpBtn.add(wijribbonDataRender.createButton(item.tip, item.css, item.name, item.text));

                    ulDrpList.add(liDrpBtn);
                });

                return divBtn;
            };

            //get special button
            wijeditor.prototype._createButtonByCommand = function (cmd) {
                var self = this, button, buttoninfo = buttonInfoAsCommand[cmd], buttonTipKey, buttonTextKey, buttonTip, buttonText, cmdName;

                if (!buttoninfo) {
                    return;
                }

                cmdName = buttoninfo.name;
                buttonTipKey = cmdName + "ButtonTip";
                buttonTextKey = cmdName + "ButtonText";
                buttonTip = this.localizeString(buttonTipKey, buttoninfo.tip);
                buttonText = this.localizeString(buttonTextKey, buttoninfo.text);
                switch (cmdName) {
                    case cmd_blockquote:
                    case cmd_form:
                    case cmd_imagebutton:
                    case cmd_textarea:
                    case cmd_button:
                    case cmd_textbox:
                    case cmd_listbox:
                    case cmd_password:
                    case cmd_dropdownlist:
                    case cmd_hiddenfield:
                    case cmd_radio:
                    case cmd_checkbox:
                    case cmd_insertcolumn:
                    case cmd_insertrow:
                    case cmd_insertcell:
                    case cmd_splitcell:
                    case cmd_mergecell:
                    case cmd_removecolumn:
                    case cmd_removerow:
                    case cmd_removecell:
                    case cmd_removeformat:
                    case cmd_insertbreak:
                    case cmd_insertparagraph:
                    case cmd_insertprintbreak:
                    case cmd_fullscreen:
                    case cmd_undo:
                    case cmd_redo:
                    case cmd_cut:
                    case cmd_copy:
                    case cmd_paste:
                    case cmd_date:
                    case cmd_wordwrap:
                    case cmd_backcolor:
                    case cmd_fontcolor:
                    case cmd_preview:
                    case cmd_cleanup:
                    case cmd_media:
                    case cmd_specialchar:
                    case cmd_template:
                    case cmd_imagebrowser:
                    case cmd_insertcode:
                    case cmd_inserthr:
                    case cmd_selectall:
                        button = wijribbonDataRender.createButton(buttonTip, buttoninfo.css, cmdName);
                        break;
                    case cmd_find:
                    case cmd_inspect:
                        button = wijribbonDataRender.createButton(buttonTip, buttoninfo.css, cmdName, buttonText);
                        break;
                    case cmd_borders:
                    case cmd_subscript:
                    case cmd_superscript:
                    case cmd_bold:
                    case cmd_italic:
                    case cmd_underline:
                    case cmd_strike:
                        button = wijribbonDataRender.createImageCheckButton(buttonTip, self.id_prefix, buttoninfo.css, cmdName);
                        break;
                    case cmd_designview:
                    case cmd_splitview:
                    case cmd_sourceview:
                    case cmd_alignleft:
                    case cmd_aligncenter:
                    case cmd_alignright:
                    case cmd_alignfull:
                    case cmd_outdent:
                    case cmd_indent:
                    case cmd_numberedlist:
                    case cmd_bulletedlist:
                        button = wijribbonDataRender.createImageRadioButton(buttonTip, self.id_prefix, buttoninfo.css, cmdName, buttoninfo.grpname);
                        break;
                    case cmd_table:
                        button = self._createSplitButton(this.localizeString("tableButtonTip", "Table"), css_ribbon_table, cmd_table, this.localizeString("tableButtonText", "Table"), [
                            {
                                tip: this.localizeString("insertTableButtonTip", "Insert Table"),
                                css: css_ribbon_inserttable,
                                name: cmd_inserttable,
                                text: this.localizeString("insertTableButtonText", "Insert")
                            }, {
                                tip: this.localizeString("editTableButtonTip", "Edit Table"),
                                css: css_ribbon_edittable,
                                name: cmd_edittable,
                                text: this.localizeString("editTableButtonText", "Edit")
                            }]);
                        break;

                    case cmd_save:
                        if (self.options.mode === "ribbon") {
                            button = wijribbonDataRender.createBigButton(buttonTip, buttoninfo.css, cmdName, buttonText);
                        } else {
                            button = wijribbonDataRender.createButton(buttonTip, css_ribbon_save16, cmdName);
                        }
                        break;
                    case cmd_link:
                        if (self.options.mode === "ribbon") {
                            button = wijribbonDataRender.createBigButton(buttonTip, buttoninfo.css, cmdName, buttonText);
                        } else {
                            button = wijribbonDataRender.createButton(buttonTip, css_ribbon_link16, cmdName);
                        }
                        break;
                    case cmd_fontname:
                        button = self._createDropdownButton(buttonTip, cmd_fontname, buttonText, self.options.fontNames || [], self.id_prefix);
                        break;
                    case cmd_fontsize:
                        button = self._createDropdownButton(buttonTip, cmd_fontsize, buttonText, self.options.fontSizes || [], self.id_prefix);
                        break;
                    case cmd_spelling:
                        break;
                }

                return button;
            };

            //end of special button
            wijeditor.prototype._createGroup = function (groupName, groupButtons) {
                var self = this, group = wijribbonDataRender.createElement("li"), groupString = self.localizeString(groupName.toLowerCase() + "Group", groupName);

                self._createGroupButtons(group, groupButtons);

                group.add(wijribbonDataRender.createElement("div", groupString, { displayname: groupName }));

                return group;
            };

            wijeditor.prototype._createGroupButtons = function (groupElement, buttons) {
                var self = this, rbList, container = groupElement, button;

                // create buttons
                $.each(buttons, function (index, name) {
                    if (name === "") {
                        container = groupElement;
                        rbList = wijribbonDataRender.createRibbonList();
                        container.add(rbList);
                        container = rbList;
                    } else {
                        button = self._createButtonByCommand(name);
                        if ($.isArray(button) && button.length > 0) {
                            $.each(button, function (idx, btn) {
                                container.add(btn);
                            });
                        } else {
                            container.add(self._createButtonByCommand(name));
                        }
                    }
                });
            };

            wijeditor.prototype._getDefaultRibbonMarkup = function () {
                var self = this, rb = wijribbonDataRender.createElement("div"), rbTabs = wijribbonDataRender.createElement("ul"), rbFmtTab = wijribbonDataRender.createElement("li"), rbIstTab = wijribbonDataRender.createElement("li"), rbFmtPnl = wijribbonDataRender.createElement("div", { id: self.id_prefix + "format" }), rbIstPnl = wijribbonDataRender.createElement("div", { id: self.id_prefix + "insert" }), rbFmtGrps = wijribbonDataRender.createElement("ul"), rbIstGrps = wijribbonDataRender.createElement("ul"), formatTabString = self.localizeString("formatTab", "Format"), insertTabString = self.localizeString("insertTab", "Insert");

                //ribbon tab.
                rb.add(rbTabs);
                rb.add(rbFmtPnl);
                rb.add(rbIstPnl);

                rbTabs.add(rbFmtTab);
                rbTabs.add(rbIstTab);

                rbFmtTab.add(wijribbonDataRender.createElement("a", formatTabString, {
                    href: "#" + self.id_prefix + "format"
                }));
                rbIstTab.add(wijribbonDataRender.createElement("a", insertTabString, {
                    href: "#" + self.id_prefix + "insert"
                }));

                //format groups
                rbFmtPnl.add(rbFmtGrps);
                $.each(formatGroupInfo, function (action, buttons) {
                    rbFmtGrps.add(self._createGroup(action, buttons));
                });

                //insert groups
                rbIstPnl.add(rbIstGrps);
                $.each(insertGroupInfo, function (action, buttons) {
                    rbIstGrps.add(self._createGroup(action, buttons));
                });

                return rb.render();
            };

            wijeditor.prototype._resetModesBtnTip = function (css, buttonInfo) {
                var editorFooter = this.element.find(".wijeditor-footer"), button = $(editorFooter.find("." + css));

                if (button.length > 0) {
                    buttonInfo.tip = button.attr("title") || buttonInfo.tip;
                }
            };

            wijeditor.prototype._getRibbonModesMarkup = function () {
                var self = this, rb = wijribbonDataRender.createDiv(css_ribbon_modes), rbList = wijribbonDataRender.createRibbonList(), editorFooter = self.element.find(".wijeditor-footer");

                //added for localization
                if (editorFooter.length > 0) {
                    self._resetModesBtnTip(css_ribbon_designview, buttonInfoAsCommand.Wysiwyg);
                    self._resetModesBtnTip(css_ribbon_splitview, buttonInfoAsCommand.Split);
                    self._resetModesBtnTip(css_ribbon_sourceview, buttonInfoAsCommand.Code);
                    self._resetModesBtnTip(css_ribbon_wordwrap, buttonInfoAsCommand.Wordwrap);
                    self._resetModesBtnTip(css_ribbon_fullscreen, buttonInfoAsCommand.FullScreen);
                    editorFooter.remove();
                }

                rb.add(rbList);

                self._createGroupButtons(rbList, ["Wysiwyg", "Code", "Split"]);
                self._createGroupButtons(rb, ["Wordwrap", "FullScreen"]);

                return rb.render();
            };

            wijeditor.prototype._getSimpleToolBar = function (simpleModeCommands) {
                var self = this, button, rb = wijribbonDataRender.createDiv("");

                $.each(simpleModeCommands, function (idx, cmd) {
                    button = self._createButtonByCommand(cmd);
                    if (button) {
                        if ($.inArray(cmd, imageTypeButton) !== -1) {
                            $.each(button, function (idx, btn) {
                                rb.add(btn);
                            });
                        } else {
                            rb.add(button);
                        }
                    }
                });

                return rb.render();
            };

            wijeditor.prototype._editorify = function () {
                var self = this, element = self.element, width = element.width(), height = element.height(), o = self.options, mode = o.mode, container, content, filterCustomSimpleModeCommands, ribbons, footer, $content, text;

                self._oriStyle = element.attr("style");
                self._oriContent = element.html();
                self._oriEleWidth = width;
                self._oriEleHeight = height;

                if (element.is("textarea")) {
                    if (mode === "ribbon") {
                        self.$ribbon = $(self._getDefaultRibbonMarkup());
                    } else if (mode === "bbcode") {
                        self.$ribbon = $(self._getSimpleToolBar(defaultBBCodeModeCommands));
                    } else {
                        if (o.simpleModeCommands && o.simpleModeCommands.length !== 0) {
                            //Note: filter table command
                            filterCustomSimpleModeCommands = $.grep(o.simpleModeCommands, function (n, i) {
                                return n !== "Table";
                            }, undefined);
                            self.$ribbon = $(self._getSimpleToolBar(filterCustomSimpleModeCommands));
                        } else {
                            self.$ribbon = $(self._getSimpleToolBar(defaultSimpleModeCommands));
                        }
                    }
                    if (o.text) {
                        element.val(o.text);
                    }
                    self.sourceView = element;
                    self.editor = element.wrap("<div></div>").parent();
                    self.editor.width(width).height(height);
                } else {
                    self.editor = element;
                    self.$ribbon = element.children(":eq(0)");
                    $content = element.children(":eq(1)");

                    if ($content.is("textarea")) {
                        if (o.text) {
                            $content.val(o.text);
                        }
                        self.sourceView = $content;
                    } else {
                        if (o.text) {
                            text = o.text;
                        } else {
                            text = $content.html();
                        }

                        $content.remove();
                        self.sourceView = $("<textarea aria-label='textarea'></textarea>").val(text);
                    }
                }

                container = $("<div class='" + css_editor_container + "'></div>");
                self.dialog = $("<div class ='" + css_editor + "'></div>");
                self.subDialog = $("<div class ='" + css_editor + "'></div>");
                self.editor.addClass(css_editor).addClass(self.options.wijCSS.widget).append(container).append(self.dialog).append(self.subDialog);
                self._createMenuMarkUp(self, o);

                //head
                //ribbon
                self.$ribbon.wrap("<a href='javascript:void(null)'></a>").parent().appendTo("<div class='" + css_editor_header + " ui-widget-header ui-helper-clearfix ui-corner-top'></div>").parent().appendTo(container);

                //content
                content = $("<div class='" + css_editor_content + "'></div>").appendTo(container);

                self.designView = $("<iframe frameborder='0'></iframe>");

                self.designView.wrap("<div></div>").parent().appendTo(content);
                self.sourceView.wrap("<div></div>").parent().appendTo(content);

                ribbons = [self.$ribbon];
                self.$modes = $(self._getRibbonModesMarkup());

                //footer
                if (o.showFooter) {
                    footer = $("<div class='" + css_editor_footer + " " + "ui-widget ui-widget-content ui-state-default'></div>");
                    container.append(footer);
                    footer.append("<div class='" + css_editor_pathselector + "'></div>");

                    self.$modes.appendTo(footer);
                    ribbons.push(self.$modes);
                }

                $.each(ribbons, function (idx, ribbon) {
                    ribbon.wijribbon({
                        compactMode: self.options.compactRibbonMode,
                        click: function (e, data) {
                            self._ribbonCommand(data.commandName, data.name);
                            self._trigger('commandButtonClick', e, data);
                        }
                    });
                });
            };

            //fixed bug for customContextMenu
            wijeditor.prototype._createMenuMarkUp = function (self, o) {
                if (o.customContextMenu) {
                    self.contextMenu = $("<ul>" + "<li _c1buttoncmd='cut'><a>" + this.localizeString("contextMenuCut", "Cut") + "</a></li>" + "<li _c1buttoncmd='copy'><a>" + this.localizeString("contextMenuCopy", "Copy") + "</a></li>" + "<li _c1buttoncmd='paste'><a>" + this.localizeString("contextMenuPaste", "Paste") + "</a></li></ul>");

                    $("<a href='#'></a>").append(self.contextMenu).appendTo(self.editor);
                }
            };

            wijeditor.prototype._handleDisabledOption = function (disabled, ele) {
                var self = this;

                if (disabled) {
                    if (!self.disabledDiv) {
                        self.disabledDiv = self._createDisabledDiv(ele);
                    }
                    $("body").focus();
                    self.disabledDiv.appendTo(self.editor);
                } else {
                    if (self.disabledDiv) {
                        self.disabledDiv.remove();
                        self.disabledDiv = null;
                    }
                }
            };

            wijeditor.prototype._createDisabledDiv = function (outerEle) {
                var self = this, ele = outerEle ? outerEle : self.element, disabledWidth = ele.outerWidth(), disabledHeight = ele.outerHeight();

                return $("<div></div>").addClass("ui-state-disabled").css({
                    "z-index": "99999",
                    position: "relative",
                    "background-color": "lightgray",
                    width: disabledWidth,
                    height: disabledHeight,
                    left: 0,
                    top: -disabledHeight
                });
            };

            wijeditor.prototype._initElements = function () {
                var self = this, o = self.options, contentHeight = self.editor.height() - self._getHeader().outerHeight(true) - self._getFooter().outerHeight(true), buttonStates = {};

                self._getContent().height(contentHeight).wijsplitter({
                    showExpander: false,
                    orientation: "horizontal",
                    panel1: {
                        scrollBars: "none",
                        collapsed: false
                    },
                    panel2: {
                        scrollBars: "none",
                        collapsed: true
                    }
                });
                self.sourceView.css("width", "").css("height", "");
                self._addHandlerToDesignView();
                self._addDefaultFontStyleToDesignView();
                self._createWijMenu();

                if (!o.showPathSelector || self.options.mode === "bbcode") {
                    self._getPathSelector().hide();
                }
                self._ribbonCommand(o.editorMode, null, true);

                if (o.fullScreenMode) {
                    self._setFullScreen(o.fullScreenMode);
                }

                buttonStates[cmd_redo] = true;
                buttonStates[cmd_undo] = true;
                self.$ribbon.wijribbon(setButtonsDisabled, buttonStates);
                self._handleWinDocumentKeyDown();
            };

            wijeditor.prototype._handleWinDocumentKeyDown = function () {
                var self = this;
                $(document).bind('keydown.' + self.widgetName + "." + self.id_prefix.replace(/-/g, ""), function (e) {
                    if (self._isDisabled()) {
                        return;
                    }
                    switch (e.keyCode) {
                        case 27:
                            self._escActionAssociated();
                            break;
                    }
                });
            };

            wijeditor.prototype._setOption = function (key, value) {
                var self = this, o = self.options, oldMode = o.mode, oldEditorMode = o.editorMode, oldCompactRibbonMode = o.compactRibbonMode, ribbonParent = self.$ribbon.parent(), oldFullScreenMode = o.fullScreenMode, oldCustomContextMenu = o.customContextMenu;

                _super.prototype._setOption.call(this, key, value);

                if (key === "fullScreenMode") {
                    if (value !== oldFullScreenMode) {
                        self._setFullScreen(value);
                    }
                } else if (key === "showPathSelector") {
                    if (value) {
                        self._getPathSelector().show();
                        self._refreshPathSelector();
                    } else {
                        self._getPathSelector().hide();
                    }
                } else if (key === "editorMode" && oldEditorMode !== value) {
                    self._ribbonCommand(value);
                    if (self.$modes.data("wijmo-wijribbon")) {
                        self.$modes.wijribbon(setButtonChecked, oldEditorMode, false);
                    }
                } else if (key === "fullScreenContainerSelector") {
                    if (self.options.fullScreenMode) {
                        self._setFullScreen(true);
                    }
                } else if (key === "showFooter") {
                    if (value) {
                        if (!($("." + css_editor_footer).is(":visible"))) {
                            $("." + css_editor_footer).show();
                        }
                    } else {
                        if (($("." + css_editor_footer).is(":visible"))) {
                            $("." + css_editor_footer).hide();
                        }
                    }
                } else if (key === "commandButtonClick") {
                    o.commandButtonClick = value;
                } else if (key === "text") {
                    self.setText(value);
                } else if (key === "customContextMenu") {
                    if (oldCustomContextMenu === value) {
                        return;
                    }
                    if (value) {
                        if (!self.contextMenu) {
                            self._createMenuMarkUp(self, o);
                        }
                        self._createWijMenu();
                    } else {
                        self.contextMenu[self._contextMenuWidgetName()]("destroy").remove();
                        self.contextMenu = undefined;
                    }
                } else if ((key === "mode" && value !== oldMode) || (key === "compactRibbonMode" && value !== oldCompactRibbonMode)) {
                    self._recreateRibbon(o.mode);
                    self._ribbonCommand(o.editorMode);
                } else if (key === "fontNames" || key === "fontSizes") {
                    self._recreateRibbon(o.mode);
                } else if (key === "readOnly") {
                    self._updateContentEditable();
                }
                //Todo
                //set the option tableVirtualBorderShowing
            };

            wijeditor.prototype._updateContentEditable = function () {
                var self = this, doc = self._getDesignViewWindow().document;
                if ($.browser.mozilla) {
                    setTimeout(self._setDesignModeForFF, 1000, self);
                } else {
                    self._setContentEditable(doc, !self.options.readOnly);
                }
                self.sourceView.attr("readonly", self.options.readOnly);
            };

            wijeditor.prototype._innerDisable = function () {
                _super.prototype._innerDisable.call(this);
                this._handleDisabledOption(true, this.editor);
            };

            wijeditor.prototype._innerEnable = function () {
                _super.prototype._innerEnable.call(this);
                this._handleDisabledOption(false, this.editor);
            };

            wijeditor.prototype._recreateRibbon = function (mode) {
                var self = this, ribbonParent = self.$ribbon.parent();
                self.$ribbon.wijribbon("destroy");
                self.$ribbon.remove();
                if (mode === "ribbon") {
                    self.$ribbon = $(self._getDefaultRibbonMarkup());
                } else if (mode === "bbcode") {
                    self.$ribbon = $(self._getSimpleToolBar(defaultBBCodeModeCommands));
                } else {
                    self.$ribbon = $(self._getSimpleToolBar(defaultSimpleModeCommands));
                }

                ribbonParent.append(self.$ribbon);
                self.$ribbon.wijribbon({
                    compactMode: self.options.compactRibbonMode,
                    click: function (e, data) {
                        self._ribbonCommand(data.commandName, data.name);
                        self._trigger('commandButtonClick', e, data);
                    }
                });
            };

            wijeditor.prototype._getHeader = function () {
                return $("." + css_editor_header, this.editor);
            };

            wijeditor.prototype._getContent = function () {
                return $("." + css_editor_content, this.editor);
            };

            wijeditor.prototype._getFooter = function () {
                return $("." + css_editor_footer, this.editor);
            };

            wijeditor.prototype._getPathSelector = function () {
                return $("." + css_editor_pathselector, this.editor);
            };

            wijeditor.prototype._getModes = function () {
                return $("." + css_ribbon_modes, this.editor);
            };

            wijeditor.prototype._getDesignView = function () {
                return this.designView;
            };

            wijeditor.prototype._getDesignViewWindow = function () {
                var $designView = this.designView;

                if ($designView && $designView.length > 0) {
                    return $designView[0].contentWindow;
                }

                return null;
            };

            wijeditor.prototype._getDesignViewDocument = function () {
                var win = this._getDesignViewWindow();

                if (win) {
                    return win.document;
                }

                return null;
            };

            wijeditor.prototype._getDesignViewText = function () {
                var doc = this._getDesignViewDocument();

                if (doc && doc.body && doc.body.innerHTML) {
                    return doc.body.innerHTML;
                }

                return "";
            };

            wijeditor.prototype._setDesignViewText = function (text) {
                var self = this, doc = this._getDesignViewDocument();

                if (this.options.mode === "bbcode") {
                    //Note: maybe need to trim the text.
                    text = self._convertBBCodeToHtml(text);
                }
                if (doc && doc.body) {
                    doc.body.innerHTML = text;
                }

                self.options.text = text;
            };

            wijeditor.prototype._getDialog = function () {
                return this.dialog;
            };

            wijeditor.prototype._getSubDialog = function () {
                return this.subDialog;
            };

            wijeditor.prototype._initContentDocument = function () {
                var self = this, text = self.sourceView.val(), doc = self._getDesignViewDocument(), tableVirtualBorderShowing = self.options.tableVirtualBorderShowing, bindLoadEvent = function () {
                    self.designView.load(function () {
                        try  {
                            self._addHandlerToDesignView();
                            self._addDefaultFontStyleToDesignView();
                            self._createWijMenu();
                        } catch (e) {
                        }
                    });
                };

                // fixed an issue that when contains image element, toggling full screen mode will cause endless loop in IE9+
                if (text !== "" && text === self._getDesignViewText()) {
                    return;
                }

                if (self.options.mode === "bbcode") {
                    //Note: trim leading/trailing whitespace
                    //because when get the innerhtml from body, there
                    //are some whitespace on leading/trailing
                    text = self._convertBBCodeToHtml($.trim(text));
                }

                self.designView.unbind("load");
                doc.open();
                doc.write("<html style=\"width:100%;height:100%;" + (self.options.enabled ? "cursor:text;" : "") + "\"><head><title></title><style id=\"__wijStyle\" " + " type=\"text/css\" >table,td,tr{border: 1px #acacac dashed;}hr.pagebreak{visibility: visible!important;}" + "</style></head><body style=\"word-wrap:break-word\">" + text + "</body></html>");
                doc.close();
                if (!tableVirtualBorderShowing) {
                    self._updateTableBorderShowing(tableVirtualBorderShowing);
                    self.$ribbon.wijribbon(setButtonChecked, cmd_borders, !tableVirtualBorderShowing);
                }
                if (self.element.attr("accesskey")) {
                    $(doc.body).attr("accesskey", self.element.attr("accesskey"));
                    self.element.removeAttr("accesskey");
                }
                undoBuffers = [];
                undoBuffers.push(text);
                undoSteps = 0;
                bindLoadEvent();
            };

            wijeditor.prototype._addHandlerToDesignView = function () {
                var self = this, win = self._getDesignViewWindow(), doc = win.document;

                self._initContentDocument();

                self._loadDesignView();

                //before lose focus, save the selection in ie.
                if ($.browser.msie) {
                    $(doc).unbind("beforedeactivate").bind("beforedeactivate", function () {
                        self._saveSelectionForIE();
                    });
                }
            };

            wijeditor.prototype._loadDesignView = function () {
                var self = this, win = self._getDesignViewWindow(), doc = win.document;

                self._updateContentEditable();

                if ($.browser.msie) {
                    self._setContentSpellCheck(doc, false);
                }

                self.sourceView.unbind('blur.' + self.widgetName).bind('blur.' + self.widgetName, function (e) {
                    self._onSourceViewBlur(e);
                });

                //add for any change happens, the text would be saved
                self.sourceView.unbind('keyup.' + self.widgetName).bind('keyup.' + self.widgetName, function (e) {
                    self._onSourceViewBlur(e);
                });

                //note: in safari and chrome, the source view is show null
                if (!$.browser.mozilla) {
                    $(win).blur(function (e) {
                        self._onDesignViewBlur(e);
                    });
                } else {
                    $(doc).unbind('blur.' + self.widgetName).bind('blur.' + self.widgetName, function (e) {
                        self._onDesignViewBlur(e);
                    });
                }

                $(doc).unbind('mouseup.' + self.widgetName).bind('mouseup.' + self.widgetName, function (e) {
                    self._onDesignViewMouseUp(e);
                }).unbind('keydown.' + self.widgetName).bind('keydown.' + self.widgetName, function (e) {
                    self._onDesignViewKeyDown(e);
                }).unbind('keyup.' + self.widgetName).bind('keyup.' + self.widgetName, function (e) {
                    self._onDesignViewKeyUp(e);

                    //add for any change happens, the text would be saved
                    self._onDesignViewBlur(e);
                });
            };

            wijeditor.prototype._addDefaultFontStyleToDesignView = function () {
                var self = this, o = self.options, doc = self._getDesignViewDocument(), defaultFontName = o.defaultFontName, defaultFontSize = o.defaultFontSize, defaultFontStyleString = "<style type=\"text/css\"> body {";

                if ((defaultFontName === "" || defaultFontName === null) && (defaultFontSize === "" || defaultFontSize === null)) {
                    return;
                }

                if (defaultFontName !== "" && defaultFontName !== null) {
                    defaultFontStyleString += "font-family: " + defaultFontName + ";";
                }

                if (o.defaultFontSize !== "" && o.defaultFontSize !== null) {
                    defaultFontStyleString += " font-size: " + defaultFontSize + ";";
                }

                defaultFontStyleString += "}</style>";

                window.setTimeout(function () {
                    $(defaultFontStyleString).appendTo($("head", doc));
                }, 200);

                self._setFontStyleButtonState(defaultFontName, cmd_fontname);
                self._setFontStyleButtonState(defaultFontSize, cmd_fontsize);
            };

            wijeditor.prototype._setFontStyleButtonState = function (defaultValue, cmd) {
                var defaultKey = "";
                if (!defaultValue || defaultValue === null) {
                    return;
                }
                $.each(this.$ribbon.wijribbon("getDropdownList", cmd), function (key, value) {
                    if (value.toUpperCase() === defaultValue.toUpperCase()) {
                        defaultKey = key;
                        return false;
                    }
                });
                this.$ribbon.wijribbon(setButtonChecked, defaultKey, true, cmd);
            };

            wijeditor.prototype._setDesignModeForFF = function (self) {
                var dvDoc = self._getDesignViewDocument();
                if (dvDoc) {
                    dvDoc.designMode = self.options.readOnly ? "off" : "on";
                }
            };

            /**
            * Remove the functionality completely. This will return the element back to its pre-init state.
            */
            wijeditor.prototype.destroy = function () {
                var self = this;

                self.element.html(self._oriContent);
                self.element.removeAttr("tabindex").removeAttr("aria-label");

                if (self._oriStyle === undefined) {
                    self.element.removeAttr("style");
                } else {
                    self.element.attr("style", self._oriStyle);
                }

                if (self.dialog) {
                    self.dialog.remove();
                }
                self.element.insertBefore(self.editor);
                self.element.unbind('.' + self.widgetName);
                $(document).unbind('.' + self.widgetName + "." + self.id_prefix.replace(/-/g, ""));
                self.element.removeUniqueId();
                if (self.element.is("textarea")) {
                    self.editor.remove();
                } else {
                    self.editor.removeClass(self.options.wijCSS.widget).removeClass(css_editor);
                }

                if (self._oriDocOverFlow) {
                    $(document.documentElement).css({
                        overflow: self._oriDocOverFlow
                    });
                }

                $.Widget.prototype.destroy.call(self);
            };

            /** @ignore */
            wijeditor.prototype.showEditorDialog = function (dialogCmd) {
                switch (dialogCmd) {
                    case cmd_inserttable:
                    case cmd_template:
                    case cmd_imagebrowser:
                    case cmd_inspect:
                    case cmd_find:
                    case cmd_specialchar:
                    case cmd_media:
                    case cmd_cleanup:
                    case cmd_link:
                    case cmd_backcolor:
                    case cmd_fontcolor:
                    case cmd_insertcode:
                        this._ribbonCommand(dialogCmd);
                        break;
                    default:
                        wijAlert(this.localizeString("notFindCommandError", "Cannot find the dialog with command name '") + dialogCmd + "'!");
                        break;
                }
            };

            /** @ignore */
            wijeditor.prototype.executeEditorAction = function (command, parentCmd) {
                this._ribbonCommand(command, parentCmd);
            };

            wijeditor.prototype._isFontSizeCustomized = function () {
                if (isFontSizeCustomized !== null) {
                    return isFontSizeCustomized;
                }

                var fontSizes = this.$ribbon.wijribbon("getDropdownList", cmd_fontsize), fss = [
                    cmd_verysmall, cmd_smaller, cmd_small,
                    cmd_medium, cmd_large, cmd_larger, cmd_verylarge];

                isFontSizeCustomized = false;

                $.each(fontSizes, function (key, value) {
                    if ($.inArray(key, fss) === -1) {
                        isFontSizeCustomized = true;
                        return false;
                    }
                });

                return isFontSizeCustomized;
            };

            wijeditor.prototype._fontSizeCommand = function (cmd) {
                var self = this, doc = self._getDesignViewDocument(), docSelection, arg = 4, fontSize = "font-size", $spans = [];

                if (self._getDesignViewWindow().getSelection) {
                    docSelection = self._getDesignViewWindow().getSelection();
                }
                switch (cmd) {
                    case cmd_verysmall:
                        arg = 1;
                        break;
                    case cmd_smaller:
                        arg = 2;
                        break;
                    case cmd_small:
                        arg = 3;
                        break;
                    case cmd_medium:
                        arg = 4;
                        break;
                    case cmd_large:
                        arg = 5;
                        break;
                    case cmd_larger:
                        arg = 6;
                        break;
                    case cmd_verylarge:
                        arg = 7;
                        break;
                }

                self._setIEFocus();

                //Add comments by RyanWu@20110915.
                //For implementing the font-size
                //support px/pt etc other than only small/x-small/x-large/large...
                //doc.execCommand("FontSize", false, arg);
                if (!self._isFontSizeCustomized()) {
                    if ($.browser.msie && wijParseInt($.browser.version) >= 9) {
                        if (docSelection && docSelection.rangeCount > 0) {
                            doc.execCommand("FontSize", false, arg);
                        }
                    } else {
                        doc.execCommand("FontSize", false, arg);
                    }
                } else {
                    self._formatFontSpan(doc, fontSize, cmd);
                }

                //end by RyanwWu@20110915.
                if (self.options.mode === "bbcode" && !($.browser.msie)) {
                    self._convertFontStyleToStandTag();
                }

                self._addtoUndoBuffer();
            };

            wijeditor.prototype._fontNameCommand = function (cmd) {
                var self = this, doc = self._getDesignViewDocument(), docSelection, fontNames = self.$ribbon.wijribbon("getDropdownList", cmd_fontname), fontName;

                if (self._getDesignViewWindow().getSelection) {
                    docSelection = self._getDesignViewWindow().getSelection();
                }
                $.each(fontNames, function (key, value) {
                    if (cmd === key) {
                        fontName = value;
                        return false;
                    }
                });

                self._setIEFocus();
                doc.execCommand("FontName", false, fontName);

                self._addtoUndoBuffer();
            };

            //Add comments by RyanWu@20110922.
            //For implementing the font-size
            //support px/pt etc other than only small/smaller/larger/large...
            wijeditor.prototype._formatFontSpan = function (doc, cssName, cssValue) {
                var self = this, tempValue = cssValue, styleAttrName = "fontFamily", $spans = [], orgValue;

                if (cssName !== "font-family") {
                    tempValue = "c1-temp";
                    styleAttrName = "fontSize";
                    orgValue = self._queryCommandValue(cmd_fontname);
                    if (orgValue !== "undefined") {
                        tempValue = orgValue;
                    }
                }
                doc.execCommand("FontName", false, tempValue);

                if ($("font[face='" + tempValue + "']", doc).length === 0) {
                    tempValue = "c1-temp";
                    doc.execCommand("FontName", false, tempValue);
                }

                $.each($("font[face='" + tempValue + "']", doc), function (i, fn) {
                    var $span = self._replaceFontWithSpan($(fn), "face", cssName, cssValue), $children, idx;

                    $spans.push($span);

                    //1. remove all font-family style of the child spans.
                    //<span style="font-family:B">blah<span style="font-family:A">
                    //</span></span>,
                    //need remove the span whose font-family is A
                    $children = $("span." + css_formatspan, $span);

                    for (idx = $children.length - 1; idx >= 0; idx--) {
                        self._removeSpecifiedStyleSpan($($children[idx]), styleAttrName, cssName);
                    }

                    //2. remove duplicated spans.
                    //<span style="font-family:A">
                    //<span style="font-family:B">blah</span></span>
                    $.each($span, function (idx, span) {
                        $.each($(span).parents("span." + css_formatspan), function (i, parent) {
                            var $parent = $(parent);

                            if ($parent.children().length > 1) {
                                return false;
                            }

                            if ($parent.text() === $(span).text()) {
                                self._removeSpecifiedStyleSpan($parent, styleAttrName, cssName);
                            }
                        });
                    });
                });

                self._setSelection($spans);
            };

            wijeditor.prototype._replaceFontWithSpan = function ($fn, attrName, cssName, cssValue) {
                $fn.wrap("<span class = '" + css_formatspan + "' style='" + cssName + ":" + cssValue + "'></span>");
                var $span = $fn.parent();

                // Do not reset the font name unless "c1-temp".
                if ($fn.attr(attrName) === "c1-temp") {
                    $fn.removeAttr(attrName);
                }

                if (/<font\s*>/ig.test($span.html())) {
                    $span.html($fn.html());
                    $fn.remove();
                }

                return $span;
            };

            wijeditor.prototype._removeSpecifiedStyleSpan = function ($span, styleAttrName, cssAttrName) {
                var style, shouldRemove = true;

                if ($span[0].style[styleAttrName] !== "") {
                    $span.css(cssAttrName, "");
                }
                style = $span.attr("style");

                if (style) {
                    $.each(style.split(';'), function (i, attr) {
                        var styleAttr = $.trim(attr).toLowerCase();
                        if (styleAttr !== "" && styleAttr.indexOf(cssAttrName) !== -1) {
                            shouldRemove = false;
                            return false;
                        }
                    });
                }

                if (shouldRemove) {
                    $span.replaceWith($span.html());
                }
            };

            wijeditor.prototype._removeFormat = function () {
                var self = this, doc = self._getDesignViewDocument(), buttonStates = {};

                doc.execCommand(cmd_removeformat, false, null);

                if (self._isFontSizeCustomized() && $.browser.msie) {
                    self._removeFormatForIE(doc);
                }
                self._addtoUndoBuffer();
                buttonStates[cmd_bold] = false;
                buttonStates[cmd_italic] = false;
                buttonStates[cmd_strike] = false;
                buttonStates[cmd_underline] = false;
                buttonStates[cmd_subscript] = false;
                buttonStates[cmd_superscript] = false;
                buttonStates[cmd_numberedlist] = false;
                buttonStates[cmd_bulletedlist] = false;
                buttonStates[cmd_alignleft] = false;
                buttonStates[cmd_aligncenter] = false;
                buttonStates[cmd_alignright] = false;
                buttonStates[cmd_alignfull] = false;

                self.$ribbon.wijribbon(setButtonsChecked, buttonStates);
            };

            wijeditor.prototype._removeFormatForIE = function (doc) {
                var range = this._getIESelectionRange(), htmlText = this._getSelectedContent(), text = this._getSelectedContent(true), start = 0, selection = doc.getSelection(), $parent = this._isIE11 ? ((selection && selection.anchorNode && selection.anchorNode.parentNode) ? $(selection.anchorNode.parentNode) : null) : $(range.parentElement()), $body = $(doc.body), preHtml = "", sufHtml = "", specialStr = "__c1temp", specialCss = "c1-temp", tempSpan = "<span class='" + specialCss + "'>" + specialStr + "</span>", $tempSpan, $tempSibling, $spans, $span, idx, items, frag;

                //1. <span style="font-size:20pt">A[B</span>C]D
                //2. <span style="font-size:20pt">A[B</span>CD<span style="font-size:30pt">EF]G</span>
                //3. <span style="font-size:20pt">A[BC]D</span>
                //4. <span style="font-family:arial"><span style="font-size:20pt">A[B</span>CD<span style="font-size:30pt">EF]G</span></span>
                $parent.addClass("c1-app-parent");

                if (this._isIE11) {
                    range.deleteContents();
                    frag = range.createContextualFragment(tempSpan);
                    range.insertNode(frag);
                    range.collapse(false);
                } else {
                    range.pasteHTML(tempSpan);
                }

                start = $body.text().indexOf(specialStr);
                $tempSpan = $("span." + specialCss, doc);
                $tempSibling = $tempSpan;

                $tempSpan.parentsUntil("body").each(function (index) {
                    if ($(this).is(".c1-app-parent")) {
                        return false;
                    }

                    $tempSibling = $(this);
                });
                $tempSpan.html(htmlText);

                $spans = $("span." + css_formatspan, $tempSpan);

                for (idx = $spans.length - 1; idx >= 0; idx--) {
                    $span = $($spans[idx]);

                    $span.replaceWith($span.html());
                }

                if (!$tempSibling.is("." + specialCss)) {
                    $tempSibling.after($tempSpan);
                }

                $.each($tempSibling.parents("span." + css_formatspan), function (index, p) {
                    preHtml += "</span>";
                    sufHtml = "<span class='" + css_formatspan + "' style = '" + $(p).attr("style") + "'>" + sufHtml;
                });

                htmlText = $tempSpan.html();
                $tempSpan.replaceWith(specialStr);
                items = $body.html().split(specialStr);

                $body.html(items[0] + preHtml + htmlText + sufHtml + items[1]);

                $spans = $("span." + css_formatspan, doc);

                for (idx = $spans.length - 1; idx >= 0; idx--) {
                    $span = $($spans[idx]);

                    if ($span.text() === "") {
                        $span.replaceWith($span.html());
                    }
                }

                $(".c1-app-parent", doc).removeClass("c1-app-parent");

                this._setSelection(null, start, text.length);
            };

            //end by RyanwWu@20110922.
            wijeditor.prototype._toggleFullScreen = function () {
                var self = this, o = self.options;

                o.fullScreenMode = !o.fullScreenMode;

                self._setFullScreen(o.fullScreenMode);
                self.$modes.wijribbon(setButtonChecked, cmd_fullscreen, o.fullScreenMode);
                self.$modes.wijribbon("removeButtonHoverState", cmd_fullscreen);
            };

            wijeditor.prototype._setFullScreen = function (fullScreenMode) {
                var self = this, borderWidth = 1, header = self._getHeader(), footer = self._getFooter(), content = self._getContent(), cSelector = self.options.fullScreenContainerSelector, $container = $(cSelector), oriHtml = self._getDesignViewText(), width, height, contentHeight;

                if (fullScreenMode) {
                    if ($container.length === 0) {
                        $container = $(wijWindow);
                        cSelector = "body";

                        //note:add the block for preventing the scrollbar appear
                        self._oriDocOverFlow = $(document.documentElement).css("overflow");
                        $(document.documentElement).css({
                            overflow: "hidden"
                        });

                        //end for block
                        //note: if the content exclude the editor, the window still
                        //has the scroll, need to do some adjustment.
                        if (!$.browser.mozilla) {
                            window.scrollTo(0, 0);
                        }
                        $(wijWindow).bind("resize.wijeditor", function () {
                            self._fullscreenOnWindowResize();
                        });
                    }

                    width = $container.width();
                    height = $container.height() - 2 * borderWidth;
                    oriWidth = self.editor.width();
                    oriHeight = self.editor.height();

                    if (!$oriParent) {
                        $oriParent = self.editor.parent();
                    }

                    if (!self._replacedDiv) {
                        self._replacedDiv = $("<div />");
                    }

                    self.editor.after(self._replacedDiv);

                    $(cSelector).append(self.editor);

                    self.editor.css({
                        width: width,
                        height: height,
                        position: ""
                    }).addClass(css_editor_fullscreen);

                    self.$ribbon.wijribbon("updateRibbonSize");
                } else {
                    self._replacedDiv.after(self.editor).remove();

                    self.editor.css({
                        width: oriWidth,
                        height: oriHeight,
                        position: "static"
                    }).removeClass(css_editor_fullscreen);

                    if (!self.options.fullScreenContainerSelector) {
                        $(document.documentElement).css({
                            overflow: self._oriDocOverFlow
                        });
                    }
                    $(wijWindow).unbind("resize.wijeditor");
                    self.$ribbon.wijribbon("updateRibbonSize");
                }

                if (self.disabledDiv) {
                    if (fullScreenMode) {
                        self.disabledDiv.css({
                            position: "fixed",
                            width: "",
                            height: "",
                            left: 0,
                            top: 0,
                            right: 0,
                            bottom: 0
                        });
                    } else {
                        self.disabledDiv.css({
                            position: "relative",
                            width: self.editor.outerWidth(),
                            height: self.editor.outerHeight(),
                            left: 0,
                            top: -self.editor.outerHeight(),
                            right: "",
                            bottom: ""
                        });
                    }
                }

                contentHeight = self.editor.height() - header.outerHeight(true) - footer.outerHeight(true);

                content.height(contentHeight).wijsplitter("refresh");

                if (self.$modes.data("wijmo-wijribbon")) {
                    self.$modes.wijribbon(setButtonChecked, cmd_fullscreen, fullScreenMode);
                }
            };

            wijeditor.prototype._createWijMenu = function () {
                var self = this, doc = self._getDesignViewDocument();
                if (self.contextMenu) {
                    self.contextMenu[self._contextMenuWidgetName()]({
                        orientation: 'vertical',
                        trigger: self.designView,
                        triggerEvent: 'rtclick',
                        showing: function (e, sublist) {
                            if ($.browser.msie) {
                                self._saveSelectionForIE();
                            }
                            var offset = self.designView.offset(), contentWindowScrollLeft = $($(self.designView)[0].contentWindow).scrollLeft(), contentWindowScrollTop = $($(self.designView)[0].contentWindow).scrollTop(), menuOffsetLeft = offset.left + 2 - contentWindowScrollLeft, menuOffsetTop = offset.top - contentWindowScrollTop;
                            sublist.options.position = {
                                my: 'left+' + menuOffsetLeft + ' ' + 'top+' + menuOffsetTop,
                                at: 'right top',
                                of: e,
                                collision: 'none none'
                            };
                        },
                        animation: { animated: "fade" },
                        select: function (e, item) {
                            self._setIESelection();
                            self._contextMenuItemClick(e, item);
                            self.contextMenu[self._contextMenuWidgetName()]("deactivate");
                        }
                    });
                }
            };

            wijeditor.prototype._fullscreenOnWindowResize = function () {
                var self = this, header = self._getHeader(), footer = self._getFooter(), content = self._getContent(), contentHeight, fWidth = $(window).width(), fHeight = $(window).height();

                self.editor.css({
                    width: fWidth,
                    height: fHeight
                });

                contentHeight = self.editor.height() - header.height() - footer.height();
                content.height(contentHeight);
                if (content.data("wijmo-wijsplitter")) {
                    content.wijsplitter("refresh");
                }
                //TODO
                //$ribbon.wijribbon("updateRibbonSize");
            };

            wijeditor.prototype._saveText = function (arg) {
            };

            wijeditor.prototype._doSpellCheck = function () {
            };

            wijeditor.prototype._ribbonCommand = function (cmd, parentCmd, isInit) {
                var self = this, disabled = self._isDisabled(), doc = self._getDesignViewDocument(), content = self._getContent(), selection, distance = content.height() / 2, elementName, selectedHtml, range;

                if ($.inArray(cmd, [cmd_sourceview, cmd_find, cmd_fullscreen, cmd_preview, cmd_splitview, cmd_wordwrap, cmd_designview]) < 0 && self.options.readOnly) {
                    return;
                }

                if (parentCmd === cmd_fontname) {
                    self._fontNameCommand(cmd);
                    self._onDesignViewBlur(null);
                    return;
                }

                if (parentCmd === cmd_fontsize) {
                    self._fontSizeCommand(cmd);
                    self._onDesignViewBlur(null);
                    return;
                }

                if (!self.editor.hasClass("ui-helper-hidden-accessible") && !disabled) {
                    // when the editor is place another container widget, such as accordion, and the container is invisible after
                    // the container widget init. if firstly create the editor widget, and then create the container widget,
                    // the iframe will be focusd in ie9, and in the container widget, it looks like someting can edit.
                    if (isInit) {
                        setTimeout(function () {
                            self._setIEFocus();
                        }, 0);
                    } else {
                        // when the design view losefocus, the last selection will lost;
                        // so use focus method to set last selection.
                        if ($.browser.msie) {
                            self.focus();
                        }
                    }
                }

                switch (cmd) {
                    case cmd_blockquote:
                        if ($.browser.msie) {
                            // we first change the block into <ADDRESS> tags,
                            // using the FormatBlock functionality of the execCommand
                            doc.execCommand("FormatBlock", false, "<ADDRESS>");
                            if (self._isIE11 && doc.getSelection) {
                                selection = doc.getSelection();
                                if (selection && selection.anchorNode) {
                                    range = $(selection.anchorNode).closest("address");
                                }
                            } else {
                                range = doc.selection.createRange();
                                range = $(range.parentElement()).closest("address");
                            }

                            if (range.length) {
                                // then sneakily we use regex's to replace
                                // <ADDRESS> tags with <BLOCKQUOTE> tags
                                range.replaceWith("<blockquote>" + range.html() + "</blockquote>");

                                // then we tidy any extra <BLOCKQUOTES>
                                //that have been unhelpfully added.
                                doc.body.innerHTML = doc.body.innerHTML.replace(/<BLOCKQUOTE>\s*?<BLOCKQUOTE>/gi, "<BLOCKQUOTE>");
                                doc.body.innerHTML = doc.body.innerHTML.replace(/<\/BLOCKQUOTE>\s*?<\/BLOCKQUOTE>/gi, "<\/BLOCKQUOTE>");
                                doc.body.innerHTML = doc.body.innerHTML.replace(/<BLOCKQUOTE>\s*?<\/BLOCKQUOTE>/gi, "");
                            }
                        } else {
                            doc.execCommand("FormatBlock", false, "<BLOCKQUOTE>");
                        }
                        self._addtoUndoBuffer();
                        self._setFocusNotIE();
                        break;
                    case cmd_form:
                        elementName = self._generateUniqueName('form');
                        self.insertHTML('<form id="' + elementName + '" name="' + elementName + '" method="post">' + elementName + '</form>');
                        self._setFocusNotIE();
                        break;
                    case cmd_imagebutton:
                        elementName = self._generateUniqueName('image');
                        self.insertHTML('<input id="' + elementName + '" name="' + elementName + '" type="image"' + ' value="' + elementName + '"/>');
                        self._setFocusNotIE();
                        break;
                    case cmd_textarea:
                        elementName = self._generateUniqueName('textarea');
                        self.insertHTML('<textarea id="' + elementName + '" name="' + elementName + '" rows="4" cols="48"></textarea>');
                        self._setFocusNotIE();
                        break;
                    case cmd_button:
                        elementName = self._generateUniqueName('button');
                        self.insertHTML('<input id="' + elementName + '" name="' + elementName + '" type="button"' + ' value="' + elementName + '"/>');
                        self._setFocusNotIE();
                        break;
                    case cmd_textbox:
                        elementName = self._generateUniqueName('textbox');
                        self.insertHTML('<input id="' + elementName + '" name="' + elementName + '" type="text"' + ' value="' + elementName + '"/>');
                        self._setFocusNotIE();
                        break;
                    case cmd_listbox:
                        elementName = self._generateUniqueName('list');
                        self.insertHTML('<select id="' + elementName + '" name="' + elementName + '" style="width: 120px" size="8"></select>');
                        self._setFocusNotIE();
                        break;
                    case cmd_password:
                        elementName = self._generateUniqueName('password');
                        self.insertHTML('<input id="' + elementName + '" name="' + elementName + '" type="password" value="' + elementName + '"/>');
                        self._setFocusNotIE();
                        break;
                    case cmd_dropdownlist:
                        elementName = self._generateUniqueName('dropdown');
                        self.insertHTML('<select id="' + elementName + '" name="' + elementName + '"></select>');
                        self._setFocusNotIE();
                        break;
                    case cmd_hiddenfield:
                        elementName = self._generateUniqueName('hidden');
                        self.insertHTML('<input id="' + elementName + '" name="' + elementName + '" type="hidden" value="' + elementName + '" />');
                        self._setFocusNotIE();
                        break;
                    case cmd_radio:
                        elementName = self._generateUniqueName('radiobox');
                        self.insertHTML('<input id="' + elementName + '" name="' + elementName + '" type="radio"' + ' value="' + elementName + '">' + '<label for="' + elementName + '">' + elementName + '</label></input>');
                        self._setFocusNotIE();
                        break;
                    case cmd_checkbox:
                        elementName = self._generateUniqueName('checkbox');
                        self.insertHTML('<input id="' + elementName + '" name="' + elementName + '" type="checkbox"' + ' value="' + elementName + '">' + '<label for="' + elementName + '">' + elementName + '</label></input>');
                        self._setFocusNotIE();
                        break;
                    case cmd_insertcolumn:
                    case cmd_insertrow:
                    case cmd_insertcell:
                    case cmd_splitcell:
                    case cmd_mergecell:
                    case cmd_removecolumn:
                    case cmd_removerow:
                    case cmd_removecell:
                        self._tableAction(cmd);
                        break;
                    case cmd_borders:
                        self._toggleTableBorders();
                        break;
                    case cmd_subscript:
                        try  {
                            if (doc.queryCommandState(cmd_superscript)) {
                                doc.execCommand(cmd_superscript, false, null);
                                self.$ribbon.wijribbon(setButtonChecked, cmd_superscript, false);
                            }
                        } catch (e) {
                        }
                        doc.execCommand(cmd_subscript, false, null);
                        self._addtoUndoBuffer();
                        self._setFocusNotIE();
                        break;
                    case cmd_superscript:
                        try  {
                            if (doc.queryCommandState(cmd_subscript)) {
                                doc.execCommand(cmd_subscript, false, null);
                                self.$ribbon.wijribbon(setButtonChecked, cmd_subscript, false);
                            }
                        } catch (e1) {
                        }
                        doc.execCommand(cmd_superscript, false, null);
                        self._addtoUndoBuffer();
                        self._setFocusNotIE();
                        break;
                    case cmd_removeformat:
                        //doc.execCommand(cmd_removeformat, false, null);
                        self._removeFormat();
                        self._setFocusNotIE();
                        break;
                    case cmd_insertbreak:
                        self.insertHTML("<br/>");
                        self._setFocusNotIE();
                        break;
                    case cmd_insertparagraph:
                        selectedHtml = self._getSelectedContent();

                        if (!selectedHtml || selectedHtml === "") {
                            selectedHtml = "&nbsp;";
                        }

                        self.insertHTML('<p>' + selectedHtml + '</p>');
                        self._setFocusNotIE();
                        break;
                    case cmd_insertprintbreak:
                        self.insertHTML('<hr class="pagebreak" style="page-break-before:always;visibility:hidden" />');
                        self._setFocusNotIE();
                        break;
                    case cmd_fullscreen:
                        self._storeSelectionForIE();
                        self._toggleFullScreen();
                        break;
                    case cmd_undo:
                        self._undoAction();
                        self._setFocusNotIE();
                        break;
                    case cmd_redo:
                        self._redoAction();
                        self._setFocusNotIE();
                        break;
                    case cmd_cut:
                        self._execCut();
                        self._setFocusNotIE();
                        break;
                    case cmd_copy:
                        self._execCopy();
                        break;
                    case cmd_paste:
                        self._execPaste();
                        break;
                    case cmd_date:
                        self.insertDateAndTime();
                        self._setFocusNotIE();
                        break;
                    case cmd_designview:
                        if (self.$modes.data("wijmo-wijribbon")) {
                            self.$modes.wijribbon(setButtonDisabled, cmd_wordwrap, true).wijribbon(setButtonChecked, cmd_designview, true);
                        }
                        self.$ribbon.wijribbon("option", "disabled", false);

                        //TODO:maybe need to add the code block
                        //update for bbcode
                        //if (self.options.mode === "bbcode") {
                        //self._onSourceViewBlur();
                        //}
                        //end for update
                        content.wijsplitter("option", "panel2", {
                            collapsed: true
                        });
                        self._restoreSelectionForIE();
                        break;
                    case cmd_splitview:
                        if (self.$modes.data("wijmo-wijribbon")) {
                            self.$modes.wijribbon(setButtonDisabled, cmd_wordwrap, true).wijribbon(setButtonChecked, cmd_splitview, true);
                        }

                        self.$ribbon.wijribbon("option", "disabled", false);
                        content.wijsplitter("option", {
                            splitterDistance: distance,
                            panel1: { collapsed: false },
                            panel2: { collapsed: false }
                        });
                        self._restoreSelectionForIE();
                        break;
                    case cmd_sourceview:
                        if (self.$modes.data("wijmo-wijribbon")) {
                            self.$modes.wijribbon(setButtonDisabled, cmd_wordwrap, false).wijribbon(setButtonChecked, cmd_sourceview, true);
                        }
                        self._storeSelectionForIE();
                        self.$ribbon.wijribbon("option", "disabled", true);

                        //TODO:maybe need to add the code block
                        //update for bbcode
                        //if (self.options.mode === "bbcode") {
                        //self._onDesignViewBlur();
                        //}
                        //end for update
                        content.wijsplitter("option", "panel1", {
                            collapsed: true
                        });
                        if ($.browser.msie && !disabled) {
                            self.sourceView.focus();
                        }
                        break;
                    case cmd_wordwrap:
                        if (content.wijsplitter("option", "panel1").collapsed) {
                            self._toggleWordWrap();
                        }
                        break;
                    case cmd_backcolor:
                        self._saveSelectionForIE();
                        self._createDialog(this.localizeString("backColorDialogTitle", "Set BackColor"), self._getDialogRes_BackColor(), self.initBackColorDialog);
                        break;
                    case cmd_fontcolor:
                        self._saveSelectionForIE();
                        self._createDialog(this.localizeString("foreColorDialogTitle", "Set ForeColor"), self._getDialogRes_ForeColor(), self.initForeColorDialog);
                        break;
                    case cmd_inserttable:
                        self._saveSelectionForIE();
                        self._createDialog(this.localizeString("insertTableDialogTitle", "Insert Table"), self._getDialogRes_Table(), self.initInsertTableDialog);
                        break;
                    case cmd_edittable:
                        if (self._getEditableTable()) {
                            self._createDialog(this.localizeString("editTableDialogTitle", "Edit Table"), self._getDialogRes_Table(), self.initEditTableDialog);
                        }
                        break;
                    case cmd_preview:
                        self._createDialog(this.localizeString("previewDialogPreview", "Preview"), self._getDialogRes_Preview(), self.initPreviewDialog);
                        break;
                    case cmd_cleanup:
                        self._createDialog(this.localizeString("cleanUpDialogTitle", "Clean up source HTML document"), self._getDialogRes_CleanUp(), self.initCleanUpDialog);
                        break;
                    case cmd_media:
                        self._saveSelectionForIE();
                        self._createDialog(this.localizeString("mediaDialogTitle", "Insert media"), self._getDialogRes_Media(), self.initMediaDialog);
                        break;
                    case cmd_specialchar:
                        self._saveSelectionForIE();
                        self._createDialog(this.localizeString("specialCharacterDialogTitle", "Insert special character"), self._getDialogRes_SpecialCharacter(), self.initSpecialCharacterDialog);
                        break;
                    case cmd_find:
                        self._createDialog(this.localizeString("findAndReplaceDialogTitle", "Find and replace"), self._getDialogRes_FindAndReplace(), self.initFindDialog);
                        break;
                    case cmd_inspect:
                        inspectElement = self._getSelectedElement();

                        self._createDialog(this.localizeString("tagInspectorDialogTitle", "Tag Inspector"), self._getDialogRes_TagInspector(), self.initTagInspectorDialog);
                        break;
                    case cmd_template:
                        self._saveSelectionForIE();
                        self._createDialog(this.localizeString("templateDialogApplyTemplate", "Apply Template"), self._getDialogRes_Template(), self.initTemplateDialog);
                        break;
                    case cmd_imagebrowser:
                        self._saveSelectionForIE();
                        self._createDialog(this.localizeString("imageEditorDialogImageBrowser", "Image Browser"), self._getDialogRes_ImageBrowser(), self.initImageBrowserDialog);
                        break;
                    case cmd_link:
                        self._storeSelectionForIE();
                        self._createDialog(this.localizeString("hyperLinkDialogInserthyperLink", "Insert hyperLink"), self._getDialogRes_Link(), self.initHyperLinkDialog);
                        break;
                    case cmd_insertcode:
                        self._saveSelectionForIE();
                        self._createDialog(this.localizeString("insertCodeDialogInsertCode", "Insert Code"), self._getDialogRes_Code(), self.initInsertCodeDialog);
                        break;
                    case cmd_alignleft:
                    case cmd_aligncenter:
                    case cmd_alignright:
                    case cmd_alignfull:
                    case cmd_outdent:
                    case cmd_indent:
                    case cmd_bold:
                    case cmd_italic:
                    case cmd_underline:
                    case cmd_numberedlist:
                    case cmd_bulletedlist:
                    case cmd_strike:
                    case cmd_inserthr:
                    case cmd_selectall:
                        doc.execCommand(cmd, false, null);
                        if (self.options.mode === "bbcode" && !($.browser.msie)) {
                            //convert style="font-weight: bold;
                            //font-style: italic; text-decoration: underline;"
                            //same as ie
                            self._convertStyleToStandTag();
                        }
                        self._addtoUndoBuffer();
                        self._setFocusNotIE();
                        break;
                    case cmd_save:
                        self._saveText();
                        break;
                    case cmd_spelling:
                        self._doSpellCheck();
                        break;
                }

                // If document is not load complete, we can't get the design view codes.
                if (cmd !== cmd_fullscreen && doc && doc.readyState === "complete") {
                    self._onDesignViewBlur(null);
                }
            };

            //added by Ryanwu@20110512.
            wijeditor.prototype._createDialog = function (title, content, callback) {
                var self = this, dialogOpts, $dlg = self.dialog;

                $dlg.html("").undelegate(self.widgetName).undelegate("." + self.widgetName).append(content);
                if (self.subDialog) {
                    self.subDialog.html("").undelegate(self.widgetName).undelegate("." + self.widgetName);
                }

                dialogOpts = {
                    width: "auto",
                    height: "auto",
                    modal: true,
                    title: title,
                    position: { my: "center", at: "center", of: window },
                    resizable: false,
                    captionButtons: {
                        pin: { visible: false },
                        refresh: { visible: false },
                        toggle: { visible: false },
                        minimize: { visible: false },
                        maximize: { visible: false }
                    }
                };
                if (!$dlg.data("wijmo-wijdialog")) {
                    if ($.browser.msie && wijParseInt($.browser.version) === 6) {
                        window.setTimeout(function () {
                            $dlg.wijdialog(dialogOpts);
                        }, 0);
                    } else {
                        $dlg.wijdialog(dialogOpts);
                    }
                } else {
                    $dlg.wijdialog("reset");
                    $dlg.wijdialog("option", {
                        width: "auto",
                        height: "auto",
                        title: title
                    });
                }

                self._adjustDialogLayoutForIE7();

                if (callback) {
                    callback.call(self);
                }

                $dlg.wijdialog("open");
            };

            wijeditor.prototype._adjustDialogLayoutForIE7 = function () {
                var $dlg = this.dialog;

                if ($.browser.msie && (/^7\.[0-9]+/.test($.browser.version) || document.documentMode === 7)) {
                    $dlg.wijdialog('option', 'width', $dlg.parent().width());
                }
            };

            wijeditor.prototype._contextMenuItemClick = function (e, item, sender) {
                var self = this, cmd = item.item.element.attr("_c1buttoncmd");

                if (cmd !== cmd_copy && self.options.readOnly) {
                    return;
                }

                switch (cmd) {
                    case cmd_cut:
                        self._execCut();
                        break;
                    case cmd_copy:
                        self._execCopy();
                        break;
                    case cmd_paste:
                        self.focus();
                        self._execPaste();
                        break;
                }
            };

            wijeditor.prototype._execCut = function () {
                var self = this, doc = self._getDesignViewDocument();

                if (!self._getSelectedContent()) {
                    return;
                }

                if (doc.queryCommandSupported("Cut") && doc.queryCommandEnabled("Cut")) {
                    doc.execCommand("Cut", false, null);
                    self._addtoUndoBuffer();
                } else {
                    self._execCopy(true);
                    self._deleteSelectionContent();
                    self._addtoUndoBuffer();
                }
            };

            wijeditor.prototype._execCopy = function (cut) {
                var self = this, doc = self._getDesignViewDocument();

                if (!self._getSelectedContent()) {
                    return;
                }

                if (doc.queryCommandSupported("Copy") && doc.queryCommandEnabled("Copy")) {
                    doc.execCommand("Copy", false, null);
                    self._addtoUndoBuffer();
                } else {
                    self._copyToClipboard(self._getSelectedContent(), cut);
                }
            };

            wijeditor.prototype._execPaste = function () {
                var self = this, copiedText, doc = self._getDesignViewDocument();

                if (doc.queryCommandSupported("Paste") && doc.queryCommandEnabled("Paste")) {
                    doc.execCommand("Paste", false, null);
                    self._addtoUndoBuffer();
                } else {
                    try  {
                        copiedText = self._copyFromClipboard();

                        if (copiedText && copiedText !== '') {
                            self.insertHTML(copiedText);
                        }
                    } catch (e1) {
                    }
                }
            };

            wijeditor.prototype._getFontSizeCollection = function () {
                return {
                    '10px': cmd_verysmall,
                    '13px': cmd_smaller,
                    '16px': cmd_small,
                    '18px': cmd_medium,
                    '24px': cmd_large,
                    '32px': cmd_larger,
                    '48px': cmd_verylarge,
                    1: cmd_verysmall,
                    2: cmd_smaller,
                    3: cmd_small,
                    4: cmd_medium,
                    5: cmd_large,
                    6: cmd_larger,
                    7: cmd_verylarge
                };
            };

            wijeditor.prototype._updateButtonStates = function (e) {
                var self = this, doc = self._getDesignViewDocument(), rawValue, cmd, buttonStates = {}, stateButtons = [
                    cmd_bold, cmd_italic, cmd_strike,
                    cmd_underline, cmd_subscript, cmd_superscript,
                    cmd_numberedlist, cmd_bulletedlist, cmd_alignleft,
                    cmd_aligncenter, cmd_alignright, cmd_alignfull], $fontSizeSpans, target = e.target, $target = $(target);

                $.each(stateButtons, function (idx, btnKey) {
                    buttonStates[btnKey] = doc.queryCommandState(btnKey);
                });

                self.$ribbon.wijribbon(setButtonsChecked, buttonStates);

                rawValue = self._queryCommandValue(cmd_fontname) || "";

                $.each(self.$ribbon.wijribbon("getDropdownList", cmd_fontname), function (key, value) {
                    if (value.toUpperCase() === rawValue.toUpperCase()) {
                        cmd = key;
                        return false;
                    }
                });

                self.$ribbon.wijribbon(setButtonChecked, cmd, true, cmd_fontname);

                //Add comments by RyanWu@20110923.
                //For implementing the font size customization.
                if (self._isFontSizeCustomized()) {
                    if ($target.is("span")) {
                        cmd = target.style.fontSize;
                    } else {
                        cmd = "";
                    }

                    if (cmd === "") {
                        $fontSizeSpans = $target.parents("span." + css_formatspan);

                        $.each($fontSizeSpans, function (idx, fontSizeSpan) {
                            cmd = fontSizeSpan.style.fontSize;

                            if (cmd && cmd !== "") {
                                return false;
                            }
                        });
                    }

                    if (cmd === "") {
                        cmd = $target.css("font-size");
                    }
                } else {
                    rawValue = self._queryCommandValue(cmd_fontsize) || "";

                    if (rawValue === "") {
                        rawValue = $target.css("font-size");
                    }

                    $.each(self._getFontSizeCollection(), function (key, value) {
                        if (key.toString() === rawValue.toString()) {
                            cmd = value;
                            return false;
                        }
                    });
                }

                //end by RyanWu@20110923.
                self.$ribbon.wijribbon(setButtonChecked, cmd, true, cmd_fontsize);
            };

            wijeditor.prototype._queryCommandValue = function (commandName) {
                var doc = this._getDesignViewDocument(), value;

                try  {
                    if (!doc.queryCommandEnabled(commandName)) {
                        return null;
                    }
                } catch (e1) {
                    return null;
                }

                try  {
                    value = doc.queryCommandValue(commandName);
                    if (commandName === cmd_fontname && value) {
                        value = value.replace(/'/g, '');
                    }
                    return value;
                } catch (e2) {
                }

                return null;
            };

            wijeditor.prototype._escActionAssociated = function () {
                var self = this, win = self._getDesignViewWindow();

                if (win && win.document && win.document.selection !== undefined) {
                    win.document.selection.empty();
                }

                if (win && win.getSelection !== undefined) {
                    win.getSelection().removeAllRanges();
                }

                self._hideAllDropdownsMenus();
            };

            wijeditor.prototype._hideAllDropdownsMenus = function () {
                var self = this;
                if (self.contextMenu) {
                    self.contextMenu[self._contextMenuWidgetName()]("hideAllMenus");
                }

                self.$ribbon.wijribbon("hideDropdown", cmd_fontname).wijribbon("hideDropdown", cmd_fontsize).wijribbon("hideDropdown", cmd_table);
            };

            wijeditor.prototype._onDesignViewKeyDown = function (e) {
                var self = this, ch;

                self._setSaveBtnEnabled();

                try  {
                    if (e.ctrlKey) {
                        ch = String.fromCharCode(e.keyCode).toLowerCase();
                        //				switch (ch) {
                        //					case 'x':
                        //					case 'v':
                        //						self._addtoUndoBuffer();
                        //						break;
                        //				}
                    } else {
                        switch (e.keyCode) {
                            case 27:
                                self._escActionAssociated();
                                break;
                            case 13:
                            case 46:
                                self._addtoUndoBuffer();
                                self._continueSavingInputTextForUndo = false;
                                break;
                            default:
                                self._continueSavingInputTextForUndo = true;
                                break;
                        }
                    }
                } catch (e1) {
                }
            };

            wijeditor.prototype._onDesignViewKeyUp = function (e) {
                var self = this, ch;

                if (e.keyCode === 37 || e.keyCode === 38 || e.keyCode === 39 || e.keyCode === 40 || e.keyCode === 33 || e.keyCode === 34 || e.keyCode === 35 || e.keyCode === 36) {
                    if ($.browser.msie && $.browser.version === "6.0") {
                        if (self._keyTimeoutHandlerIE6) {
                            clearTimeout(self._keyTimeoutHandlerIE6);
                            self._keyTimeoutHandlerIE6 = null;
                        }

                        self._keyTimeoutHandlerIE6 = window.setTimeout(function () {
                            self._updateButtonStates(e);
                        }, 300);
                    } else {
                        self._updateButtonStates(e);
                    }
                }

                if (e.ctrlKey) {
                    ch = String.fromCharCode(e.keyCode).toLowerCase();

                    switch (ch) {
                        case 'y':
                            self._redoAction();
                            e.preventDefault();
                            e.stopPropagation();
                            break;
                        case 'z':
                            self._undoAction();
                            e.preventDefault();
                            e.stopPropagation();
                            break;
                        case 'x':
                        case 'v':
                            self._addtoUndoBuffer();
                            self._continueSavingInputTextForUndo = false;
                            break;
                    }
                }
            };

            wijeditor.prototype._onDesignViewMouseUp = function (e) {
                var self = this, $link;

                if (e.button === 2) {
                    return;
                }

                self._updateButtonStates(e);
                if (self.options.showPathSelector) {
                    self._refreshPathSelector();
                }

                //Note: recover the code by wuhao at 2011/9/14, when dropdown is open
                //click the design view, the dropdown don't close
                self._hideAllDropdownsMenus();
                self.editor.mouseup();

                if ($.browser.msie) {
                    $link = $(e.target).closest("a");

                    if (e.ctrlKey && $link.length > 0) {
                        try  {
                            $link.focus();
                            wijWindow.open($link[0].href, '_blank');
                        } catch (e1) {
                        }
                    }
                }
            };

            wijeditor.prototype._onDesignViewBlur = function (e) {
                var self = this, o = self.options, sourceView;
                sourceView = self._getDesignViewText();

                if (o.mode === "bbcode") {
                    //Note: trim leading/trailing whitespace
                    //because when get the innerhtml from body, there
                    //are some whitespace on leading/trailing
                    sourceView = self._convertHtmlToBBCode($.trim(sourceView));
                }
                self.sourceView.val(sourceView);

                self._onTextChange(e);
                o.text = sourceView;
            };

            wijeditor.prototype._onTextChange = function (e) {
                var self = this;
                if (self._continueSavingInputTextForUndo) {
                    self._addtoUndoBuffer();
                    self._continueSavingInputTextForUndo = false;
                }
                self._trigger('textChanged', e, { text: self.options.text });
            };

            wijeditor.prototype._onSourceViewBlur = function (e) {
                var self = this, designViewText;
                designViewText = self.sourceView.val();
                if (self.options.text !== designViewText) {
                    self._setDesignViewText(designViewText);
                    self._onTextChange(e);
                    self.options.text = designViewText;
                }
            };

            //bbcode implement
            wijeditor.prototype._convertBBCodeToHtml = function (data) {
                if (!data) {
                    return "";
                }

                // Convert < and > to their HTML entities.
                data = data.replace(/</g, '&lt;');
                data = data.replace(/>/g, '&gt;');

                //note: can't asure  there is no problem.
                //data = data.replace(/ /g, '&nbsp;');
                // In IE, recover "&lt;p&gt;""&lt;/p&gt;" to <p></p>.
                if ($.browser.msie) {
                    data = data.replace(/&lt;p&gt;/gim, '<p>');
                    data = data.replace(/&lt;\/p&gt;/gim, '</p>');
                }

                // Convert line breaks to <br>.
                data = data.replace(/(?:\r\n|\n|\r)/g, '<br>');

                //[email]
                data = data.replace(/\[EMAIL\]([\s\S]*?)\[\/EMAIL\]/gim, '<a href="mailto:$1">$1</a>');
                data = data.replace(/\[EMAIL\=([^\]]+)]([\s\S]*?)\[\/EMAIL\]/gim, '<a href="mailto:$1">$2</a>');

                // [url]
                data = data.replace(/\[URL\]([\s\S]*?)\[\/URL\]/gim, '<a href="$1">$1</a>');
                data = data.replace(/\[URL\=([^\]]+)]([\s\S]*?)\[\/URL\]/gim, '<a href="$1">$2</a>');

                // [b]
                data = data.replace(/\[B\]/gim, '<b>');
                data = data.replace(/\[\/B\]/gim, '</b>');

                // [i]
                data = data.replace(/\[I\]/gim, '<i>');
                data = data.replace(/\[\/I\]/gim, '</i>');

                // [s]
                data = data.replace(/\[S\]/gim, '<strike>');
                data = data.replace(/\[\/S\]/gim, '</strike>');

                // [u]
                data = data.replace(/\[U\]/gim, '<u>');
                data = data.replace(/\[\/U\]/gim, '</u>');

                // [IMG]  [^<>]*
                data = data.replace(/\[IMG height=(.*?) width=(.*?)](.+?)\[\/IMG\]/gim, '<img height="$1" width = "$2" src="$3"/>');

                //[BLOCK]
                data = data.replace(/\[BLOCK\]/gim, '<blockquote>');
                data = data.replace(/\[\/BLOCK\]/gim, '</blockquote>');

                // Ordered List [OL]
                data = data.replace(/\[LIST\=1\]\[\*\]([\s\S]*?)\[\/LIST\]/gim, '<ol><li>$1</li></ol>');

                // Unordered List [UL]
                data = data.replace(/\[LIST\]\[\*\]([\s\S]*?)\[\/LIST\]/gim, '<ul><li>$1</li></ul>');

                //LI
                data = data.replace(/\[\*\]/gim, '</li><li>');

                // [SIZE]
                //			data = data.replace(/\[size=([^\]]*?)\]/gi,
                //					"<span style=\"font-size: $1;\">");
                //			data = data.replace(/\[\/size\]/gim, '</span>');
                data = data.replace(/\[size=([^\]]*?)\]/gi, "<font size=\"$1\">");
                data = data.replace(/\[\/size\]/gim, '</font>');

                // [COLOR]
                data = data.replace(/\[color=([^\]]*?)\]/gi, "<font color=\"$1\">");
                data = data.replace(/\[\/color\]/gim, '</font>');

                return data;
            };

            wijeditor.prototype._replaceComplexHtml = function (data) {
                var imgs, fonts, replaceHtml, i, root = $("<div/>").html(data);

                //img
                imgs = $("img", root);
                $.each(imgs, function () {
                    replaceHtml = '[IMG height=' + $(this).height() + ' width=' + $(this).width() + ']' + $(this).attr("src").toString() + '[/IMG]';
                    $(this).replaceWith(replaceHtml);
                });

                //font
                fonts = $("font", root);

                for (i = fonts.length - 1; i >= 0; i--) {
                    if ($(fonts[i]).attr("color") && $($(fonts[i])).attr("size")) {
                        replaceHtml = '[Color=' + $($(fonts[i])).attr("color") + ']' + '[Size=' + $($(fonts[i])).attr("size") + ']' + $($(fonts[i])).html() + '[/Size][/Color]';
                    } else if ($($(fonts[i])).attr("color") && !$($(fonts[i])).attr("size")) {
                        replaceHtml = '[Color=' + $($(fonts[i])).attr("color") + '] ' + $($(fonts[i])).html() + '[/Color]';
                    } else if ($($(fonts[i])).attr("size") && !$($(fonts[i])).attr("color")) {
                        replaceHtml = '[Size=' + $($(fonts[i])).attr("size") + ']' + $($(fonts[i])).html() + '[/Size]';
                    }
                    $($(fonts[i])).replaceWith(replaceHtml);
                }

                return root.html();
            };

            wijeditor.prototype._convertHtmlToBBCode = function (data) {
                var self = this;

                if (data === "") {
                    return;
                }
                data = self._replaceComplexHtml(data);

                // Convert <br> to line breaks.
                data = data.replace(/<br(?=[ \/>]).*?>/gim, '\r\n');

                // In IE, convert <p></p> to "&lt;p&gt;""&lt;/p&gt;" to prevent from being deleted.
                if ($.browser.msie) {
                    data = data.replace(/<p>/gim, '&lt;p&gt;');
                    data = data.replace(/<\/p>/gim, '&lt;/p&gt;');
                }

                // [URL]
                data = data.replace(/<a .*?href=(["'])(.+?)\1.*?>(.+?)<\/a>/gi, '[URL=$2]$3[/URL]');

                // [Email]
                data = data.replace(/<a .*?href=(["'])mailto:(.+?)\1.*?>(.+?)<\/a>/gi, '[EMAIL=$2]$3[/EMAIL]');

                // [B]
                data = data.replace(/<(?:b|strong)>/gim, '[B]');
                data = data.replace(/<\/(?:b|strong)>/gim, '[/B]');

                // [I]
                data = data.replace(/<(?:i|em)>/gim, '[I]');
                data = data.replace(/<\/(?:i|em)>/gim, '[/I]');

                // [strike]
                data = data.replace(/<(?:strike|s)>/gim, '[S]');
                data = data.replace(/<\/(?:strike|s)>/gim, '[/S]');

                // [U]
                data = data.replace(/<u>/gim, '[U]');
                data = data.replace(/<\/u>/gim, '[/U]');

                // [IMG]
                //data = data.replace(/<img\s{1}.*?src\s{0,1}=\s{0,1}["'](.+?)["'].*/gim,
                //		'[IMG="$1"][/IMG]');
                //data = data.replace(/<img\s{1}([^>]*)src\s{0,1}=\s{0,1}["'](.+?)["']([^>]*)>/gim,
                //	'[IMG $1$3]$2[/IMG]');
                // [BLOCK]
                data = data.replace(/<blockquote.*?\>/gim, '[BLOCK]');
                data = data.replace(/\s{0,}<\/blockquote>/gim, '[/BLOCK]');

                // Ordered List [OL]
                data = data.replace(/(?:\r\n|\r|\n){0,1}<(?:ol)>[\s]*/gim, '[LIST=1]');
                data = data.replace(/<\/(?:ol)>/gim, '[/LIST]');

                // Unordered List [UL]
                //\r\n<ul> must convert to ul
                data = data.replace(/(?:\r\n|\r|\n){0,1}\<(?:ul)>[\s]*/gim, '[LIST]');
                data = data.replace(/<\/(?:ul)>/gim, '[/LIST]');

                // [LI]
                data = data.replace(/\s{0,}<li\s{0,1}.*?>([\s\S]*?)\n{0,}\s{0,}<\/li>/gim, '[*]$1');

                //space convert
                data = data.replace(/&nbsp;/gi, " ");

                // Remove remaining tags.
                data = data.replace(/(<[^>]+>)/gm, '');

                return data;
            };

            wijeditor.prototype._convertFontStyleToStandTag = function () {
                var self = this, doc = self._getDesignViewDocument(), $designviewBody = $(doc.body), currentNode, bbcodeMark, colorTag = $("[style*='color: ']", $designviewBody);

                if (colorTag.length !== 0) {
                    currentNode = colorTag;
                    bbcodeMark = "<font color='" + self._getWebColorFromRgb(colorTag.css("color")) + "'></font>";
                }

                if (currentNode) {
                    $.each(currentNode, function (i) {
                        //there is no attribute in span,
                        //like <span style="color:#123">xxx</b>
                        //must replace span with new tag
                        //like <b>XXX</b>
                        if ($(this).is("span")) {
                            $(this).replaceWith($(bbcodeMark).html($(this).html()));
                        } else if ($(this).is("font") && $(this).attr("size")) {
                            //note: there are other attribute in span
                            //like <span style="font-size:15px, color=#123">XXX</b>
                            // so insert new tag in span content
                            //like <span style="font-size:15px><b>XXX</b></span>
                            //maybe there is no need here
                            //$(this).css("color", undefined)
                            //$(this).removeAttr("style")
                            //    .html($(bbcodeMark).html($(this).html()));
                            $(this).removeAttr("style").html($(bbcodeMark).html());
                        }
                    });
                }
            };

            wijeditor.prototype._convertStyleToStandTag = function () {
                var self = this, doc = self._getDesignViewDocument(), $designviewBody = $(doc.body), currentNode, bbcodeMark, currentAttr, boldTag = $("[style*='font-weight: bold;']", $designviewBody), italicTag = $("[style*='font-style: italic;']", $designviewBody), strikeTag = $("[style*='text-decoration: line-through;']", $designviewBody), underlineTag = $("[style*='text-decoration: underline;']", $designviewBody);

                if (boldTag.length !== 0) {
                    currentNode = boldTag;
                    bbcodeMark = "<b></b>";
                    currentAttr = "font-weight";
                } else if (italicTag.length !== 0) {
                    currentNode = italicTag;
                    bbcodeMark = "<i></i>";
                    currentAttr = "font-style";
                } else if (strikeTag.length !== 0) {
                    currentNode = strikeTag;
                    bbcodeMark = "<strike></strikes>";
                    currentAttr = "text-decoration";
                } else if (underlineTag.length !== 0) {
                    currentNode = underlineTag;
                    bbcodeMark = "<u></u>";
                    currentAttr = "text-decoration";
                }

                if (currentNode) {
                    $.each(currentNode, function (i) {
                        //there is no attribute in span,
                        //like <span style="color:#123">xxx</b>
                        //must replace span with new tag
                        //like <b>XXX</b>
                        if ($(this).is("span") && this.style.fontSize === "") {
                            $(this).replaceWith($(bbcodeMark).html($(this).html()));
                        } else {
                            //note: there are other attribute in span
                            //like <span style="font-size:15px, color=#123">XXX</b>
                            // so insert new tag in span content
                            //like <span style="font-size:15px><b>XXX</b></span>
                            //maybe there is no need here
                            $(this).removeAttr("style").html($(bbcodeMark).html());
                        }
                    });
                }
            };

            wijeditor.prototype._getWebColorFromRgb = function (rgbColor) {
                var self = this, rgbColorItems;

                if (rgbColor.indexOf('rgb(') === 0) {
                    rgbColorItems = rgbColor.substring(4, rgbColor.length - 1).split(',');
                    rgbColor = self._convertToWebColor(wijParseInt(rgbColorItems[0]), wijParseInt(rgbColorItems[1]), wijParseInt(rgbColorItems[2]));
                }
                return rgbColor;
            };

            //end bbcode
            //common for dialogs.
            wijeditor.prototype._updateList = function (list, $select) {
                var name;

                $("option", $select).remove();

                for (name in list) {
                    if (list[name]) {
                        $select.append("<option>" + name + "</option>");
                    }
                }
            };

            wijeditor.prototype._triggerEvent = function (evName, arg) {
                var self = this, ev = self.options[evName];

                if (ev && typeof (ev) === "function") {
                    return ev.call(self, arg);
                }

                return ev;
            };

            wijeditor.prototype._closeDialog = function () {
                this.dialog.wijdialog("close");
                this.rangeSelection = null;
                this.focus();
            };

            //end of common dialogs.
            //begin to handle the template dialog.
            wijeditor.prototype._onTemplateList = function (arg) {
                return this._triggerEvent("templateList", arg);
            };

            /** @ignore */
            wijeditor.prototype.updateTemplateList = function (templateList, select) {
                var self = this, $select = select || $("select", self.dialog);

                self._updateList(templateList, $select);
                self._templateList = templateList;
            };

            /** @ignore */
            wijeditor.prototype.initTemplateDialog = function () {
                var self = this, $dlg = self.dialog, tplList = $("select", $dlg), templateList = self._onTemplateList();

                $dlg.delegate("select", "change." + self.widgetName, function () {
                    self.templateListOnChanged();
                }).delegate("." + css_tpl_delete, "click." + self.widgetName, function () {
                    self.deleteTemplate();
                }).delegate("." + css_tpl_save, "click." + self.widgetName, function () {
                    self.saveTemplate();
                }).delegate(selector_dlg_ok, "click." + self.widgetName, function () {
                    self.applyTemplate();
                }).delegate(selector_dlg_cancel, "click." + self.widgetName, function () {
                    self._closeDialog();
                });

                if (!templateList) {
                    templateList = self._templateList;

                    if (!templateList) {
                        return;
                    }
                }

                self.updateTemplateList(templateList, tplList);
            };

            /** @ignore */
            wijeditor.prototype.templateListOnChanged = function () {
                var self = this, $dlg = self.dialog, selectedTpl = $("select", $dlg).val(), preview = $('iframe', $dlg), templateList = self._templateList, template;

                if (!templateList) {
                    return;
                }

                template = templateList[selectedTpl];

                if (template.src) {
                    preview.attr("src", template.src + '?d=' + new Date().getMilliseconds().toString());
                }

                if (template.text && preview.length > 0) {
                    preview[0].contentWindow.document.write(template.text);
                }

                if (selectedTpl) {
                    $("." + css_tpl_nameinfo, $dlg).html(selectedTpl);
                    $("." + css_tpl_namefield, $dlg).val(selectedTpl);
                }

                if (template.desc) {
                    $("." + css_tpl_desinfo, $dlg).html(template.desc);
                    $("." + css_tpl_desfield, $dlg).val(template.desc);
                }
            };

            wijeditor.prototype._onSaveTemplate = function (arg) {
                this._triggerEvent("saveTemplate", arg);
            };

            /** @ignore */
            wijeditor.prototype.saveTemplate = function () {
                var self = this, $dlg = self.dialog, name = $("." + css_tpl_namefield, $dlg).val(), desc = $("." + css_tpl_desfield, $dlg).val(), templateList = self._templateList, text = this._getDesignViewText();

                if ($.trim(name) === '') {
                    wijAlert(this.localizeString("errorMessageTemplateNameError", "Please input a template name!"));
                    return;
                }

                if (!templateList) {
                    self._templateList = [];
                    templateList = self._templateList;
                }

                if (!templateList[name]) {
                    $("select", $dlg).append("<option>" + name + "</option>");
                }

                templateList[name] = { desc: desc, text: text };
                self._onSaveTemplate({ name: name, desc: desc, text: text });
            };

            wijeditor.prototype._onDeleteTemplate = function (arg) {
                this._triggerEvent("deleteTemplate", arg);
            };

            /** @ignore */
            wijeditor.prototype.deleteTemplate = function () {
                var self = this, $dlg = self.dialog, tplList = $("select", $dlg), selectedTpl = tplList.val(), templateList = self._templateList;

                if ($.trim(selectedTpl) === '') {
                    wijAlert(this.localizeString("errorMessageTemplateFileError", "Please select a template file."));
                    return;
                }

                $("option:selected", tplList).remove();
                $('iframe', $dlg).attr("src", "about:blank");
                $("." + css_tpl_nameinfo, $dlg).empty();
                $("." + css_tpl_namefield, $dlg).val("");
                $("." + css_tpl_desinfo, $dlg).empty();
                $("." + css_tpl_desfield, $dlg).val("");

                delete templateList[selectedTpl];
                self._onDeleteTemplate(selectedTpl);
            };

            /** @ignore */
            wijeditor.prototype.applyTemplate = function () {
                var self = this, $dlg = self.dialog, tplList = $("select", $dlg), selectedTpl = tplList.val(), preview = $('iframe', $dlg)[0], name = $("." + css_tpl_namefield, $dlg).val(), html = preview.contentWindow.document.body.innerHTML;

                if ($.trim(name) === '' || $.trim(selectedTpl) === '') {
                    wijAlert(this.localizeString("errorMessageValidTemplateFileError", "Please select a valid template file."));
                    return;
                }

                self._setDesignViewText(html);
                self._addtoUndoBuffer();
                self._setSaveBtnEnabled();

                self._closeDialog();
            };

            //begin to handle the image dialog.
            wijeditor.prototype._onImageList = function () {
                var self = this, imageList = self.options.imageList;

                if (imageList && typeof (imageList) === "function") {
                    return imageList.call(self);
                }

                return imageList;
            };

            /** @ignore */
            wijeditor.prototype.updateImageList = function (imgList, select) {
                var self = this, $dlg = self.dialog, $select = select || $("select", $dlg), $imgfields = $("." + css_imgdlg_field, $dlg);

                self._updateList(imgList, $select);
                self._imgList = imgList;

                if (!imgList) {
                    $imgfields.addClass(css_imgdlg_hideimglist);
                    return;
                }

                $imgfields.removeClass(css_imgdlg_hideimglist);
            };

            /** @ignore */
            wijeditor.prototype.initImageBrowserDialog = function () {
                var self = this, $dlg = self.dialog, imgList = self._onImageList();

                $("img", $dlg).hide();

                $dlg.delegate("select", "change." + self.widgetName, function () {
                    self.imageListOnChanged();
                }).delegate(selector_dlg_ok, "click." + self.widgetName, function (e) {
                    self.submitInsertImageDialog();
                    self._onDesignViewBlur(e);
                }).delegate(selector_dlg_cancel, "click." + self.widgetName, function () {
                    self._closeDialog();
                });

                $("." + css_imgdlg_url + " input", $dlg).bind("change." + self.widgetName, function () {
                    self.imageUrlChanged(this);
                });

                if (!imgList) {
                    imgList = self._imgList;

                    if (!imgList) {
                        $("." + css_imgdlg_field, $dlg).addClass(css_imgdlg_hideimglist);
                        return;
                    }
                }

                self.updateImageList(imgList, $("select", $dlg));
            };

            /** @ignore */
            wijeditor.prototype.imageUrlChanged = function (element) {
                var self = this, $dlg = self.dialog;

                $('img', this.dialog).attr("src", $(element).val() + "?" + new Date().getTime()).show().bind("load", function () {
                    $("." + css_imgdlg_width + " input", $dlg).val($('img', $dlg).width().toString());
                    $("." + css_imgdlg_height + " input", $dlg).val($('img', $dlg).height().toString());
                });
            };

            /** @ignore */
            wijeditor.prototype.imageListOnChanged = function () {
                var self = this, $dlg = self.dialog, selectedImg = $('select', $dlg).val(), imgList = self._imgList, img;

                if (!imgList) {
                    return;
                }

                img = imgList[selectedImg];

                $('img', $dlg).prop("src", img).show();
                $("." + css_imgdlg_url + " input", $dlg).prop("value", img);
                wijWindow.setTimeout(function () {
                    $("." + css_imgdlg_width + " input", $dlg).val($('img', $dlg).width().toString());
                    $("." + css_imgdlg_height + " input", $dlg).val($('img', $dlg).height().toString());
                }, 200);
            };

            /** @ignore */
            wijeditor.prototype.submitInsertImageDialog = function () {
                var self = this, imageHtml, $dlg = self.dialog, imgUrl = $("." + css_imgdlg_url + " input", $dlg).val(), alt = $("." + css_imgdlg_alt + " input", $dlg).val(), width = $("." + css_imgdlg_width + " input", $dlg).val(), height = $("." + css_imgdlg_height + " input", $dlg).val(), css = $("." + css_imgdlg_css + " input", $dlg).val();

                if ($.trim(imgUrl) === "") {
                    wijAlert(this.localizeString("errorMessageSelectImageError", "Please select a image."));
                    return;
                }

                if (!self._isNumeric(width)) {
                    wijAlert(this.localizeString("errorMessageImageWidthError", "Please input a number for 'Image width' textbox."));
                    return;
                }

                if (!self._isNumeric(height)) {
                    wijAlert(this.localizeString("errorMessageImageHeightError", "Please input a number for 'Image height' textbox."));
                    return;
                }

                //Fix Insert Image (#245498)
                if (self._isIE11) {
                    setTimeout(function () {
                        self.focus();
                    }, 0);
                } else {
                    self.focus();
                }

                if ($.browser.msie) {
                    //for 35039 issue
                    imageHtml = '<img src="' + imgUrl + '" alt="' + alt + '" style="width:' + width + 'px;height:' + height + 'px';
                    if (self.options.mode !== "bbcode" && css !== null && css !== undefined && css.length > 0) {
                        imageHtml += ';' + css;
                    }
                } else {
                    imageHtml = '<img src="' + imgUrl + '" alt="' + alt + '" width="' + width + '" height="' + height;
                    if (self.options.mode !== "bbcode") {
                        imageHtml += '" style="' + css;
                    }
                }
                imageHtml += '"/>';
                self.insertHTML(imageHtml);
                self._closeDialog();
            };

            //begin to handle the link dialog.
            /** @ignore */
            wijeditor.prototype.initHyperLinkDialog = function () {
                var self = this, $dlg = self.dialog, address = self.getLinkHrefField(), $imageContainer = $("." + css_linkdlg_imagecontainer, $dlg), iconTypeIsImg, linkInnerHtml, $img, $iconTypeText = $("." + css_linkdlg_text + " input", $dlg), $address = $("." + css_linkdlg_address + " input", $dlg);

                $dlg.one("wijdialogclose", function () {
                    self._restoreSelectionForIE();
                });

                $dlg.delegate(selector_dlg_ok, "click." + self.widgetName, function (e) {
                    self.submitHyperLinkDialog();
                    self._onDesignViewBlur(e);
                }).delegate(selector_dlg_cancel, "click." + self.widgetName, function () {
                    self._closeDialog();
                }).delegate("." + css_linkdlg_anchor, "change." + self.widgetName, function () {
                    self.anchorListOnChanged(this);
                }).delegate("." + css_linkdlg_linktype + ">div", "click." + self.widgetName, function () {
                    self.radioListOnChanged();
                }).delegate("." + css_linkdlg_linkicontype + ">div", "click." + self.widgetName, function () {
                    self.linkIconTypeOnChanged();
                }).delegate("." + css_linkdlg_url + " input", "change." + self.widgetName, function () {
                    self.tempImg = $('<img src="' + $("." + css_linkdlg_url + " input", $dlg).val() + '">').appendTo("body");
                    wijWindow.setTimeout(function () {
                        $("." + css_linkdlg_width + " input", $dlg).val(self.tempImg.width().toString());
                        $("." + css_linkdlg_height + " input", $dlg).val(self.tempImg.height().toString());
                        self.tempImg.remove();
                        self.tempImg = undefined;
                    }, 200);
                });

                try  {
                    $address.val(address);
                    linkInnerHtml = self._getLinkInnerHTML();
                } catch (e) {
                }

                if (linkInnerHtml && linkInnerHtml.substring(0, 3) === '<img') {
                    iconTypeIsImg = true;
                    $img = $(linkInnerHtml);
                } else {
                    iconTypeIsImg = false;
                }

                if (!iconTypeIsImg) {
                    $iconTypeText.show();
                    $imageContainer.hide();
                    $iconTypeText.val(linkInnerHtml);
                } else {
                    $imageContainer.show();
                    $iconTypeText.hide();
                    $("." + css_linkdlg_url + " input", $dlg).val($img.attr("src"));
                    $("." + css_linkdlg_width + " input", $dlg).val($img.attr("width"));
                    $("." + css_linkdlg_height + " input", $dlg).val($img.attr("heigth"));
                }

                $("." + css_linkdlg_css + " input", $dlg).val(self._getLinkCssField());
                $("." + css_linkdlg_target + " select", $dlg).val(self._getLinkTarget());

                $("#radAnchor", $dlg).prop("checked", true);
                $("#radLinkTypeIsText", $dlg).prop("checked", true);
                if (address.length > 6) {
                    if (address.substring(0, 4) === 'http') {
                        $("#radUrl", $dlg).prop("checked", true);
                    } else if (address.substring(0, 6) === 'mailto') {
                        $("#radMail", $dlg).prop("checked", true);
                    } else {
                        if (address.substring(0, 1) === '#') {
                            $("#radAnchor", $dlg).prop("checked", true);
                        } else {
                            $("#radFile", $dlg).prop("checked", true);
                        }
                    }
                }
                $address.focus();
                $img = undefined;
            };

            wijeditor.prototype._getLinkInnerHTML = function () {
                var self = this, inspElem, tmpElem;

                self.focus();
                inspElem = self._getInspectElement();
                self._hyperlinkTextStyle = "";

                try  {
                    tmpElem = self._getHyperLinkElement(inspElem);
                    if (tmpElem && tmpElem.tagName === 'A') {
                        if (inspElem.innerHTML !== tmpElem.innerHTML) {
                            self._hyperlinkTextStyle = tmpElem.innerHTML.replace(inspElem.innerHTML, "{0}");
                        }
                        return $(inspElem).text();
                    }
                } catch (error) {
                }

                return '';
            };

            /** @ignore */
            wijeditor.prototype.getLinkHrefField = function () {
                var self = this, inspElem;

                self.focus();
                inspElem = self._getInspectElement();

                try  {
                    inspElem = self._getHyperLinkElement(inspElem);
                    if (inspElem && inspElem.tagName === 'A') {
                        return self.fixAbsoluteUrlsIfNeeded(inspElem.href || '');
                    }
                } catch (error) {
                }

                return '';
            };

            wijeditor.prototype._getLinkTarget = function () {
                var self = this, inspElem;

                self.focus();
                inspElem = self._getInspectElement();

                try  {
                    inspElem = self._getHyperLinkElement(inspElem);
                    if (inspElem && inspElem.tagName === 'A') {
                        return inspElem.target || '';
                    }
                } catch (error) {
                }

                return '';
            };

            wijeditor.prototype._getLinkCssField = function () {
                var self = this, inspElem;

                self.focus();
                inspElem = self._getInspectElement();

                try  {
                    inspElem = self._getHyperLinkElement(inspElem);
                    if (inspElem && inspElem.tagName === 'A') {
                        return inspElem.style.cssText || '';
                    }
                } catch (error) {
                }

                return '';
            };

            /** @ignore */
            wijeditor.prototype.submitHyperLinkDialog = function () {
                var self = this, $dlg = self.dialog, $radUrl = $("#radUrl", $dlg), $radAnchor = $("#radAnchor", $dlg), $radMail = $("#radMail", $dlg), $address = $("." + css_linkdlg_address + " input", $dlg), $text = $("." + css_linkdlg_text + " input", $dlg), $css = $("." + css_linkdlg_css + " input", $dlg), $target = $("." + css_linkdlg_target + " select", $dlg), address = $address.val(), text = $text.val(), target = $target.val(), $radImage = $("#radLinkTypeIsImage", $dlg), imageChecked = $radImage.prop("checked"), imageUrl = $("." + css_linkdlg_url + " input", $dlg).val(), imageWidth = $("." + css_linkdlg_width + " input", $dlg).val(), imageHeight = $("." + css_linkdlg_height + " input", $dlg).val(), css = $css.val();

                if (address === '') {
                    wijAlert(this.localizeString("errorMessageAddressError", "Please input address!"));
                    return;
                }

                if (text === '' && !imageChecked) {
                    wijAlert(this.localizeString("errorMessageDisplayTextError", "Please input display text!"));
                    return;
                }

                if (imageUrl === '' && imageChecked) {
                    wijAlert(this.localizeString("errorMessageHyperLinkImageUrlError", "Please input image url!"));
                    return;
                }

                if (!self._isNumeric(imageWidth) && imageChecked) {
                    wijAlert(this.localizeString("errorMessageHyperLinkImageWidthError", "Please input correct image width!"));
                    return;
                }

                if (!self._isNumeric(imageHeight) && imageChecked) {
                    wijAlert(this.localizeString("errorMessageHyperLinkImageHeightError", "Please input correct image height!"));
                    return;
                }

                if ($radUrl.prop("checked") && !self._isUrl(address)) {
                    wijAlert(this.localizeString("errorMessageHyperLinkUrl", "Please input correct url!"));
                    return;
                }

                if ($radAnchor.prop("checked") && !self._isAnchor(address)) {
                    wijAlert(this.localizeString("errorMessageHyperLinkAnchor", "Please input correct anchor!"));
                    return;
                }

                if ($radMail.prop("checked") && !self._isEmail(address)) {
                    wijAlert(this.localizeString("errorMessageHyperLinkEmail", "Please input correct email!"));
                    return;
                }

                if (imageChecked) {
                    text = '<img src="' + imageUrl + '" width="' + imageWidth + '" height="' + imageHeight;
                    text += '"/>';
                }

                self._closeDialog();
                self._editLink(text, address, css, target);
            };

            wijeditor.prototype._editLink = function (text, href, css, target) {
                var self = this, html = '', inspElem;
                self.focus();
                inspElem = self._getInspectElement();

                try  {
                    inspElem = self._getHyperLinkElement(inspElem);
                    if (inspElem && inspElem.tagName === 'A') {
                        inspElem.innerHTML = self._hyperlinkTextStyle && self._hyperlinkTextStyle !== "" ? self._hyperlinkTextStyle.replace("{0}", text) : text;
                        inspElem.href = href;
                        inspElem.target = target;

                        if (css !== inspElem.style.cssText) {
                            inspElem.style.cssText = css;
                        }

                        self._addtoUndoBuffer();
                        self._setSaveBtnEnabled();

                        return;
                    }
                } catch (error) {
                }

                html = '<a href="' + href + '" target="' + target + '"';

                if (css !== '') {
                    html += ' style="' + css + '"';
                }

                html += '>' + text + '</a>';
                self.insertHTML(html);
            };

            /** @ignore */
            wijeditor.prototype.anchorListOnChanged = function (list) {
                var self = this, $dlg = self.dialog, val = $(list).val();

                if (val !== '') {
                    $("." + css_linkdlg_address + " input", $dlg).val(val);
                    $("#radAnchor", $dlg).attr("checked", "checked");
                }
            };

            /** @ignore */
            wijeditor.prototype.radioListOnChanged = function () {
                var self = this, $dlg = self.dialog, $anchor = $("." + css_linkdlg_anchor, $dlg), $address = $("." + css_linkdlg_address + " input", $dlg);

                $address.val("");

                if ($("#radUrl", $dlg).is(":checked")) {
                    $anchor.hide();
                } else if ($("#radAnchor", $dlg).is(":checked")) {
                    $anchor.show();
                } else if ($("#radMail", $dlg).is(":checked")) {
                    $anchor.hide();
                    $address.val(this.localizeString("insertHyperLinkMailTo", "mailto:"));
                } else if ($("#radFile", $dlg).is(":checked")) {
                    $anchor.hide();
                }
            };

            /** @ignore */
            wijeditor.prototype.linkIconTypeOnChanged = function () {
                var self = this, $dlg = self.dialog, $imageContainer = $("." + css_linkdlg_imagecontainer, $dlg), $text = $("." + css_linkdlg_text, $dlg);

                if ($("#radLinkTypeIsText", $dlg).is(":checked")) {
                    $text.show();
                    $imageContainer.hide();
                } else if ($("#radLinkTypeIsImage", $dlg).is(":checked")) {
                    $text.hide();
                    $imageContainer.show();
                }
            };

            //end of link dialog.
            //beging to handle the insert code dialog
            wijeditor.prototype._getDialogRes_Code = function () {
                var self = this, dialog = wijribbonDataRender.createDiv(css_linkdlg);

                dialog.add(wijribbonDataRender.createElement("div", this.localizeString("insertCodeDialogEnterSourceCode", "Enter source code:"), {
                    "class": css_codedlg_sourcelabel
                }));
                dialog.add(wijribbonDataRender.createElement("textarea", "", {
                    "class": css_codedlg_source
                }));

                dialog.add(self._createSeparator());
                dialog.add(self._createOKCancelButtons());

                return dialog.render();
            };

            /** @ignore */
            wijeditor.prototype.initInsertCodeDialog = function () {
                var self = this, $dlg = self.dialog;
                $dlg.delegate(selector_dlg_ok, "click." + self.widgetName, function (e) {
                    self.submitCodeDialog();
                    self._onDesignViewBlur(e);
                }).delegate(selector_dlg_cancel, "click." + self.widgetName, function () {
                    self._closeDialog();
                });
            };

            /** @ignore */
            wijeditor.prototype.submitCodeDialog = function () {
                var self = this, $dlg = self.dialog, $source = $("." + css_codedlg_source, $dlg), html = $source.val();

                if (html === '') {
                    return;
                }
                html = html.replace(/</g, '&lt;');
                html = html.replace(/>/g, '&gt;');
                html = '<pre>' + html + '</pre>';
                self._setIESelection();
                self.insertHTML(html);
                self._closeDialog();
            };

            //end of insert code dialog
            //begin to handle the tagInspector dialog.
            /** @ignore */
            wijeditor.prototype.initTagInspectorDialog = function () {
                var self = this, $dlg = self.dialog, $innerHTML = $("." + css_taginsdlg_innerhtml);

                $dlg.delegate(selector_dlg_ok, "click." + self.widgetName, function (e) {
                    self.submitTagInspectorDialog();
                    self._onDesignViewBlur(e);
                }).delegate(selector_dlg_cancel, "click." + self.widgetName, function () {
                    self._closeDialog();
                }).delegate("#displayNoEmpty", "click." + self.widgetName, function () {
                    self.tagInspectorDialogSwitchAttList(this);
                });

                self._laySelectedElementAttributes($("." + css_taginsdlg_attriblist, $dlg), $("." + css_taginsdlg_tagtext, $dlg));

                $("." + css_taginsdlg_css + " input", $dlg).val(self._getSelectedElementStyle());

                if (self._selectedElementCanHaveChildren()) {
                    $innerHTML.show();
                    $("textarea", $innerHTML).val(self._getSelectedElementInnerHTML());
                } else {
                    $innerHTML.hide();
                }
            };

            /** @ignore */
            wijeditor.prototype.submitTagInspectorDialog = function () {
                var self = this, $dlg = self.dialog, el = self._getInspectElement(), $attriblist = $("." + css_taginsdlg_attriblist, $dlg), cssText = $("." + css_taginsdlg_css + " input").val(), innerHTML = $("." + css_taginsdlg_innerhtml + " textarea").val();

                try  {
                    $.each($("input:checkbox", $attriblist), function (idx, chk) {
                        var attrName, attrValue, $chk = $(chk);

                        if ($chk.is(":checked")) {
                            attrName = $chk.siblings("span").text();
                            attrName = attrName.substring(0, attrName.length - 1);
                            attrValue = $chk.siblings("input:text").val();
                            $(el).attr(attrName, attrValue);
                        }
                    });

                    if ($.trim(cssText) !== '') {
                        el.style.cssText = cssText;
                    }

                    if (self._selectedElementCanHaveChildren()) {
                        $(el).html(innerHTML);
                    }
                } catch (error) {
                }

                self._closeDialog();
                self._addtoUndoBuffer();
                self._setSaveBtnEnabled();
            };

            /** @ignore */
            wijeditor.prototype.tagInspectorDialogSwitchAttList = function (element) {
                var $attriblis = $("." + css_taginsdlg_attriblist, this.dialog), showAll = !element.checked;

                $.each($("input:text", $attriblis), function (idx, text) {
                    if ($(text).val() === "") {
                        $(text).parent("li")[showAll ? "show" : "hide"]();
                    }
                });
            };

            wijeditor.prototype._laySelectedElementAttributes = function ($attriblist, $tag) {
                var self = this, el = self._getInspectElement(), dic, tag, attrs, localSaveString = this.localizeString("tagInspectorDialogSave", "Save"), html = "";

                if (!el) {
                    return;
                }

                $tag.html(el.tagName);

                dic = self._getDictionaryDeclare();
                tag = el.tagName.toLowerCase();
                attrs = dic[tag];

                switch (tag) {
                    case 'ul':
                    case 'u':
                    case 'textarea':
                    case 'tbody':
                    case 'tr':
                    case 'th':
                    case 'td':
                    case 'table':
                    case 'select':
                    case 'strong':
                    case 'span':
                    case 'p':
                    case 'option':
                    case 'ol':
                    case 'li':
                    case 'label':
                    case 'input':
                    case 'img':
                    case 'i':
                    case 'hr':
                    case 'form':
                    case 'font':
                    case 'em':
                    case 'div':
                    case 'code':
                    case 'button':
                    case 'body':
                    case 'b':
                    case 'a':
                        html += "<ul class='ui-helper-reset'>";

                        $.each(attrs, function (idx, attr) {
                            var val = el.getAttribute(attr) || "";

                            html += "<li><span class='" + css_dlg_text + "'>";
                            html += attr + ":</span>";
                            html += "<input type='text' aria-label='text' value='" + val + "'/>";
                            html += "<input type='checkbox' id='save" + idx + "'/>";
                            html += "<label for='save" + idx + "'>" + localSaveString + "</label></li>";
                        });
                        break;
                }

                $attriblist.html(html);
            };

            wijeditor.prototype._getSelectedElementStyle = function () {
                var inspElem = this._getInspectElement();

                if (inspElem && inspElem.style) {
                    return inspElem.style.cssText || '';
                } else {
                    return '';
                }
            };

            wijeditor.prototype._getSelectedElementInnerHTML = function () {
                var inspElem = this._getInspectElement();

                if (inspElem) {
                    return inspElem.innerHTML;
                } else {
                    return '';
                }
            };

            wijeditor.prototype._selectedElementCanHaveChildren = function () {
                return !$(this._getInspectElement()).is("input,hr,br,img");
            };

            //end of tag inspector dialog.
            //begin to handle the color dialog.
            /** @ignore */
            wijeditor.prototype.initBackColorDialog = function () {
                this._initColorDialog("BackColor");
            };

            /** @ignore */
            wijeditor.prototype.initForeColorDialog = function () {
                this._initColorDialog("ForeColor");
            };

            wijeditor.prototype._initColorDialog = function (colorCommand) {
                var self = this, $dlg = self.dialog, doc = self._getDesignViewDocument(), color = doc.queryCommandValue(colorCommand), iColor, items, sColor;

                $dlg.delegate(selector_dlg_ok, "click." + self.widgetName, function (e) {
                    self.submitColorDialog(colorCommand);
                    self._onDesignViewBlur(e);
                }).delegate(selector_dlg_cancel, "click." + self.widgetName, function () {
                    self._closeDialog();
                });

                if (color) {
                    sColor = color.toString();
                    if ($.browser.mozilla && sColor === "transparent") {
                        sColor = "#ffffff";
                    }

                    if ($.browser.msie || !isNaN(sColor)) {
                        iColor = wijParseInt(sColor);

                        sColor = 'rgb(' + (iColor & 255) + ', ' + ((iColor & 65280) >> 8) + ', ' + ((iColor & 16711680) >> 16) + ')';
                    }

                    if (sColor.indexOf('rgb(') === 0) {
                        items = sColor.substring(4, sColor.length - 1).split(',');
                        sColor = self._convertToWebColor(wijParseInt(items[0]), wijParseInt(items[1]), wijParseInt(items[2]));
                    } else if (sColor.indexOf('rgba(') === 0) {
                        items = sColor.substring(5, sColor.length - 1).split(',');
                        sColor = self._convertToWebColor(wijParseInt(items[0]), wijParseInt(items[1]), wijParseInt(items[2]));
                    }

                    $("." + css_colordlg_color + " input", $dlg).attr("value", sColor);
                }

                $("." + css_colordlg_picker, $dlg).wijeditorcolorcanvas("." + css_colordlg_color + " input", sColor);
            };

            /** @ignore */
            wijeditor.prototype.submitColorDialog = function (colorCommand) {
                var self = this, $color = $("." + css_colordlg_color + " input", self.dialog);

                self.setColor(colorCommand, $color.val());
                self._closeDialog();
            };

            /** @ignore */
            wijeditor.prototype.setColor = function (cmdID, color) {
                var self = this, htmlText, doc = self._getDesignViewDocument(), win = self._getDesignViewWindow(), selection;

                self._setIESelection();

                if ($.browser.mozilla && cmdID === 'BackColor') {
                    selection = win.getSelection();
                    self.insertHTML('<span style="background-color:' + color + ';">' + selection + '</span>');
                } else {
                    doc.execCommand(cmdID, false, color);

                    // For case 41717. Make <U> and <STRIKE> tag wrapped in <FONT>. Just in IE.
                    if ($.browser.msie) {
                        htmlText = self._getHtmlTextInIE(doc);

                        if (htmlText.indexOf("<U>") >= 0 && htmlText.indexOf("</U>") >= 0) {
                            doc.execCommand("Underline", false, false);
                            doc.execCommand("Underline");
                        }
                        if (htmlText.indexOf("<STRIKE>") >= 0 && htmlText.indexOf("</STRIKE>") >= 0) {
                            doc.execCommand("StrikeThrough", false, false);
                            doc.execCommand("StrikeThrough");
                        }
                    }

                    if (self.options.mode === "bbcode" && !($.browser.msie)) {
                        self._convertFontStyleToStandTag();
                    }
                }

                self._addtoUndoBuffer();
                self._setSaveBtnEnabled();
            };

            //end of color dialog.
            //begin to handle the table dialog.
            /** @ignore */
            wijeditor.prototype.initInsertTableDialog = function () {
                var self = this, $dlg = self.dialog;

                $dlg.delegate(selector_dlg_ok, "click." + self.widgetName, function (e) {
                    self.submitInsertTableDialog();
                    self._onDesignViewBlur(e);
                }).delegate(selector_input_cancel, "click." + self.widgetName, function () {
                    self._closeDialog();
                }).delegate("." + css_tabledlg_bgcolor + " input:button", "click." + self.widgetName, function () {
                    self.showTableColorDialog(this, $dlg);
                });
            };

            /** @ignore */
            wijeditor.prototype.submitInsertTableDialog = function () {
                var self = this, attribs = self._getValuesFromTableDialog();

                if (!attribs) {
                    return;
                }

                self._insertTable(attribs);
                self._closeDialog();
            };

            wijeditor.prototype._insertTable = function (attribs) {
                var self = this, html = '', i, j;

                if (!attribs) {
                    return false;
                }

                //Fix Insert Table (#245498)
                if (self._isIE11) {
                    setTimeout(function () {
                        self.focus();
                    }, 0);
                } else {
                    self.focus();
                }

                html += '<table width="' + attribs.width + '" height="' + attribs.height + '" cellspacing="' + attribs.cspacing + '" cellpadding="' + attribs.cpadding + '" border="' + attribs.border + '" bgcolor="' + attribs.bgcolor + '" style="' + attribs.css + '">';

                for (i = 0; i < attribs.rows; i++) {
                    html += '<tr>';
                    for (j = 0; j < attribs.cols; j++) {
                        html += '<td>Cell ' + (i + 1) + '-' + (j + 1) + '</td>';
                    }
                    html += '</tr>';
                }
                html += '</table>';

                if ($.browser.mozilla || ($.browser.msie && wijParseInt($.browser.version) >= 9) || this._isEdge) {
                    html += '<br />';
                }

                self.insertHTML(html);
            };

            ////end of the insert table dialog.
            ////begin to handle the edit table dialog.
            /** @ignore */
            wijeditor.prototype.initEditTableDialog = function () {
                var self = this, $dlg = self.dialog, el = self._getInspectElement(), rows, columns;

                $dlg.delegate(selector_dlg_ok, "click." + self.widgetName, function (e) {
                    self.submitEditTableDialog();
                    self._onDesignViewBlur(e);
                }).delegate(selector_input_cancel, "click." + self.widgetName, function () {
                    self._closeDialog();
                }).delegate("." + css_tabledlg_bgcolor + " input:button", "click." + self.widgetName, function () {
                    self.showTableColorDialog(this, $dlg);
                });

                if (!el) {
                    return;
                }

                try  {
                    rows = el.rows;

                    if (rows.length > 0) {
                        columns = rows[0].cells.length;
                    } else {
                        columns = 0;
                    }

                    rows = rows.length;
                } catch (e) {
                }

                $("." + css_tabledlg_rows + " input", $dlg).val(rows);
                $("." + css_tabledlg_columns + " input", $dlg).val(columns);
                $("." + css_tabledlg_width + " input", $dlg).val(el.getAttribute("width"));
                $("." + css_tabledlg_height + " input", $dlg).val(el.getAttribute("height"));
                $("." + css_tabledlg_border + " input", $dlg).val(el.getAttribute("border"));
                $("." + css_tabledlg_cellpadding + " input", $dlg).val(el.getAttribute("cellPadding"));
                $("." + css_tabledlg_cellspacing + " input", $dlg).val(el.getAttribute("cellSpacing"));
                $("." + css_tabledlg_bgcolor + " input", $dlg).val(el.getAttribute("bgcolor") || "#ffffff");
                $("." + css_tabledlg_csstext + " input", $dlg).val(el.style.cssText);
            };

            /** @ignore */
            wijeditor.prototype.submitEditTableDialog = function () {
                var self = this, el = self._getInspectElement(), $el = $(el), attribs = self._getValuesFromTableDialog(), rows = attribs && wijParseInt(attribs.rows), cols = attribs && wijParseInt(attribs.cols), newRow, newCell;

                if (!attribs) {
                    return;
                }

                if (el) {
                    $el.attr("width", attribs.width);
                    $el.attr("height", attribs.height);
                    $el.attr("bgcolor", attribs.bgcolor);
                    $el.attr("border", attribs.border);
                    $el.attr("cellSpacing", attribs.cspacing);
                    $el.attr("cellPadding", attribs.cpadding);

                    el.style.cssText = attribs.css;

                    if (!rows || isNaN(rows)) {
                        return;
                    }

                    if (!cols || isNaN(cols)) {
                        return;
                    }

                    while (el.rows.length > rows) {
                        el.deleteRow(0);
                    }

                    while (el.rows.length < rows) {
                        newRow = el.insertRow(0);
                        while (newRow.cells.length < cols) {
                            newCell = newRow.insertCell(0);
                            newCell.innerHTML = '&nbsp;';
                        }
                    }

                    $.each(el.rows, function (idx, row) {
                        while (row.cells.length > cols) {
                            row.deleteCell(0);
                        }

                        while (row.cells.length < cols) {
                            newCell = row.insertCell(0);
                            newCell.innerHTML = '&nbsp;';
                        }
                    });
                }

                self._closeDialog();
            };

            ////end of the edit table dialog.
            wijeditor.prototype._getValuesFromTableDialog = function () {
                var self = this, $dlg = self.dialog, rows = $("." + css_tabledlg_rows + " input", $dlg).val(), cols = $("." + css_tabledlg_columns + " input", $dlg).val(), width = $("." + css_tabledlg_width + " input", $dlg).val(), height = $("." + css_tabledlg_height + " input", $dlg).val(), border = $("." + css_tabledlg_border + " input", $dlg).val(), cpadding = $("." + css_tabledlg_cellpadding + " input", $dlg).val(), cspacing = $("." + css_tabledlg_cellspacing + " input", $dlg).val(), css = $("." + css_tabledlg_csstext + " input", $dlg).val(), bgcolor = $("." + css_tabledlg_bgcolor + " input", $dlg).val();

                if (!self._isNumeric(rows)) {
                    wijAlert(this.localizeString("errorMessageRowsError", "Please input a number for 'Rows' textbox."));
                    return false;
                }

                if (!self._isNumeric(cols)) {
                    wijAlert(this.localizeString("errorMessageColumnsError", "Please input a number for 'Columns' textbox."));
                    return false;
                }

                if (!self._isNumeric(width)) {
                    wijAlert(this.localizeString("errorMessageTableWidthError", "Please input a number for 'Table Width ' textbox."));
                    return false;
                }

                if (!self._isNumeric(height)) {
                    wijAlert(this.localizeString("errorMessageTableHeightError", "Please input a number for 'Table Height' textbox."));
                    return false;
                }

                if (!self._isNumeric(border)) {
                    wijAlert(this.localizeString("tableDialogBorderError", "Please input a number for 'Border thickness' textbox."));
                    return false;
                }

                if (!self._isNumeric(cpadding)) {
                    wijAlert(this.localizeString("tableDialogCellPaddingError", "Please input a number for 'Cell Padding' textbox."));
                    return false;
                }

                if (!self._isNumeric(cspacing)) {
                    wijAlert(this.localizeString("tableDialogCellSpacingError", "Please input a number for 'Cell Spacing' textbox."));
                    return false;
                }

                return {
                    rows: rows,
                    cols: cols,
                    width: wijParseInt(width),
                    height: wijParseInt(height),
                    border: border,
                    cpadding: cpadding,
                    cspacing: cspacing,
                    css: css,
                    bgcolor: bgcolor
                };
            };

            /** @ignore */
            wijeditor.prototype.showTableColorDialog = function (el, parentDlg) {
                var self = this, dialogOpts, $subDlg = self.subDialog, bgcolor = $(el).prev().val(), content = self._getDialogRes_Color();

                dialogOpts = {
                    width: "auto",
                    height: "auto",
                    modal: true,
                    title: self.localizeString("backColorDialogTitle", "Set BackColor"),
                    position: { my: "center", at: "center", of: window },
                    resizable: false,
                    captionButtons: {
                        pin: { visible: false },
                        refresh: { visible: false },
                        toggle: { visible: false },
                        minimize: { visible: false },
                        maximize: { visible: false }
                    },
                    close: function () {
                        parentDlg.focus();
                    }
                };

                $subDlg.empty().append(content);
                if ($.browser.msie && wijParseInt($.browser.version) === 6) {
                    window.setTimeout(function () {
                        $subDlg.wijdialog(dialogOpts);
                    }, 0);
                } else {
                    $subDlg.wijdialog(dialogOpts);
                }

                $subDlg.delegate(selector_input_ok, "click." + self.widgetName, function () {
                    self.submitTableColorDialog();
                }).delegate(selector_input_cancel, "click." + self.widgetName, function () {
                    self.closeSubDialog();
                });

                if (bgcolor !== "") {
                    $("." + css_colordlg_color + " input", $subDlg).val(bgcolor);
                }

                $("." + css_colordlg_picker, $subDlg).wijeditorcolorcanvas("." + css_colordlg_color + " input", bgcolor);

                $subDlg.wijdialog("open");
            };

            /** @ignore */
            wijeditor.prototype.submitTableColorDialog = function () {
                var self = this, $subDlg = self.subDialog, $dlg = self.dialog, color = $("." + css_colordlg_color + " input", $subDlg).val();

                $("." + css_tabledlg_bgcolor + " input:text", $dlg).val(color);
                self.closeSubDialog();
            };

            /** @ignore */
            wijeditor.prototype.closeSubDialog = function () {
                this.subDialog.wijdialog("close");
            };

            wijeditor.prototype._getEditableTable = function () {
                var self = this, table, editableTable, $editableTable;

                editableTable = self._getSelectedElement();

                if (!editableTable) {
                    wijAlert(this.localizeString("errorMessageSelectTableError", "Please select a table!"));
                    return false;
                }

                $editableTable = $(editableTable);

                if ($editableTable.is("td,tr,tbody,th")) {
                    editableTable = $editableTable.parents("table:first")[0];
                } else if (!$editableTable.is("table")) {
                    table = $editableTable.find("table:only-child");
                    if ($.browser.msie && table.length) {
                        editableTable = table[0];
                    } else {
                        wijAlert(this.localizeString("errorMessageSelectTableError", "Please select a table!"));
                        return false;
                    }
                }

                inspectElement = editableTable;
                return true;
            };

            //end of table dialog.
            //begin to handle the preview dialog.
            /** @ignore */
            wijeditor.prototype.initPreviewDialog = function () {
                var self = this, $dlg = self.dialog;

                self._setPreviewContent(0);

                $dlg.one("wijdialogclose", function () {
                    self._curPageIdx = 0;
                });

                $dlg.delegate("#rad640_480", "click." + self.widgetName, function () {
                    self._setPreviewDialogSize(640, 480);
                }).delegate("#rad800_600", "click." + self.widgetName, function () {
                    self._setPreviewDialogSize(800, 600);
                }).delegate("#rad1024_768", "click." + self.widgetName, function () {
                    self._setPreviewDialogSize(1024, 768);
                }).delegate("#chkSplit", "click." + self.widgetName, function () {
                    self._splitPreviewPages(this.checked);
                }).delegate("." + css_previewdlg_printall, "click." + self.widgetName, function () {
                    self._printPreviewPage(true);
                }).delegate("." + css_previewdlg_printone, "click." + self.widgetName, function () {
                    self._printPreviewPage(false);
                }).delegate("." + css_previewdlg_ok, "click." + self.widgetName, function () {
                    self._closeDialog();
                }).delegate("." + css_previewdlg_prev, "click." + self.widgetName, function () {
                    self._navigatePreviewPage(false);
                }).delegate("." + css_previewdlg_next, "click." + self.widgetName, function () {
                    self._navigatePreviewPage(true);
                });
            };

            wijeditor.prototype._setPreviewContent = function (pageIndex) {
                var self = this, $dlg = self.dialog, $iframe = $("iframe", $dlg), $pager = $("." + css_previewdlg_navigator + " span", $dlg), doc = $iframe[0].contentWindow.document;

                doc.open();

                if (pageIndex === -1) {
                    doc.write(self._getPreviewAllPageContent());
                    $pager.html('1 / 1');
                } else {
                    doc.write(self._getPreviewPageContent(pageIndex));
                    $pager.html((pageIndex + 1) + ' / ' + self._getPreviewPageCount());
                }

                doc.close();
            };

            wijeditor.prototype._setPreviewDialogSize = function (width, height) {
                var self = this, $dlg = self.dialog, $iframe = $("iframe", $dlg), offsetW = $dlg.wijdialog("option", "width"), offsetH = $dlg.wijdialog("option", "height");

                if (offsetW === "auto") {
                    offsetW = $dlg.parent(".wijmo-wijdialog").width() - $iframe.width();
                } else {
                    offsetW = offsetW - $iframe.width();
                }

                if (offsetH === "auto") {
                    offsetH = $dlg.parent(".wijmo-wijdialog").height() - $iframe.height();
                } else {
                    offsetH = offsetH - $iframe.height();
                }

                $iframe.css("width", width).css("height", height);
                $dlg.wijdialog("option", {
                    width: width + offsetW,
                    height: height + offsetH
                });
            };

            wijeditor.prototype._getPreviewPageCount = function () {
                return this._getPreviewPages().length;
            };

            wijeditor.prototype._getPreviewPageContent = function (pageIndex) {
                var contents = this._getPreviewPages();

                if (contents.length > pageIndex) {
                    return contents[pageIndex];
                }

                return null;
            };

            wijeditor.prototype._getPreviewAllPageContent = function () {
                return this._getDesignViewText();
            };

            wijeditor.prototype._getPreviewPages = function () {
                var contents = this._getPreviewAllPageContent(), regexp = new RegExp('<(HR|hr)[^>]*(page-break-before|' + 'PAGE-BREAK-BEFORE)[ ]*:[ ]*always[^>]*>', 'g'), tempContents = contents.replace(regexp, '!-~U^n#i@q,P|.a=g~e+br!');

                return tempContents.split('!-~U^n#i@q,P|.a=g~e+br!');
            };

            //_curPageIdx: 0,
            wijeditor.prototype._splitPreviewPages = function (isSplit) {
                var self = this, $dlg = self.dialog, $pdoc = $("." + css_previewdlg_printdocument, $dlg), $pnav = $("." + css_previewdlg_navigator, $dlg);

                if (isSplit) {
                    self._setPreviewContent(0);
                    $pnav.show();
                    $pdoc.hide();
                } else {
                    self._setPreviewContent(-1);
                    $pnav.hide();
                    $pdoc.show();
                }

                self._curPageIdx = 0;
            };

            wijeditor.prototype._navigatePreviewPage = function (isNext) {
                var self = this, $chkSplit = $("#chkSplit", self.dialog), curIdx = self._curPageIdx, pageCount = self._getPreviewPageCount();

                if ($chkSplit.is(":checked")) {
                    if (isNext) {
                        curIdx++;
                        if (curIdx < pageCount) {
                            self._setPreviewContent(curIdx);
                        } else {
                            curIdx = pageCount - 1;
                        }
                    } else {
                        curIdx--;
                        if (curIdx >= 0) {
                            self._setPreviewContent(curIdx);
                        } else {
                            curIdx = 0;
                        }
                    }

                    self._curPageIdx = curIdx;
                }
            };

            wijeditor.prototype._printPreviewPage = function (isAll) {
                var self = this, $dlg = self.dialog, $chkSplit = $("#chkSplit", $dlg), win = $("iframe", $dlg)[0].contentWindow;

                if (isAll) {
                    $chkSplit.removeAttr("checked");
                    self._setPreviewContent(-1);
                }

                win.focus();
                win.print();
            };

            //end of preview dialog.
            //begin to handle the cleanup dialog.
            /** @ignore */
            wijeditor.prototype.initCleanUpDialog = function () {
                var self = this, $dlg = self.dialog;

                $("textarea", $dlg).val(self.sourceView.val());

                $dlg.delegate(selector_dlg_ok, "click." + self.widgetName, function (e) {
                    self.submitCleanUpDialog();
                    self._onDesignViewBlur(e);
                }).delegate(selector_dlg_cancel, "click." + self.widgetName, function () {
                    self._closeDialog();
                });
            };

            /** @ignore */
            wijeditor.prototype.submitCleanUpDialog = function () {
                var self = this, $dlg = self.dialog, $sourceView = self.sourceView, source = $sourceView.val(), reg;

                if ($("#replaceSpans", $dlg).is(":checked")) {
                    reg = new RegExp('<\\/?SPAN[^>]*>', 'g');
                    source = source.replace(reg, '');
                }

                if ($("#replaceClass", $dlg).is(":checked")) {
                    reg = new RegExp('<(\\w[^>]*) class=([^ |>]*)([^>]*)', 'g');
                    source = source.replace(reg, '<$1$3');
                }

                if ($("#replaceStyle", $dlg).is(":checked")) {
                    reg = new RegExp('<(\\w[^>]*) style=\"([^\"]*)\"([^>]*)', 'g');
                    source = source.replace(reg, '<$1$3');
                    reg = new RegExp('<(\\w[^>]*) lang=([^ |>]*)([^>]*)', 'g');
                    source = source.replace(reg, '<$1$3');
                    reg = new RegExp('<\\\\?\\?xml[^>]*>', 'g');
                    source = source.replace(reg, '');
                    reg = new RegExp('<\\/?\\w+:[^>]*>', 'g');
                    source = source.replace(reg, '');
                }

                if ($("#replaceNbsp", $dlg).is(":checked")) {
                    reg = new RegExp('&nbsp;', 'g');
                    source = source.replace(reg, ' ');
                }

                if ($("#transformPtoDiv", $dlg).is(":checked")) {
                    reg = new RegExp('(<P)([^>]*>.*?)(<\\/P>)', 'g');
                    source = source.replace(reg, '<div$2</div>');
                }

                $sourceView.val(source);
                self._setDesignViewText(source);
                self._addtoUndoBuffer();
                self._closeDialog();
            };

            //end of cleanup dialog.
            //begin to handle the find/replace dialog.
            /** @ignore */
            wijeditor.prototype.initFindDialog = function () {
                var self = this, $dlg = self.dialog;

                if (self.tRange) {
                    self.tRange = null;
                }

                $dlg.delegate(selector_dlg_ok, "click." + self.widgetName, function () {
                    self.submitFindAction();
                }).delegate(selector_dlg_cancel, "click." + self.widgetName, function (e) {
                    if (self.options.readOnly) {
                        return;
                    }

                    self.submitReplaceAction();
                    self._onDesignViewBlur(e);
                });
            };

            /** @ignore */
            wijeditor.prototype.submitFindAction = function () {
                var self = this, text = $("textarea:first", self.dialog).val();

                if ($.trim(text) === '') {
                    return;
                }

                self._findAndReplaceString(text);
            };

            /** @ignore */
            wijeditor.prototype.submitReplaceAction = function () {
                var self = this, $dlg = self.dialog, fText = $("textarea:first", $dlg).val(), rText = $("textarea:last", $dlg).val();

                if ($.trim(fText) === '') {
                    return;
                }

                if ($.trim(rText) === '') {
                    wijAlert(this.localizeString("errorMessageReplaceStringError", "please input replace string!"));
                    return;
                }

                self._findAndReplaceString(fText, rText);
            };

            wijeditor.prototype._findAndReplaceString = function (fText, rText) {
                var self = this, contentWindow = self._getDesignViewWindow(), strFound = 0, strReplaced = false, noIESel, needReplace = rText && rText !== fText;

                // window.find(chrome and FF), createTextRange(IE) and range.findText(IE)
                // are not the html standard. And all of these are not supported in Edge.
                // Return if the browser is Edge. Please refer to #122977.
                if (self._isEdge) {
                    return;
                }

                if (!rText) {
                    rText = fText;
                }

                if ($.browser.msie) {
                    if (self.tRange) {
                        if (self.txtFoundInIE && needReplace) {
                            strFound = self.tRange.findText(fText);
                            if (strFound) {
                                self.tRange.pasteHTML(rText);
                                self.tRange.collapse(false);
                                strReplaced = true;
                                self.txtFoundInIE = false;
                            }
                        } else {
                            self.tRange.collapse(false);
                            strFound = self.tRange.findText(fText);
                            if (strFound) {
                                self.tRange.select();
                            }
                        }
                    }
                    if (!strReplaced && (!self.tRange || !strFound)) {
                        self.tRange = contentWindow.document.body.createTextRange();
                        strFound = self.tRange.findText(fText);
                        if (strFound) {
                            self.tRange.select();
                            if (needReplace) {
                                self.tRange.pasteHTML(rText);
                                strReplaced = true;
                            }
                        }
                    }
                } else {
                    if (self.txtFoundInNoneIE && needReplace) {
                        self._replaceSelectionForNoneIE(rText);
                        strReplaced = true;
                        self.txtFoundInNoneIE = false;
                    } else {
                        noIESel = contentWindow.getSelection();
                        if (noIESel.rangeCount > 0) {
                            noIESel.collapseToEnd();
                        }
                        strFound = contentWindow.find(fText);
                        if (!strFound) {
                            strFound = contentWindow.find(fText, 0, 1);
                            while (contentWindow.find(fText, 0, 1)) {
                                continue;
                            }
                        }
                    }
                    self.txtFoundInNoneIE = self.txtFoundInNoneIE || (strFound > 0);
                    if (self.txtFoundInNoneIE && needReplace) {
                        self._replaceSelectionForNoneIE(rText);
                        strReplaced = true;
                        self.txtFoundInNoneIE = false;
                    }
                }

                if (!strFound && !strReplaced) {
                    wijAlert('"' + fText + '"' + this.localizeString("errorMessageFindTextError", " String Not Found!"));
                    self.tRange = null;
                    self.txtFoundInNoneIE = false;
                    self.txtFoundInIE = false;
                } else {
                    self.txtFoundInIE = true;
                }
            };

            wijeditor.prototype._replaceSelectionForNoneIE = function (html) {
                var doc = this._getDesignViewDocument();

                //randomStr = 'insert_html_' + Math.round(Math.random() * 100000000);
                //regex = new RegExp('<[^<]*' + randomStr + '[^>]*>');
                /** update for case 30008
                doc.execCommand('insertimage', false, randomStr);
                doc.body.innerHTML = doc.body.innerHTML.replace(regex, html);
                */
                doc.execCommand('inserttext', false, html);
            };

            //end of find/replace dialog.
            //begin to handle the media dialog.
            /** @ignore */
            wijeditor.prototype.initMediaDialog = function () {
                var self = this, $dlg = self.dialog;

                $dlg.delegate(selector_dlg_ok, "click." + self.widgetName, function (e) {
                    self.submitMediaDialog();
                    self._onDesignViewBlur(e);
                }).delegate(selector_dlg_cancel, "click." + self.widgetName, function () {
                    self._closeDialog();
                });
            };

            /** @ignore */
            wijeditor.prototype.submitMediaDialog = function () {
                var self = this, $dlg = self.dialog, type = $("select", $dlg).val(), url = $("." + css_mediadlg_url + " input", $dlg).val(), width = $("." + css_mediadlg_width + " input", $dlg).val(), height = $("." + css_mediadlg_height + " input", $dlg).val();

                if (url === '') {
                    wijAlert(this.localizeString("errorMessageUrlEmptyError", "URL is empty!"));
                    return;
                }

                if (!self._isUrl(url)) {
                    wijAlert(this.localizeString("errorMessageUrlCorrectError", "please input correct URL!"));
                    return;
                }

                if (!self._isNumeric(width)) {
                    wijAlert(this.localizeString("errorMessageMediaWidthError", "please input width of the media!"));
                    return;
                }

                if (!self._isNumeric(height)) {
                    wijAlert(this.localizeString("errorMessageMediaHeightError", "please input height of the media!"));
                    return;
                }

                self._insertMedia(type, url, width, height);
                self._closeDialog();
            };

            wijeditor.prototype._insertMedia = function (type, url, width, height) {
                var self = this, html = '';

                //Fix Insert Media (#245498)
                if (self._isIE11) {
                    setTimeout(function () {
                        self._setIESelection();
                    });
                } else {
                    self._setIESelection();
                }

                switch (type) {
                    case 'video':
                        html += '<embed src="' + url + '" width="' + width + '" ' + 'height="' + height + '" ' + 'type=audio/x-pn-realaudio-plugin console="Clip1" ' + 'controls="IMAGEWINDOW,ControlPanel,StatusBar" ' + 'autostart="true"></embed>';
                        break;
                    case 'flash':
                        html += '<object classid="' + 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" ' + 'codebase="http://download.macromedia.com/pub/' + 'shockwave/cabs/flash/swflash.cab#version=6,0,29,0" ' + 'width="' + width + '" height="' + height + '">';
                        html += '<param name="movie" value="' + url + '">';
                        html += '<param name="wmode" value="opaque">';
                        html += '<param name="quality" value="high">';
                        html += '<embed src="' + url + '" quality="high" ' + 'pluginspage="http://www.macromedia.com/go/getflashplayer" ' + 'type="application/x-shockwave-flash" ' + 'width="' + width + '" height="' + height + '"></embed>';
                        html += '</object>';
                        break;
                    case 'applet':
                        html += '<applet code="' + url + '" width="' + width + '" ' + 'height="' + height + '"></applet>';
                        break;
                    case 'other':
                        html += '<embed src="' + url + '" width="' + width + '" ' + 'height="' + height + '"></embed>';
                        break;
                }

                self.insertHTML(html);
            };

            //end of media dialog.
            //begin to handle the special char dialog.
            /** @ignore */
            wijeditor.prototype.initSpecialCharacterDialog = function () {
                var self = this, $dlg = self.dialog, $preview = $("." + css_specialchardlg_content + " span", $dlg);

                $dlg.delegate("label", "click." + self.widgetName, function (e) {
                    self.submitSpecialCharacterDialog(this);
                    self._onDesignViewBlur(e);
                }).delegate(selector_dlg_ok, "click." + self.widgetName, function () {
                    self._closeDialog();
                }).delegate("label", "mouseover." + self.widgetName, function () {
                    $preview.html($(this).html());
                }).delegate("label", "mouseout." + self.widgetName, function () {
                    $preview.empty();
                });
            };

            /** @ignore */
            wijeditor.prototype.submitSpecialCharacterDialog = function (element) {
                var self = this;

                //Fix Insert Special Character (#245498)
                if (self._isIE11) {
                    setTimeout(function () {
                        self._setIESelection();
                    });
                } else {
                    self._setIESelection();
                }
                self.insertHTML($(element).html());
                self._closeDialog();
            };

            //end of special dialog.
            //begin to handle the ribbon commands.
            wijeditor.prototype._setSaveBtnEnabled = function () {
                this.$ribbon.wijribbon(setButtonDisabled, cmd_save, false);
            };

            //undo/redo action.
            wijeditor.prototype._undoAction = function () {
                var body = this._getDesignViewDocument().body, buttonStates = {};

                undoSteps--;
                if (undoSteps <= 0) {
                    undoSteps = 0;
                }

                body.innerHTML = undoBuffers[undoSteps];

                if (!undoSteps) {
                    buttonStates[cmd_undo] = true;
                    buttonStates[cmd_redo] = false;
                    this.$ribbon.wijribbon(setButtonsDisabled, buttonStates);
                } else {
                    this.$ribbon.wijribbon(setButtonDisabled, cmd_redo, false);
                }
            };

            wijeditor.prototype._redoAction = function () {
                var body = this._getDesignViewDocument().body, len = undoBuffers.length, buttonStates = {};

                undoSteps++;
                if (undoSteps >= len - 1) {
                    undoSteps = len - 1;
                }

                body.innerHTML = undoBuffers[undoSteps];

                if (undoSteps === len - 1) {
                    buttonStates[cmd_undo] = false;
                    buttonStates[cmd_redo] = true;
                    this.$ribbon.wijribbon(setButtonsDisabled, buttonStates);
                } else {
                    this.$ribbon.wijribbon(setButtonDisabled, cmd_undo, false);
                }
            };

            wijeditor.prototype._addtoUndoBuffer = function () {
                var len = undoBuffers.length - 1 - undoSteps, idx;

                for (idx = 0; idx < len; idx++) {
                    undoBuffers.pop();
                }
                undoSteps++;
                undoBuffers.push(this._getDesignViewText());
                this.$ribbon.wijribbon(setButtonDisabled, cmd_undo, false);
            };

            //end of undo/redo action.
            //delete action for cut.
            wijeditor.prototype._deleteSelectionContent = function () {
                var cWin = this._getDesignViewWindow(), selection, i, range, rangeCount = "rangeCount";

                if ($.browser.msie) {
                    selection = cWin.document.selection;
                    if (selection.type.toLowerCase() !== 'none') {
                        selection.clear();
                    }
                } else {
                    selection = cWin.getSelection();
                    for (i = 0; i < selection[rangeCount]; i++) {
                        range = selection.getRangeAt(i);
                        range.deleteContents();
                    }
                }
            };

            //end of delete action for cut.
            //path selector action.
            wijeditor.prototype._refreshPathSelector = function () {
                var self = this, inspEl = self._getParentElement(self._getDesignViewWindow()), inspElName, $pathSelector = self._getPathSelector(), $parents = $(inspEl).parents(), len = $parents.length, css = "wijmo-wijeditor-label ui-state-default ui-corner-all", idx, labelSize, halfLabelSize, footerWidth = $(".wijmo-wijeditor-footer", self.editor).outerWidth(true), modesWidth = $(".wijmo-wijribbon-modes", self.editor).outerWidth(true), labelWidth, labelsString = "";

                if (!inspEl) {
                    return;
                }
                inspElName = inspEl.tagName ? inspEl.tagName.toLowerCase() : "";
                $pathSelector.empty();

                //get first label to calculate the width
                $pathSelector.append("<label class='" + css + "'>&lt;" + $parents[len - 1].tagName.toLowerCase() + "&gt;</label>");
                labelWidth = $(".wijmo-wijeditor-pathselector>.wijmo-wijeditor-label", self.editor).outerWidth(true);

                //get show maximum label size
                labelSize = Math.floor((footerWidth - modesWidth) / labelWidth);
                halfLabelSize = Math.floor((footerWidth - modesWidth) / (labelWidth * 2));

                if (len <= labelSize) {
                    for (idx = len - 2; idx >= 0; idx--) {
                        if ($parents[idx]) {
                            labelsString += "<label class='" + css + "'> &lt;" + $parents[idx].tagName.toLowerCase() + "&gt;</label>";
                        }
                    }
                } else {
                    for (idx = len - 2; idx >= len - halfLabelSize + 1; idx--) {
                        if ($parents[idx]) {
                            labelsString += "<label class='" + css + "'> &lt;" + $parents[idx].tagName.toLowerCase() + "&gt;</label>";
                        }
                    }
                    labelsString += "<label class='" + css + "'>&lt;.......&gt;</label>";

                    for (idx = halfLabelSize - 2; idx >= 0; idx--) {
                        if ($parents[idx]) {
                            labelsString += "<label class='" + css + "'> &lt;" + $parents[idx].tagName.toLowerCase() + "&gt;</label>";
                        }
                    }
                }

                labelsString += "<label class='" + css + " wijmo-wijeditor-selectlabel ui-state-highlight ui-corner-all'>&lt;" + inspElName + "&gt;</label>";
                $pathSelector.append(labelsString);
            };

            //end of path selector action.
            //table borders action.
            wijeditor.prototype._toggleTableBorders = function () {
                var tableVirtualBorderShowing = this.options.tableVirtualBorderShowing;

                this._updateTableBorderShowing(!tableVirtualBorderShowing);
                this.options.tableVirtualBorderShowing = !tableVirtualBorderShowing;
            };

            //end of table borders action.
            wijeditor.prototype._updateTableBorderShowing = function (tableVirtualBorderShowing) {
                var doc = this._getDesignViewDocument(), $bStyle = $('#__wijStyle', doc);

                if ($.browser.safari || this._isEdge) {
                    if (tableVirtualBorderShowing) {
                        $bStyle.html('table,td,tr{border: 1px #acacac dashed;}');
                    } else {
                        $bStyle.empty();
                    }
                } else {
                    $bStyle.prop("disabled", !tableVirtualBorderShowing);
                }
            };

            //table action.
            wijeditor.prototype._tableAction = function (type) {
                var self = this, inspEl = self._getParentElement(self._getDesignViewWindow()), $td = $(inspEl).closest("td"), $tr, $table, td, tr, table, rowIdx, cellIdx, cellCount, rowCount, newRow, idx = 0;

                self._setSaveBtnEnabled();
                if ($td.length === 0 && type !== cmd_mergecell) {
                    return false;
                } else if (type !== cmd_mergecell) {
                    $tr = $td.parent();
                    $table = $tr.closest("table");
                    td = $td[0];
                    tr = $tr[0];
                    table = $table[0];
                    rowIdx = tr.rowIndex;
                    cellIdx = td.cellIndex;
                }
                try  {
                    switch (type) {
                        case cmd_insertrow:
                            cellCount = tr.cells.length;
                            newRow = table.insertRow(rowIdx);

                            for (idx = 0; idx < cellCount; idx++) {
                                self._insertCell(newRow, idx);
                            }
                            break;
                        case cmd_removerow:
                            table.deleteRow(rowIdx);
                            break;
                        case cmd_insertcolumn:
                            rowCount = table.rows.length;

                            for (idx = 0; idx < rowCount; idx++) {
                                self._insertCell(table.rows[idx], cellIdx);
                            }
                            break;
                        case cmd_removecolumn:
                            self._removeColumn(table, cellIdx);
                            break;
                        case cmd_insertcell:
                            self._insertCell(tr, cellIdx + 1);
                            break;
                        case cmd_removecell:
                            cellCount = tr.cells.length;

                            if (cellCount === 1) {
                                table.deleteRow(rowIdx);
                            } else {
                                tr.deleteCell(cellIdx);
                            }
                            break;
                        case cmd_splitcell:
                            self._splitCell(table, tr, rowIdx, cellIdx);
                            break;
                        case cmd_mergecell:
                            self._mergeCell(self._getSelectedCells(inspEl));
                            break;
                    }
                    this._addtoUndoBuffer();
                } catch (e) {
                    wijAlert(e.message);
                    return false;
                }
                return true;
            };

            wijeditor.prototype._removeColumn = function (table, curCellIndex) {
                var rowCount = table.rows.length, idx = 0, tr, cells, cellCount, cellIdx, colSpan;

                while (idx < rowCount) {
                    tr = table.rows[idx];
                    cells = tr.cells;
                    cellCount = cells.length;
                    cellIdx = (curCellIndex > cellCount - 1) ? cellCount - 1 : curCellIndex;
                    colSpan = cells[cellIdx].colSpan;

                    if (colSpan > 1 && cellCount > 1) {
                        if (cellIdx + 1 < cellCount) {
                            (cells[cellIdx + 1]).colSpan += colSpan - 1;
                        } else {
                            (cells[cellIdx - 1]).colSpan += colSpan + 1;
                        }
                    }

                    if (cellCount === 1) {
                        table.deleteRow(idx);
                        rowCount = table.rows.length;
                    } else {
                        tr.deleteCell(cellIdx);
                        idx++;
                    }
                }
            };

            wijeditor.prototype._splitCell = function (table, tr, rowIndex, cellIndex) {
                var rowCount = table.rows.length, idx = 0, colSpan = 0, tempRow, tempColSpan, i, maxCellIdx, tempRowCount;

                while (idx <= cellIndex) {
                    if (tr.cells[idx].colSpan > 1) {
                        colSpan += tr.cells[idx].colSpan - 1;
                    }
                    idx++;
                }

                this._insertCell(tr, cellIndex + 1);

                if (tr.cells[cellIndex].colSpan > 1) {
                    tr.cells[cellIndex].colSpan--;
                } else {
                    for (i = 0; i < rowCount; i++) {
                        tempRow = table.rows[i];
                        if (i !== rowIndex) {
                            maxCellIdx = cellIndex;
                            idx = 0;
                            tempColSpan = 0;
                            while (idx <= maxCellIdx) {
                                if (tempRow.cells[idx].colSpan > 1) {
                                    tempColSpan += tempRow.cells[idx].colSpan - 1;
                                    maxCellIdx -= tempColSpan;
                                }
                                idx++;
                            }
                            tempRowCount = cellIndex + colSpan - tempColSpan;
                            if (tempRowCount < 0) {
                                tempRowCount = 0;
                            }
                            tempRow.cells[tempRowCount].colSpan++;
                        }
                    }
                }
            };

            wijeditor.prototype._mergeCell = function (cells) {
                var _this = this;
                var len = cells.length, tr = cells[0].parentNode, sIdx, eIdx, idx, trLast = cells[len - 1].parentNode, columnSize = tr.cells.length, sameRowCells = {}, rowIndex, isCellsInSameRow = true, newtrCells = [];

                if (len < 2) {
                    return;
                }

                // merge cells that the table only one column
                if (columnSize === 1 && tr !== trLast) {
                    for (var i = 1; i < cells.length; i++) {
                        cells[0].innerHTML += cells[i].innerHTML;
                        $(cells[i].parentNode).remove();
                    }
                } else if (columnSize > 1 && tr === trLast) {
                    //merge cells in same row
                    sIdx = cells[0].cellIndex;
                    eIdx = sIdx + len;

                    for (idx = sIdx + 1; idx < eIdx; idx++) {
                        tr.cells[sIdx].innerHTML += tr.cells[sIdx + 1].innerHTML;
                        tr.cells[sIdx].colSpan++;
                        tr.deleteCell(sIdx + 1);
                    }
                } else if (columnSize > 1 && tr !== trLast) {
                    //collect the selected cells with row index order
                    $.each(cells, function (index, cell) {
                        rowIndex = cells[index].parentNode.rowIndex;
                        if (!sameRowCells[rowIndex]) {
                            sameRowCells[rowIndex] = [];
                        }
                        sameRowCells[rowIndex].push(cell);
                    });

                    //check the whole tr cell is selected
                    $.each(sameRowCells, function (key, cells) {
                        if (cells.length !== columnSize) {
                            isCellsInSameRow = false;
                            return false;
                        }
                    });

                    if (isCellsInSameRow) {
                        $.each(sameRowCells, function (key, cells) {
                            newtrCells.push(cells[0]);
                            _this._mergeCell(cells);
                        });
                        this._mergeCell(newtrCells);
                    }
                }
            };

            wijeditor.prototype._getSelectedCells = function (inspEl) {
                var self = this, win = this._getDesignViewWindow(), doc = win.document, cells = [], tempCells, range, parent, selection, idx, rangeCount, sContainer, nodeName, offset;

                if ($.browser.msie) {
                    parent = $(inspEl).closest("tr")[0];
                    range = self._getIESelectionRange();
                    tempCells = parent ? parent.cells : self._getPrepareTableCells(inspEl);
                    $.each(tempCells, function (idx, cell) {
                        if (self._isIE11) {
                            if (self._checkSelectionIncludeNodeForIE11AndChrome(win, range, cell)) {
                                cells.push(cell);
                            }
                        } else {
                            if (self._checkSelectionIncludeNodeExceptIE11(win, range, cell)) {
                                cells.push(cell);
                            }
                        }
                    });
                } else if ($.browser.mozilla) {
                    selection = win.getSelection();
                    rangeCount = selection.rangeCount;

                    for (idx = 0; idx < rangeCount; idx++) {
                        range = selection.getRangeAt(idx);
                        sContainer = range.startContainer;
                        nodeName = sContainer.nodeName.toLowerCase();

                        if (nodeName === 'td' || nodeName === 'th') {
                            cells.push(sContainer);
                        } else if (nodeName === 'tr') {
                            offset = range.startOffset;
                            cells.push(sContainer.cells[offset]);
                        }
                    }
                } else {
                    parent = $(inspEl).closest("tr")[0];

                    //merge cells only one column in table
                    selection = win.getSelection();
                    if (selection && selection.rangeCount > 0) {
                        range = selection.getRangeAt(0);
                    }
                    tempCells = parent ? parent.cells : self._getPrepareTableCells(inspEl);
                    $.each(tempCells, function (index, cell) {
                        if (self._checkSelectionIncludeNodeForIE11AndChrome(win, range, cell)) {
                            cells.push(cell);
                        }
                    });
                }

                return cells;
            };

            wijeditor.prototype._getPrepareTableCells = function (ele) {
                var parent = $(ele.parentElement), templeCells;
                templeCells = parent ? parent.children().children("tr").children("td") : [];
                return templeCells;
            };

            //end of table action.
            //insert date time.
            /** @ignore */
            wijeditor.prototype.insertDateAndTime = function () {
                var curDate = new Date();
                if (this.options.culture && this.options.culture !== "") {
                    this.insertHTML(Globalize.format(curDate, "dddd ", Globalize.findClosestCulture(this.options.culture)) + Globalize.format(curDate, "F", Globalize.findClosestCulture(this.options.culture)));
                } else {
                    this.insertHTML(curDate.toDateString() + ' ' + curDate.toTimeString());
                }
            };

            //end of insert date time.
            //wordwrap action.
            wijeditor.prototype._toggleWordWrap = function () {
                var self = this, $sourceView = self.sourceView, wrap = "wrap", value;

                wordwrap = !wordwrap;
                value = wordwrap ? 'soft' : 'off';

                $sourceView.attr(wrap, value);
                $sourceView[0].focus();

                if ($.browser.mozilla) {
                    $sourceView.hide();

                    wijWindow.setTimeout(function () {
                        $sourceView.show();
                    }, 40);
                }
            };

            //end of wordwrap action.
            //insert html text to the document.
            /** @ignore */
            wijeditor.prototype.insertHTML = function (htmlText) {
                var self = this, doc = self._getDesignViewDocument(), range;

                try  {
                    if ($.browser.msie) {
                        if (self._isIE11 && doc.getSelection) {
                            range = self._getRangeForInsertHTML(doc, htmlText);
                        } else {
                            if (doc.selection.type === "Control") {
                                // If the selection type is "Control",
                                // clear the content of the selection firstly
                                // and then the result of "createRange" will be a TextRange located in the position of original control.
                                doc.selection.clear();
                            }
                            range = doc.selection.createRange();
                            range.pasteHTML(htmlText);
                            range.collapse(false);
                            self.rangeSelection = null;
                        }
                        self._setIESelection(range, true);
                    } else {
                        doc.execCommand('insertHTML', false, htmlText);
                    }
                } catch (e) {
                    //Condition: insert element after inserting hidden input element
                    //Result: IE8 and IE11 are ok; but IE9 and IE10 exception throws
                    if ($.browser.msie && $.browser.version && parseFloat($.browser.version) >= 9 && parseFloat($.browser.version) <= 10 && self.rangeSelection) {
                        try  {
                            range = self.rangeSelection;
                            range.pasteHTML(htmlText);
                            range.collapse(false);
                            self._setIESelection(range, true);
                        } catch (e) {
                        }
                    }
                }

                self._addtoUndoBuffer();
                self._setSaveBtnEnabled();
            };

            //end of insert html text to the document.
            wijeditor.prototype._getRangeForInsertHTML = function (doc, htmlText) {
                var sel, range, frag;
                if (doc.getSelection) {
                    sel = doc.getSelection();
                    if (this.rangeSelection) {
                        range = this.rangeSelection;
                        this.rangeSelection = null;
                    } else if (sel.getRangeAt && sel.rangeCount) {
                        range = sel.getRangeAt(0);
                    }
                    if (range) {
                        range.deleteContents();
                        frag = range.createContextualFragment(htmlText);
                        range.insertNode(frag);
                        range.collapse(false);
                    }
                }
                return range;
            };
            wijeditor.prototype._setIEFocus = function () {
                var doc = this._getDesignViewDocument();

                if ($.browser.msie) {
                    try  {
                        doc.body.focus();
                    } catch (ee) {
                    }
                }
            };

            /** @ignore */
            wijeditor.prototype.focus = function () {
                var win = this._getDesignViewWindow(), doc = win.document;

                if ($.browser.msie) {
                    if (!this.rangeSelection) {
                        //In IE10 Compatibility view, when call the focus too quickly, the iframe document is not loaded,
                        // the body will be null. So use the onreadystatechange to delay the focus.
                        if (doc.body) {
                            doc.body.focus();
                        } else {
                            doc.onreadystatechange = function () {
                                if (doc.readyState === "complete") {
                                    doc.body.focus();
                                }
                            };
                        }
                    } else {
                        this._setIESelection();
                    }
                } else {
                    win.focus();
                }
            };

            //end of focus related methods in ie.
            wijeditor.prototype._setFocusNotIE = function () {
                var self = this, win, body;
                if ($.browser.msie) {
                    return;
                }

                if (self._isEdge) {
                    self._setFocusForEdge();
                    return;
                }

                win = self._getDesignViewWindow();
                if ($.browser.mozilla) {
                    win.focus();
                    return;
                }

                body = win.document.body;

                //for chrome version has updated, the unittest failed
                if (body) {
                    body.focus();
                }
            };

            wijeditor.prototype._setFocusForEdge = function () {
                var self = this, body, scrollTop, scrollLeft;

                if (!self._isEdge) {
                    return;
                }

                body = $(self._getDesignViewWindow().document.body);
                if (!body.length) {
                    return;
                }

                scrollTop = body.scrollTop();
                scrollLeft = body.scrollLeft();
                body[0].focus();
                body.scrollTop(scrollTop).scrollLeft(scrollLeft);
            };

            wijeditor.prototype._createInputButton = function (className, text) {
                var attrs = { "class": className, "type": "button", "value": undefined };

                if (text) {
                    attrs.value = text;
                }

                return wijribbonDataRender.createElement("input", attrs);
            };

            wijeditor.prototype._createTextField = function (label, className, text, defaultValue) {
                var self = this, ele = wijribbonDataRender.createDiv(className), attrs = { type: "text", value: "", "aria-label": label };

                if (defaultValue) {
                    attrs.value = defaultValue;
                }

                ele.add(wijribbonDataRender.createSpan(css_dlg_text, label));
                ele.add(wijribbonDataRender.createElement("input", attrs));

                if (text) {
                    ele.add(new TextElement(text));
                }

                return ele;
            };

            wijeditor.prototype._createTextAreaField = function (label, className, defaultValue, text) {
                var ele = wijribbonDataRender.createDiv(className);

                ele.add(wijribbonDataRender.createSpan(css_dlg_text, label));
                ele.add(wijribbonDataRender.createElement("textarea", defaultValue));
                if (text) {
                    ele.add(new TextElement(text));
                }
                return ele;
            };

            wijeditor.prototype._createSeparator = function () {
                var self = this, hrdiv = wijribbonDataRender.createDiv(css_dlg_hr);

                hrdiv.add(wijribbonDataRender.createElement("hr"));

                return hrdiv;
            };

            wijeditor.prototype._createOKCancelButtons = function () {
                var self = this, buttons = wijribbonDataRender.createDiv(css_dlg_buttons);

                buttons.add(wijribbonDataRender.createElement("input", {
                    type: "button",
                    "class": css_dlg_button,
                    value: this.localizeString("dialogOK", "OK")
                }));
                buttons.add(wijribbonDataRender.createElement("input", {
                    type: "button",
                    "class": css_dlg_button,
                    engValue: "Cancel",
                    value: this.localizeString("dialogCancel", "Cancel")
                }));

                return buttons;
            };

            wijeditor.prototype._getDialogRes_Template = function () {
                var self = this, dialog = wijribbonDataRender.createDiv(css_tpldlg), topLabels = wijribbonDataRender.createDiv(css_tpl_labels), content = wijribbonDataRender.createDiv(css_tpl_content), tpllist = wijribbonDataRender.createDiv(css_tpl_list), preview = wijribbonDataRender.createDiv(css_tpl_preview), tplinfo = wijribbonDataRender.createDiv(css_tpl_tplinfo), namefield = wijribbonDataRender.createElement("div", this.localizeString("templateDialogName", "Name :")), desfield = wijribbonDataRender.createElement("div", this.localizeString("templateDialogDescription", "Description :")), fields = wijribbonDataRender.createDiv(css_tpl_fields), tplButtons = wijribbonDataRender.createDiv(css_tpl_buttons);

                topLabels.add(wijribbonDataRender.createElement("div", this.localizeString("templateDialogSelectTemplate", "Select Template:"), {
                    "class": css_tpl_tllabel
                }));
                topLabels.add(wijribbonDataRender.createElement("div", this.localizeString("templateDialogTemplatePreview", "Template Preview:"), {
                    "class": css_tpl_trlabel
                }));
                dialog.add(topLabels);

                tpllist.add(wijribbonDataRender.createElement("select", { size: 8, "aria-label": "Select Template" }));
                preview.add(wijribbonDataRender.createElement("iframe", { frameborder: 0 }));
                content.add(tpllist);
                content.add(preview);
                dialog.add(content);

                namefield.add(wijribbonDataRender.createSpan(css_tpl_nameinfo));
                desfield.add(wijribbonDataRender.createSpan(css_tpl_desinfo));
                tplinfo.add(namefield);
                tplinfo.add(desfield);
                dialog.add(tplinfo);

                fields.add(wijribbonDataRender.createSpan(css_dlg_text, this.localizeString("templateDialogName", "Name :")));
                fields.add(wijribbonDataRender.createTextBox(css_tpl_namefield, "", "Name"));
                fields.add(wijribbonDataRender.createSpan(css_dlg_text, this.localizeString("templateDialogDescription", "Description :")));
                fields.add(wijribbonDataRender.createTextBox(css_tpl_desfield, "", "Description"));
                dialog.add(fields);

                tplButtons.add(self._createInputButton(css_dlg_button + " " + css_tpl_delete, this.localizeString("templateDialogDeleteSelected", "Delete selected")));
                tplButtons.add(self._createInputButton(css_dlg_button + " " + css_tpl_save, this.localizeString("templateDialogSaveCurrentPage", "Save current page as template")));
                dialog.add(tplButtons);

                dialog.add(self._createSeparator());
                dialog.add(self._createOKCancelButtons());

                return dialog.render();
            };

            wijeditor.prototype._getDialogRes_ImageBrowser = function () {
                var self = this, dialog = wijribbonDataRender.createDiv(css_imgdlg), content = wijribbonDataRender.createDiv(css_imgdlg_content), fields = wijribbonDataRender.createDiv(css_imgdlg_fields), imgField = wijribbonDataRender.createDiv(css_imgdlg_field), imglist = wijribbonDataRender.createDiv(css_imgdlg_list), imgpreview = wijribbonDataRender.createDiv(css_imgdlg_preview);

                fields.add(self._createTextField(this.localizeString("imageEditorDialogImageSrc", "Image Src:"), css_imgdlg_url));
                fields.add(self._createTextField(this.localizeString("imageEditorDialogImageAltText", "Image alt text:"), css_imgdlg_alt));
                fields.add(self._createTextField(this.localizeString("imageEditorDialogImageWidth", "Image width:"), css_imgdlg_width, this.localizeString("dialogPixel", "px")));
                fields.add(self._createTextField(this.localizeString("imageEditorDialogImageHeight", "Image height:"), css_imgdlg_height, this.localizeString("dialogPixel", "px")));
                fields.add(self._createTextField(this.localizeString("imageEditorDialogCssText", "Css text:"), css_imgdlg_css));
                content.add(fields);

                imgField.add(imglist);
                imglist.add(wijribbonDataRender.createElement("select", { size: 8 }));
                imgField.add(imgpreview);
                imgpreview.add(wijribbonDataRender.createElement("img", { src: "", alt: "" }));
                content.add(imgField);

                content.add(self._createSeparator());
                content.add(self._createOKCancelButtons());

                dialog.add(content);

                return dialog.render();
            };

            wijeditor.prototype._getDialogRes_link_address = function () {
                return this._createTextField(this.localizeString("hyperLinkDialogAddress", "Address :"), css_linkdlg_address);
            };

            wijeditor.prototype._getDialogRes_link_linkType_options = function () {
                return [
                    {
                        id: "radUrl", value: "url",
                        text: this.localizeString("hyperLinkDialogUrl", "url")
                    }, {
                        id: "radAnchor", value: "anchor", checked: true,
                        text: this.localizeString("hyperLinkDialogAnchor", "anchor")
                    }, {
                        id: "radMail", value: "email",
                        text: this.localizeString("hyperLinkDialogEmail", "email")
                    }];
            };

            wijeditor.prototype._getDialogRes_link_linkType = function () {
                var linkType = wijribbonDataRender.createDiv(css_linkdlg_linktype + " ui-helper-clearfix"), linktypecontainer = wijribbonDataRender.createElement("div"), linkTypeOptions = [], idx;
                linkType.add(linktypecontainer);
                $.each(this._getDialogRes_link_linkType_options(), function (idx, radio) {
                    linktypecontainer.add(wijribbonDataRender.createRadio(radio.id, "radioList", radio.value));
                    linktypecontainer.add(wijribbonDataRender.createLabel(radio.text, radio.id));
                });

                for (idx = 1; idx < 8; idx++) {
                    linkTypeOptions.push("#anchor" + idx.toString());
                }
                linkType.add(wijribbonDataRender.createSelect(css_linkdlg_anchor, linkTypeOptions));

                return linkType;
            };

            wijeditor.prototype._getDialogRes_Link_linkIconType = function () {
                var linkIconTypeOuterContainer = wijribbonDataRender.createDiv(css_linkdlg_linkicontype), linkIconTypeContainer = wijribbonDataRender.createElement("div"), inconTypeSpan = wijribbonDataRender.createSpan(css_dlg_text, this.localizeString("hyperLinkDialogIconType", "Icon Type :")), linkIconType = [
                    {
                        id: "radLinkTypeIsText", value: "text",
                        checked: true, text: this.localizeString("hyperLinkDialogText", "text")
                    }, {
                        id: "radLinkTypeIsImage", value: "image",
                        text: this.localizeString("hyperLinkDialogImage", "image")
                    }];

                $.each(linkIconType, function (idx, radio) {
                    linkIconTypeContainer.add(wijribbonDataRender.createRadio(radio.id, "linkIconRadioList", radio.value));
                    linkIconTypeContainer.add(wijribbonDataRender.createLabel(radio.text, radio.id));
                });
                linkIconTypeOuterContainer.add(linkIconTypeContainer);
                linkIconTypeContainer.add(inconTypeSpan);
                return linkIconTypeOuterContainer;
            };

            wijeditor.prototype._getDialogRes_Link_text = function () {
                return this._createTextField(this.localizeString("hyperLinkDialogTextToDisplay", "Text to display :"), css_linkdlg_text);
            };

            wijeditor.prototype._getDialogRes_Link_image = function () {
                var imageContainer = wijribbonDataRender.createDiv(css_linkdlg_imagecontainer);
                imageContainer.add(this._createTextField(this.localizeString("imageEditorDialogImageSrc", "Image Src:"), css_linkdlg_url));
                imageContainer.add(this._createTextField(this.localizeString("imageEditorDialogImageWidth", "Image width:"), css_linkdlg_width, this.localizeString("dialogPixel", "px")));
                imageContainer.add(this._createTextField(this.localizeString("imageEditorDialogImageHeight", "Image height:"), css_linkdlg_height, this.localizeString("dialogPixel", "px")));
                return imageContainer;
            };

            wijeditor.prototype._getDialogRes_link_target = function () {
                var target = wijribbonDataRender.createDiv(css_linkdlg_target), targetSpan = wijribbonDataRender.createSpan(css_dlg_text, this.localizeString("hyperLinkDialogTarget", "Target :")), targetOption = [
                    { text: "_blank", selected: true },
                    "_parent", "_self", "_top"], targetSelect = wijribbonDataRender.createSelect(css_linkdlg_target, targetOption);
                target.add(targetSpan);
                target.add(targetSelect);
                return target;
            };

            wijeditor.prototype._getDialogRes_Link_Css = function () {
                return this._createTextField(this.localizeString("hyperLinkDialogCss", "Css :"), css_linkdlg_css);
            };

            wijeditor.prototype._getDialogRes_Link = function () {
                var self = this, dialog = wijribbonDataRender.createDiv(css_linkdlg);
                dialog.add(self._getDialogRes_link_address());
                dialog.add(self._getDialogRes_link_linkType());

                dialog.add(self._createSeparator());
                dialog.add(self._getDialogRes_Link_linkIconType());
                dialog.add(self._getDialogRes_Link_text());
                dialog.add(self._getDialogRes_Link_image());
                dialog.add(self._getDialogRes_link_target());

                dialog.add(self._getDialogRes_Link_Css());
                dialog.add(self._createSeparator());
                dialog.add(self._createOKCancelButtons());

                return dialog.render();
            };

            wijeditor.prototype._getDialogRes_TagInspector = function () {
                var self = this, taginsdlg = wijribbonDataRender.createDiv(css_taginsdlg), caption = wijribbonDataRender.createDiv(css_taginsdlg_caption), filterempty = wijribbonDataRender.createDiv(css_taginsdlg_filterempty), attribs = wijribbonDataRender.createDiv(css_taginsdlg_attribs), innerhtml = wijribbonDataRender.createDiv(css_taginsdlg_innerhtml);

                taginsdlg.add(caption);

                caption.add(wijribbonDataRender.createSpan(css_taginsdlg_taglabel, this.localizeString("tagInspectorDialogSelectedTag", "Selected tag :")));
                caption.add(wijribbonDataRender.createSpan(css_taginsdlg_tagtext, ""));

                taginsdlg.add(filterempty);
                filterempty.add(wijribbonDataRender.createCheckbox("displayNoEmpty"));
                filterempty.add(wijribbonDataRender.createLabel(this.localizeString("tagInspectorDialogDisplayNotEmptyAttributes", "Display not empty attributes only"), "displayNoEmpty"));

                taginsdlg.add(attribs);
                attribs.add(wijribbonDataRender.createSpan(css_dlg_text, this.localizeString("tagInspectorDialogAttributes", "Attributes:")));
                attribs.add(wijribbonDataRender.createDiv(css_taginsdlg_attriblist));

                taginsdlg.add(innerhtml);
                innerhtml.add(wijribbonDataRender.createSpan(css_dlg_text, this.localizeString("tagInspectorDialogInnerHTML", "Inner HTML:")));
                innerhtml.add(wijribbonDataRender.createElement("textarea", { "aria-label": "Inner HTML" }));

                taginsdlg.add(self._createTextField(this.localizeString("tagInspectorDialogCSSText", "Css Text:"), css_taginsdlg_css));
                taginsdlg.add(self._createSeparator());
                taginsdlg.add(self._createOKCancelButtons());

                return taginsdlg.render();
            };

            wijeditor.prototype._getDialogRes_Color = function () {
                return this._getDialogRes_CommonColor("#FFFFFF");
            };

            wijeditor.prototype._getDialogRes_ForeColor = function () {
                return this._getDialogRes_CommonColor("#000000");
            };

            wijeditor.prototype._getDialogRes_BackColor = function () {
                return this._getDialogRes_CommonColor("#FFFFFF");
            };

            wijeditor.prototype._getDialogRes_CommonColor = function (initColor) {
                var self = this, colordlg = wijribbonDataRender.createDiv(css_colordlg), color = wijribbonDataRender.createDiv(css_colordlg_color);

                colordlg.add(wijribbonDataRender.createDiv(css_colordlg_picker));
                colordlg.add(color);
                color.add(wijribbonDataRender.createSpan(css_dlg_text, this.localizeString("backColorDialogSelectedColor", "Selected Color:")));
                color.add(wijribbonDataRender.createElement("input", { type: "text", value: initColor, "aria-label": "Selected Color" }));

                colordlg.add(self._createSeparator());
                colordlg.add(self._createOKCancelButtons());

                return colordlg.render();
            };

            wijeditor.prototype._getDialogRes_Table = function () {
                var self = this, tbldlg = wijribbonDataRender.createDiv(css_tabledlg), bgcolor = wijribbonDataRender.createDiv(css_tabledlg_bgcolor);

                tbldlg.add(self._createTextField(this.localizeString("tableDialogRows", "Rows :"), css_tabledlg_rows, "", 3));
                tbldlg.add(self._createTextField(this.localizeString("tableDialogColumns", "Columns :"), css_tabledlg_columns, "", 3));
                tbldlg.add(self._createTextField(this.localizeString("tableDialogTableWidth", "Table Width :"), css_tabledlg_width, this.localizeString("tableDialogPixels", "pixels"), 200));
                tbldlg.add(self._createTextField(this.localizeString("tableDialogTableHeight", "Table Height :"), css_tabledlg_height, this.localizeString("tableDialogPixels", "pixels"), 200));
                tbldlg.add(self._createTextField(this.localizeString("tableDialogBorder", "Border thickness:"), css_tabledlg_border));
                tbldlg.add(self._createTextField(this.localizeString("tableDialogCellPadding", "Cell Padding :"), css_tabledlg_cellpadding));
                tbldlg.add(self._createTextField(this.localizeString("tableDialogCellSpacing", "Cell Spacing :"), css_tabledlg_cellspacing));
                tbldlg.add(self._createTextField(this.localizeString("tableDialogCssText", "Css Text :"), css_tabledlg_csstext));
                tbldlg.add(bgcolor);

                bgcolor.add(wijribbonDataRender.createSpan(css_dlg_text, this.localizeString("tableDialogBackgroundColor", "Background Color:")));
                bgcolor.add(wijribbonDataRender.createElement("input", { type: "text", "aria-label": "Background Color" }));
                bgcolor.add(wijribbonDataRender.createElement("input", { type: "button", value: "..." }));

                tbldlg.add(self._createSeparator());
                tbldlg.add(self._createOKCancelButtons());

                return tbldlg.render();
            };

            wijeditor.prototype._getDialogRes_Preview = function () {
                var self = this, previewdlg = wijribbonDataRender.createDiv(css_previewdlg), caption = wijribbonDataRender.createDiv(css_previewdlg_caption), buttons = wijribbonDataRender.createDiv(css_dlg_buttons), navigate = wijribbonDataRender.createDiv(css_previewdlg_navigator), previewFrame = wijribbonDataRender.createDiv(css_previewdlg_previewiframe);

                previewdlg.add(caption);
                caption.add(wijribbonDataRender.createSpan(css_dlg_text, this.localizeString("previewDialogPreviewSize", "Preview Size:")));
                caption.add(wijribbonDataRender.createElement("input", {
                    id: "rad640_480",
                    name: "preview",
                    type: "radio",
                    checked: "checked"
                }));
                caption.add(wijribbonDataRender.createLabel("640x480", "rad640_480"));
                caption.add(wijribbonDataRender.createElement("input", {
                    id: "rad800_600",
                    name: "preview",
                    type: "radio"
                }));
                caption.add(wijribbonDataRender.createLabel("800x600", "rad800_600"));
                caption.add(wijribbonDataRender.createElement("input", {
                    id: "rad1024_768",
                    name: "preview",
                    type: "radio"
                }));
                caption.add(wijribbonDataRender.createLabel("1024x768", "rad1024_768"));
                caption.add(wijribbonDataRender.createElement("input", {
                    id: "chkSplit",
                    type: "checkbox",
                    checked: "checked"
                }));
                caption.add(wijribbonDataRender.createLabel(this.localizeString("previewDialogSplit", "Split pages"), "chkSplit"));
                previewdlg.add(self._createSeparator());
                previewdlg.add(buttons);

                buttons.add(self._createInputButton(css_dlg_button + " " + css_previewdlg_printall, this.localizeString("previewDialogPrintAll", "Print All")));
                buttons.add(self._createInputButton(css_dlg_button + " " + css_previewdlg_printone, this.localizeString("previewDialogPrintPage", "Print Page")));
                buttons.add(self._createInputButton(css_dlg_button + " " + css_previewdlg_ok, this.localizeString("dialogOK", "OK")));

                previewdlg.add(self._createSeparator());
                previewdlg.add(navigate);
                navigate.add(wijribbonDataRender.createElement("a", this.localizeString("previewDialogPrevPage", "Prev page"), {
                    "class": css_previewdlg_prev,
                    href: "#"
                }));
                navigate.add(wijribbonDataRender.createElement("span", "1 / 1"));
                navigate.add(wijribbonDataRender.createElement("a", this.localizeString("previewDialogNextPage", "Next page"), {
                    "class": css_previewdlg_next,
                    href: "#"
                }));

                previewdlg.add(wijribbonDataRender.createDiv(css_previewdlg_printdocument));
                previewdlg.add(previewFrame);
                previewFrame.add(wijribbonDataRender.createElement("iframe", { src: "about:blank" }));

                return previewdlg.render();
            };

            wijeditor.prototype._getDialogRes_CleanUp = function () {
                var self = this, cleanupdlg = wijribbonDataRender.createDiv(css_cleanupdlg), caption = wijribbonDataRender.createDiv(css_cleanupdlg_caption), doc = wijribbonDataRender.createDiv(css_cleanupdlg_document), actions = wijribbonDataRender.createDiv(css_cleanupdlg_actions), actionsArr = [
                    {
                        id: "replaceSpans",
                        label: this.localizeString("cleanUpDialogStripSpanTag", "Strip SPAN tag")
                    },
                    {
                        id: "replaceClass",
                        label: this.localizeString("cleanUpDialogStripClass", "Strip CLASS tag")
                    },
                    {
                        id: "replaceStyle",
                        label: this.localizeString("cleanUpDialogStripStyle", "Strip STYLE attribute")
                    },
                    {
                        id: "replaceNbsp",
                        label: this.localizeString("cleanUpDialogReplaceSymbol", "Replace &amp;nbsp; symbol")
                    },
                    {
                        id: "transformPtoDiv",
                        label: this.localizeString("cleanUpDialogTransformParagraphToDIV", "Transform Paragraph to DIV")
                    }];

                cleanupdlg.add(caption);
                caption.add(wijribbonDataRender.createSpan(css_dlg_text, this.localizeString("cleanUpDialogDocumentSource", "Document source :")));

                cleanupdlg.add(doc);
                doc.add(wijribbonDataRender.createElement("textarea", { readonly: "readonly", "aria-label": "Document source" }));

                cleanupdlg.add(actions);
                $.each(actionsArr, function (i, act) {
                    actions.add(wijribbonDataRender.createCheckbox(act.id));
                    actions.add(wijribbonDataRender.createLabel(act.label, act.id));
                });

                cleanupdlg.add(self._createSeparator());
                cleanupdlg.add(self._createOKCancelButtons());

                return cleanupdlg.render();
            };

            wijeditor.prototype._getDialogRes_FindAndReplace = function () {
                var self = this, finddlg = wijribbonDataRender.createDiv(css_finddlg), find = wijribbonDataRender.createDiv(css_finddlg_find), replace = wijribbonDataRender.createDiv(css_finddlg_replace), buttons = wijribbonDataRender.createDiv(css_dlg_buttons);

                finddlg.add(find);
                find.add(wijribbonDataRender.createSpan(css_dlg_text, this.localizeString("findAndReplaceDialogFind", "Find:")));
                find.add(wijribbonDataRender.createElement("textarea", "text", { "aria-label": "Find" }));

                finddlg.add(replace);
                replace.add(wijribbonDataRender.createSpan(css_dlg_text, this.localizeString("findAndReplaceDialogReplace", "Replace:")));
                replace.add(wijribbonDataRender.createElement("textarea", "", { "aria-label": "Replace" }));

                finddlg.add(self._createSeparator());
                finddlg.add(buttons);
                buttons.add(self._createInputButton(css_dlg_button, this.localizeString("findAndReplaceDialogFindButton", "Find")));
                buttons.add(self._createInputButton(css_dlg_button, this.localizeString("findAndReplaceDialogReplaceButton", "Replace")));

                return finddlg.render();
            };

            wijeditor.prototype._getDialogRes_Media = function () {
                var self = this, meddlg = wijribbonDataRender.createDiv(css_mediadlg), type = wijribbonDataRender.createDiv(css_mediadlg_type);

                meddlg.add(type);
                type.add(wijribbonDataRender.createSpan(css_dlg_text, this.localizeString("mediaDialogMediaType", "Media Type :")));
                type.add(wijribbonDataRender.createSelect("", ["flash", "video", "applet", "other"]));

                meddlg.add(self._createTextField(this.localizeString("mediaDialogMediaUrl", "Media Url :"), css_mediadlg_url));
                meddlg.add(self._createTextField(this.localizeString("mediaDialogWidth", "Width :"), css_mediadlg_width, this.localizeString("dialogPixel", "px"), 200));
                meddlg.add(self._createTextField(this.localizeString("mediaDialogHeight", "Height :"), css_mediadlg_height, this.localizeString("dialogPixel", "px"), 200));
                meddlg.add(self._createSeparator());
                meddlg.add(self._createOKCancelButtons());

                return meddlg.render();
            };

            wijeditor.prototype._getDialogRes_SpecialCharacter = function () {
                var self = this, chardlg = wijribbonDataRender.createDiv(css_specialchardlg), chars = wijribbonDataRender.createDiv(css_specialchardlg_chars), preview = wijribbonDataRender.createDiv(css_specialchardlg_preview), content = wijribbonDataRender.createDiv(css_specialchardlg_content), list = wijribbonDataRender.createDiv(css_specialchardlg_list), punctuationLabel = wijribbonDataRender.createDiv(css_specialchardlg_label, "Punctuation"), punctuation = wijribbonDataRender.createDiv(css_specialchardlg_punctuation), punctuationArr = [
                    "&#8211;", "&#8212;", "&iexcl;", "&iquest;",
                    "&quot;", "&laquo;", "&raquo;", "&nbsp;"], symbolsLabel = wijribbonDataRender.createDiv(css_specialchardlg_label, "Symbols"), symbols = wijribbonDataRender.createDiv(css_specialchardlg_symbols), symbolsArr = [
                    "&amp;", "&cent;", "&copy;", "&divide;", "&gt;", "&lt;",
                    "&micro;", "&#8226;", "&para;", "&plusmn;",
                    "&#8364;", "&pound;", "&reg;", "&sect;", "&yen;"], diacriticsLabel = wijribbonDataRender.createDiv(css_specialchardlg_label, "Diacritics"), diacritics = wijribbonDataRender.createDiv(css_specialchardlg_diacritics), diacriticsArr = [
                    "&aacute;", "&Aacute;", "&agrave;", "&Agrave;",
                    "&acirc;", "&Acirc;", "&aring;", "&Aring;",
                    "&atilde;", "&Atilde;", "&auml;", "&Auml;",
                    "&aelig;", "&AElig;", "&ccedil;", "&Ccedil;",
                    "&eacute;", "&Eacute;", "&egrave;", "&Egrave;",
                    "&ecirc;", "&Ecirc;", "&euml;", "&Euml;",
                    "&iacute;", "&Iacute;", "&igrave;", "&Igrave;",
                    "&icirc;", "&Icirc;", "&iuml;", "&Iuml;",
                    "&ntilde;", "&Ntilde;", "&oacute;", "&Oacute;",
                    "&ograve;", "&Ograve;", "&ocirc;", "&Ocirc;",
                    "&oslash;", "&Oslash;", "&otilde;", "&Otilde;",
                    "&ouml;", "&Ouml;", "&uacute;", "&Uacute;",
                    "&ugrave;", "&Ugrave;", "&ucirc;", "&Ucirc;",
                    "&uuml;", "&Uuml;", "&szlig;", "&yuml;",
                    "&#8216;", "&#8217;"], buttons = wijribbonDataRender.createDiv(css_dlg_buttons);

                chardlg.add(chars);

                chars.add(preview);
                preview.add(content);
                content.add(wijribbonDataRender.createElement("span"));

                chars.add(list);
                list.add(punctuationLabel);
                punctuationLabel.add(punctuation);

                $.each(punctuationArr, function (i, n) {
                    punctuation.add(wijribbonDataRender.createLabel(n));
                });

                list.add(symbolsLabel);
                symbolsLabel.add(symbols);
                $.each(symbolsArr, function (i, n) {
                    symbols.add(wijribbonDataRender.createLabel(n));
                });

                list.add(diacriticsLabel);
                diacriticsLabel.add(diacritics);
                $.each(diacriticsArr, function (i, n) {
                    diacritics.add(wijribbonDataRender.createLabel(n));
                });

                chardlg.add(self._createSeparator());

                buttons.add(self._createInputButton(css_dlg_button, self.localizeString("dialogCancel", "Cancel")));
                chardlg.add(buttons);

                return chardlg.render();
            };

            wijeditor.prototype._copyFromClipboard = function () {
                if (wijWindow.clipboardData) {
                    return wijWindow.clipboardData.getData('Text');
                } else {
                    wijAlert(this.localizeString("errorMessagePasteError", "This function is not supported in current browser.  Plesse use (Ctrl + V)."));
                }
            };

            wijeditor.prototype._copyToClipboard = function (copyText, cut) {
                var self = this, doc = self._getDesignViewDocument();

                if (wijWindow.clipboardData && copyText) {
                    wijWindow.clipboardData.setData("Text", copyText);
                } else {
                    if (cut) {
                        wijAlert(self.localizeString("errorMessageCutError", "This function is not supported in current browser. Plesse use (Ctrl + X)."));
                    } else {
                        wijAlert(self.localizeString("errorMessageCopyError", "This function is not supported in current browser. Plesse use (Ctrl + C)."));
                    }
                }
            };

            /** @ignore */
            wijeditor.prototype.fixAbsoluteUrlsIfNeeded = function (html) {
                var self = this, sBaseDocUrl = wijDoc.URL, sBaseUrl = wijDoc.URL, sRootBaseUrl = wijDoc.URL, baseUrlFound = false, len = sBaseUrl.length, ret = html, ch, ch2, s1, r, s2, s3, i, pos;

                for (i = len - 1; i > 0; i--) {
                    ch = sBaseUrl.charAt(i);
                    ch2 = sBaseUrl.charAt(i - 1);

                    if (ch === '/' || ch === '\\') {
                        if (ch === ch2) {
                            break;
                        }

                        sRootBaseUrl = sBaseUrl.substring(0, i) + ch;

                        if (!baseUrlFound) {
                            sBaseUrl = sRootBaseUrl;
                            baseUrlFound = true;
                        }
                    }
                }

                s1 = self._prepareLiteralRegexText(sBaseDocUrl + '?');
                r = new RegExp(s1, 'g');
                ret = ret.replace(r, '?');

                s2 = self._prepareLiteralRegexText(sBaseUrl);
                r = new RegExp(s2, 'g');
                ret = ret.replace(r, '');

                s3 = self._prepareLiteralRegexText(sRootBaseUrl);
                r = new RegExp(s3, 'g');
                ret = ret.replace(r, '/');

                pos = ret.indexOf('#');

                if (pos > -1) {
                    ret = ret.substr(pos);
                }

                return ret;
            };

            wijeditor.prototype._insertCell = function (row, idx) {
                var newCell = row.insertCell(idx);

                newCell.innerHTML = '&nbsp;';

                return newCell;
            };

            wijeditor.prototype._getDictionaryDeclare = function () {
                var attrs = {};

                attrs.a = [
                    'accesskey', 'charset', 'class', 'coords', 'dir',
                    'href', 'hreflang', 'id', 'lang', 'name', 'rel',
                    'rev', 'shape', 'tabindex', 'target', 'title'];

                attrs.b = ['class', 'dir', 'id', 'lang', 'title'];

                attrs.body = [
                    'alink', 'background', 'bgColor', 'bgproperties',
                    'bottommargin', 'class', 'dir', 'id', 'lang',
                    'leftmargin', 'link', 'marginheight', 'marginwidth',
                    'rightmargin', 'text', 'title', 'topmargin', 'vlink'];

                attrs.button = [
                    'accesskey', 'class', 'dir', 'disabled', 'id',
                    'lang', 'name', 'tabindex', 'title', 'type', 'value'];

                attrs.code = ['class', 'dir', 'id', 'lang', 'title'];

                attrs.div = ['align', 'class', 'dir', 'id', 'lang', 'title'];

                attrs.em = ['class', 'dir', 'id', 'lang', 'title'];

                attrs.font = [
                    'class', 'color', 'dir', 'face', 'id',
                    'lang', 'pointsize', 'size', 'title'];

                attrs.form = [
                    'action', 'class', 'dir', 'enctype', 'id', 'lang',
                    'method', 'name', 'runat', 'target', 'title'];

                attrs.hr = [
                    'align', 'class', 'color', 'id', 'noshade',
                    'size', 'title', 'width'];

                attrs.i = ['class', 'dir', 'id', 'lang', 'title'];

                attrs.img = [
                    'align', 'alt', 'border', 'class', 'controls',
                    'dir', 'dynsrc', 'height', 'hspace', 'id', 'ismap',
                    'lang', 'longdesc', 'loop', 'lowsrc', 'name', 'src',
                    'start', 'title', 'usemap', 'vspace', 'width'];

                attrs.input = [
                    'accept', 'accesskey', 'align', 'alt', 'border',
                    'checked', 'class', 'dir', 'disabled', 'height',
                    'hspace', 'id', 'lang', 'maxlength', 'name',
                    'readonly', 'size', 'src', 'tabindex', 'title',
                    'type', 'usemap', 'value', 'vspace', 'width'];

                attrs.label = [
                    'accesskey', 'class', 'dir', 'for', 'id',
                    'lang', 'title'];

                attrs.li = ['class', 'dir', 'id', 'lang', 'title', 'type', 'value'];

                attrs.ol = [
                    'class', 'compact', 'dir', 'id', 'lang',
                    'start', 'title', 'type'];

                attrs.option = [
                    'class', 'dir', 'disabled', 'id', 'label',
                    'lang', 'selected', 'title', 'value'];

                attrs.p = ['align', 'class', 'dir', 'id', 'lang', 'title'];

                attrs.span = ['class', 'dir', 'id', 'lang', 'title'];

                attrs.strong = ['class', 'dir', 'id', 'lang', 'title'];

                attrs.select = [
                    'accesskey', 'class', 'dir', 'disabled', 'id', 'lang',
                    'multiple', 'name', 'size', 'tabindex', 'title'];

                attrs.table = [
                    'align', 'background', 'bgColor', 'border',
                    'bordercolor', 'bordercolordark', 'bordercolorlight',
                    'cellpadding', 'cellspacing', 'class', 'cols',
                    'datapagesize', 'dir', 'frame', 'height', 'hspace',
                    'id', 'lang', 'rules', 'summary', 'title', 'vspace', 'width'];

                attrs.td = [
                    'abbr', 'align', 'axis', 'background', 'bgColor',
                    'bordercolor', 'bordercolordark', 'bordercolorlight',
                    'class', 'colspan', 'dir', 'headers', 'height', 'id',
                    'lang', 'nowrap', 'rowspan', 'scope', 'title', 'valign', 'width'];

                attrs.th = [
                    'abbr', 'align', 'axis', 'background', 'bgColor', 'bordercolor',
                    'bordercolordark', 'bordercolorlight', 'class', 'colspan',
                    'dir', 'headers', 'height', 'id', 'lang', 'nowrap', 'rowspan',
                    'scope', 'title', 'valign', 'width'];

                attrs.tr = [
                    'align', 'bgColor', 'bordercolor', 'bordercolordark',
                    'bordercolorlight', 'class', 'dir', 'height', 'id',
                    'lang', 'nowrap', 'title', 'valign'];

                attrs.tbody = [
                    'align', 'bgColor', 'class', 'dir', 'id', 'lang',
                    'title', 'valign'];

                attrs.textarea = [
                    'accesskey', 'class', 'cols', 'dir', 'disabled',
                    'id', 'label', 'lang', 'name', 'readonly', 'rows',
                    'tabindex', 'title', 'wrap'];

                attrs.u = ['class', 'id', 'xml:lang'];

                attrs.ul = ['class', 'compact', 'dir', 'id', 'lang', 'title', 'type'];

                return attrs;
            };

            wijeditor.prototype._generateUniqueName = function (prefix) {
                var idx = uniqueIds[prefix];

                if (!idx) {
                    idx = 0;
                }

                uniqueIds[prefix] = ++idx;

                return prefix + idx;
            };

            wijeditor.prototype._setContentEditable = function (doc, isEditable) {
                var designMode = "designMode", contentEditable = "contentEditable";

                try  {
                    if (doc.body[contentEditable]) {
                        doc.body[contentEditable] = isEditable.toString();
                    }

                    if (doc[designMode]) {
                        if (!isEditable && doc[designMode] !== 'off') {
                            doc[designMode] = 'off';
                        } else if (isEditable && doc[designMode] !== 'on') {
                            //update for ie9 can't select the content after scroll.
                            //fix the original content will be clear if setting designmode to on in ie10.
                            if (!($.browser.msie && wijParseInt($.browser.version) >= 9 && wijParseInt($.browser.version) < 11)) {
                                doc[designMode] = 'on';
                            }
                        }
                    }

                    if (isEditable && !$.browser.msie) {
                        doc.execCommand('useCSS', false, true);
                    }
                } catch (e) {
                }
            };

            wijeditor.prototype._setContentSpellCheck = function (doc, isSpellCheck) {
                var spellcheck = "spellcheck";
                try  {
                    if (doc.body[spellcheck] !== undefined) {
                        doc.body[spellcheck] = isSpellCheck;
                    }
                } catch (e) {
                }
            };

            wijeditor.prototype._formatString = function (str, len) {
                var strLen = str.length, i;

                for (i = 0; i < len - strLen; i++) {
                    str = '0' + str;
                }

                return str;
            };

            wijeditor.prototype._convertToWebColor = function (r, g, b) {
                var self = this, hr, hg, hb, result;

                if (isNaN(r) || 255 - r < 0) {
                    r = 0;
                }

                if (isNaN(g) || 255 - g < 0) {
                    g = 0;
                }

                if (isNaN(b) || 255 - b < 0) {
                    b = 0;
                }

                hr = self._formatString(wijParseInt(r).toString(16), 2);
                hg = self._formatString(wijParseInt(g).toString(16), 2);
                hb = self._formatString(wijParseInt(b).toString(16), 2);
                result = '#' + hr + hg + hb;

                return result;
            };

            wijeditor.prototype._prepareLiteralRegexText = function (s1) {
                var ret = s1;

                ret = ret.replace(/\\/g, '\\\\');
                ret = ret.replace(/\./g, '\\.');
                ret = ret.replace(/\?/g, '\\?');

                return ret;
            };

            wijeditor.prototype._isNumeric = function (str) {
                return new RegExp('^\\d+$').test(str);
            };

            wijeditor.prototype._isEmail = function (str) {
                return new RegExp('mailto:(\\S)+[@]{1}(\\S)+[.]{1}(\\w)+').test(str);
            };

            wijeditor.prototype._isUrl = function (str) {
                return new RegExp('[a-zA-z]+://[^s]+').test(str);
            };

            wijeditor.prototype._isAnchor = function (str) {
                if (new RegExp('#[^s]+').test(str)) {
                    return true;
                } else if (new RegExp('[a-zA-z]+://[^s]+#[^s]+').test(str)) {
                    return true;
                } else {
                    return false;
                }
            };

            /** Adjust the editor layout.*/
            wijeditor.prototype.refresh = function () {
                var self = this, doc = self._getDesignViewDocument(), element = self.element, header = self._getHeader(), footer = self._getFooter(), headerHeight = header.outerHeight(true), footerHeight = footer.outerHeight(true), width = self._oriEleWidth, height = self._oriEleHeight, content = self._getContent(), contentHeight;

                self.editor.width(width).height(height);

                this.$ribbon.wijribbon("updateRibbonSize");

                // the ribbon has not resized completed, so can't get
                // the correct header width, get the updated height when the element is visible.
                window.setTimeout(function () {
                    if (self.editor.is(":visible")) {
                        headerHeight = header.outerHeight(true);
                        footerHeight = footer.outerHeight(true);
                    }
                    contentHeight = self.editor.height() - headerHeight - footerHeight;
                    content.height(contentHeight);
                    if (content.data("wijmo-wijsplitter")) {
                        if (self.options.editorMode === "split") {
                            content.wijsplitter("option", "splitterDistance", contentHeight / 2);
                        } else {
                            content.wijsplitter("refresh");
                        }
                    }
                }, 0);

                self._updateContentEditable();
            };

            /** Gets the text displayed in the editor.*/
            wijeditor.prototype.getText = function () {
                var self = this;

                return self._getDesignViewText();
            };

            /** Sets the text to display in the editor.
            * @remarks
            *   You can use the example code in a click function linked to a button,
            *   and replace any existing text in the editor with your text.
            * @param {string} text The text to show in the editor.
            */
            wijeditor.prototype.setText = function (text) {
                var self = this;

                if (text) {
                    self._setDesignViewText(text);
                    self.sourceView.val(text);
                }
            };

            /** @ignore */
            wijeditor.prototype.localizeString = function (key, defaultValue) {
                var o = this.options;
                if (o.localization && o.localization[key]) {
                    return o.localization[key];
                }
                return defaultValue;
            };

            //end of public method
            /** dom operation*/
            wijeditor.prototype._getParentElement = function (contentWin) {
                var self = this, range = self._getRange(contentWin), selection, startContainer, endContainer, startOffset, endOffset;

                if (!range) {
                    return null;
                }

                if (range.commonAncestorContainer) {
                    selection = contentWin.getSelection();
                    startContainer = range.startContainer || selection.baseNode;
                    endContainer = range.endContainer || selection.extentNode;
                    startOffset = range.startOffset;

                    if (startOffset === null) {
                        startOffset = selection.baseOffset;
                    }

                    endOffset = range.endOffset;

                    if (endOffset === null) {
                        endOffset = selection.extentOffset;
                    }

                    if (startContainer === endContainer && (endOffset - startOffset) === 1) {
                        return selection.anchorNode.childNodes[selection.anchorOffset];
                    }

                    if (!range.commonAncestorContainer.tagName) {
                        if (contentWin.document === range.commonAncestorContainer && selection.baseNode) {
                            return selection.baseNode.parentNode;
                        }

                        return range.commonAncestorContainer.parentNode;
                    }

                    return range.commonAncestorContainer;
                }

                if (range.length) {
                    return range.item(0);
                }

                if (range.parentElement) {
                    return range.parentElement();
                }

                return null;
            };

            wijeditor.prototype._getRange = function (contentWin) {
                var selection, range;

                if (contentWin.document.selection && !wijWindow.opera) {
                    return contentWin.document.selection.createRange();
                }

                if (contentWin.getSelection) {
                    selection = contentWin.getSelection();
                    if (!selection || selection.rangeCount < 1) {
                        return null;
                    }

                    if (selection.getRangeAt) {
                        range = selection.getRangeAt(0);
                    } else {
                        range = contentWin.document.createRange();
                    }

                    return range;
                }
            };

            //gets inspect element.
            wijeditor.prototype._getInspectElement = function () {
                return inspectElement || this._getSelectedElement();
            };

            wijeditor.prototype._getSelectedElement = function () {
                return this._getParentElement(this._getDesignViewWindow());
            };

            //end of gets inspect element.
            wijeditor.prototype._checkSelectionIncludeNodeForIE11AndChrome = function (win, range, nodeEle) {
                var doc = win.document, newRange;
                if (range) {
                    newRange = doc.createRange();
                    newRange.selectNode(nodeEle);
                    if (range.compareBoundaryPoints(Range.START_TO_END, newRange) <= 0 || range.compareBoundaryPoints(Range.END_TO_START, newRange) >= 0) {
                        return false;
                    }
                }
                return true;
            };

            wijeditor.prototype._checkSelectionIncludeNodeExceptIE11 = function (win, range, nodeEle) {
                var doc = win.document, newRange = doc.selection.createRange(), cep = "compareEndPoints";

                if (range) {
                    newRange.moveToElementText(nodeEle);

                    if (range.inRange(newRange) || (range[cep]('StartToStart', newRange) >= 0 && range[cep]('StartToEnd', newRange) <= 0) || (range[cep]('EndToStart', newRange) >= 0 && range[cep]('EndToEnd', newRange) <= 0)) {
                        return true;
                    }
                }

                return false;
            };

            wijeditor.prototype._getIESelectionRange = function () {
                var self = this, win = this._getDesignViewWindow(), doc = win.document, selection, range;

                if (self._isIE11) {
                    selection = win.getSelection();
                    if (selection && selection.rangeCount > 0) {
                        range = selection.getRangeAt(0);
                    }
                } else {
                    range = doc.selection.createRange();
                }
                return range;
            };

            //focus related methods in ie.
            wijeditor.prototype._setIESelection = function (range, notUseDefaultValue) {
                var doc;

                if (!$.browser.msie) {
                    return;
                }

                if (!range && !notUseDefaultValue) {
                    range = this.rangeSelection;
                }

                if (range) {
                    try  {
                        doc = this._getDesignViewDocument();
                        if (this._isIE11 && doc.getSelection) {
                            doc.getSelection().addRange(range);
                        } else {
                            range.select();
                        }
                    } catch (e) {
                        doc.body.focus();
                    }
                }
            };

            //get selected content.
            wijeditor.prototype._getSelectedContent = function (isText) {
                var win = this._getDesignViewWindow(), doc = win.document, selectedContent = "", cloneContents = "cloneContents", range, contents, helperDiv;

                if (!doc.selection) {
                    range = win.getSelection().getRangeAt(0);

                    if (range) {
                        if (range[cloneContents]) {
                            contents = range[cloneContents]();
                            helperDiv = document.createElement('div');
                            helperDiv.appendChild(contents);
                            selectedContent = isText ? $(helperDiv).text() : helperDiv.innerHTML;
                            helperDiv = null;
                        }
                    }
                } else {
                    range = doc.selection.createRange();
                    return isText ? range.text : range.htmlText;
                }

                return selectedContent || "";
            };

            //end of get selected content.
            wijeditor.prototype._getHtmlTextInIE = function (doc) {
                if (!$.browser.msie || !doc) {
                    return "";
                }
                var htmlText = "", selection;

                if (this._isIE11 && doc.getSelection) {
                    selection = doc.getSelection();
                    htmlText = selection.getRangeAt && selection.rangeCount ? selection.getRangeAt(0).toString() : "";
                } else {
                    htmlText = doc.selection.createRange().htmlText;
                }
                return htmlText;
            };

            wijeditor.prototype._saveSelectionForIE = function () {
                var doc = this._getDesignViewWindow().document, selection, selectionElement, range;
                if (!$.browser.msie)
                    return;
                if (this._isIE11 && doc.getSelection) {
                    selection = doc.getSelection();
                    this.rangeSelection = selection.getRangeAt && selection.rangeCount ? selection.getRangeAt(0) : null;
                    return;
                }
                selection = doc.selection;
                range = selection.createRange();
                if ($.browser.version && parseFloat($.browser.version) >= 9 && parseFloat($.browser.version) <= 10 && range.parentElement) {
                    selectionElement = range.parentElement();
                    if (selectionElement && selectionElement.tagName == "INPUT" && selectionElement.type == "hidden") {
                        return;
                    }
                }
                this.rangeSelection = range;
            };

            wijeditor.prototype._storeSelectionForIE = function () {
                var doc = this._getDesignViewWindow().document, range, preSelectionRange, start, startContainerText;

                if (!$.browser.msie) {
                    return;
                }

                if (doc.selection) {
                    range = doc.selection.createRange();
                    if (range.getBookmark) {
                        this.bookmark = range.getBookmark();
                    }
                } else if (doc.getSelection) {
                    if (doc.getSelection().rangeCount) {
                        range = doc.getSelection().getRangeAt(0);
                        preSelectionRange = range.cloneRange();
                        preSelectionRange.selectNode(doc.body);
                        preSelectionRange.setEnd(range.startContainer, range.startOffset);
                        start = preSelectionRange.toString().length;

                        // If the startContainer is text node, store the text value,  else, store the innerHTML.
                        if (range.startContainer.nodeType === 3) {
                            startContainerText = range.startContainer.nodeValue;
                        } else {
                            startContainerText = range.startContainer.innerHTML;
                        }
                        this.bookmark = {
                            startContainerText: startContainerText,
                            start: start,
                            end: start + range.toString().length
                        };
                    }
                }
            };

            wijeditor.prototype._restoreSelectionForIE = function (checkMoveToBookmark) {
                var _this = this;
                var win = this._getDesignViewWindow(), doc = win.document, foundStartContainer = false, moveToBookmarkInterval, moveToBookmarkCounter = 0, moveToBookmarkSuccess, range, start, startContainerText, nodeStack, isStop, node, charIndex, nextCharIndex, foundStart, end, sel, i;
                if (!this.bookmark || !$.browser.msie) {
                    return;
                }

                if (doc.selection) {
                    if (checkMoveToBookmark) {
                        moveToBookmarkInterval = setInterval(function () {
                            moveToBookmarkCounter++;
                            if (moveToBookmarkCounter > 5 || moveToBookmarkSuccess) {
                                range.select();
                                _this.bookmark = null;
                                clearInterval(moveToBookmarkInterval);
                            } else {
                                range = doc.body.createTextRange();
                                moveToBookmarkSuccess = range.moveToBookmark(_this.bookmark);
                            }
                        }, 50);
                    } else {
                        range = doc.body.createTextRange();
                        if (range.moveToBookmark(this.bookmark)) {
                            range.select();
                        }
                        this.bookmark = null;
                    }
                } else if (doc.getSelection) {
                    start = this.bookmark.start;
                    end = this.bookmark.end;
                    startContainerText = this.bookmark.startContainerText;
                    range = doc.createRange();
                    range.setStart(doc.body, 0);
                    nodeStack = [doc.body];
                    charIndex = 0;
                    while (!isStop && (node = nodeStack.pop())) {
                        if (node.nodeType == 3) {
                            nextCharIndex = charIndex + node.length;
                            if (!foundStart && (foundStartContainer || node.nodeValue === startContainerText) && start >= charIndex && start <= nextCharIndex) {
                                range.setStart(node, start - charIndex);
                                foundStart = true;
                            }
                            if (foundStart && end >= charIndex && end <= nextCharIndex) {
                                range.setEnd(node, end - charIndex);
                                isStop = true;
                            }
                            charIndex = nextCharIndex;
                        } else {
                            // if the stored startContainer is not textNode, here to find the startContainer.
                            if (node.innerHTML === startContainerText) {
                                foundStartContainer = true;
                            }
                            i = node.childNodes.length;
                            while (i--) {
                                nodeStack.push(node.childNodes[i]);
                            }
                        }
                    }

                    sel = win.getSelection();
                    sel.removeAllRanges();
                    sel.addRange(range);
                    this.rangeSelection = null;
                    this.bookmark = null;
                }
            };

            wijeditor.prototype._setSelection = function ($nodes, start, length) {
                var win = this._getDesignViewWindow(), doc = win.document, range, startNode, endNode, selection, len = 0;

                try  {
                    if (window.getSelection) {
                        selection = win.getSelection();
                        range = doc.createRange();
                        startNode = $nodes[0][0];
                        endNode = $nodes[$nodes.length - 1][0];
                        range.setStart(startNode, 0);
                        range.setEnd(endNode, endNode.childNodes.length);

                        selection.removeAllRanges();
                        selection.addRange(range);
                    } else {
                        range = doc.selection.createRange();

                        if ($nodes) {
                            $.each($nodes, function (idx, $node) {
                                len += $node.text().length;
                            });

                            range.moveToElementText($nodes[0][0]);
                            range.collapse(true);
                            range.moveEnd("character", len);
                        } else {
                            range.moveStart("textedit", -1);
                            range.collapse(true);
                            range.moveStart("character", start);
                            range.moveEnd("character", length);
                        }

                        range.select();
                    }
                } catch (e) {
                }
            };

            wijeditor.prototype._getHyperLinkElement = function (inspElem) {
                while (inspElem && inspElem.tagName !== 'A') {
                    if (inspElem.tagName === 'BODY' || inspElem.tagName === 'HTML') {
                        break;
                    }
                    inspElem = inspElem.parentElement;
                }
                return inspElem;
            };
            return wijeditor;
        })(wijmo.wijmoWidget);
        editor.wijeditor = wijeditor;

        var wijeditor_options = (function () {
            function wijeditor_options() {
                /** Selector option for auto self initialization. This option is internal.
                * @ignore
                */
                this.initSelector = ":jqmData(role='wijeditor')";
                /** Set to the selector that returns the container to fill when the user
                *   selects full screen mode.By default, it fills the client's area on the web page.
                * @remarks
                *       Once set , you can refer to this string in the ID attribute of the container,
                *       for example < div id = "container" > < / div >.
                */
                this.fullScreenContainerSelector = "";
                /**  If the compactMode option is true and ribbon is not simple,it will show
                *   compact ribbon although the editor is full width.
                */
                this.compactRibbonMode = false;
                /** Set the type of editor to show initially.
                * @remarks
                *       It has three options: wysiwyg/code/split.
                *         wysiwyg -- A visual designer with toolbar buttons that allow you to format text.
                *         code -- A code view of the text that allows you to edit the HTML formatting.
                *         split -- A horizontally split editor with the visual designer in the top pane
                *                   and the code view in the bottom.In this mode, the user can resize the panes by
                *                   dragging the horizontal bar separating them up or down.
                */
                this.editorMode = "wysiwyg";
                /** Set this option to true to show the editor in full screen mode when the page is first opened.
                * @remarks
                *       The editor fills the client area of the page(or the container specified in the fullScreenContainerSelector option).
                *       Note that this only sets the initial mode.The user can still toggle fullScreenMode off
                *       using the button at the bottom right of the editor.
                */
                this.fullScreenMode = false;
                /**
                * The fontSizes option specifies the list of font size
                * which will be shown in the font size drop down list.
                * Use the option to customize font sizes.
                * @remarks
                * Each item includes:
                * tip: the dropdown item’s tip.
                * name: the really fontsize's value that apply.
                * text: the font size text that show on dropdown item.
                *   the default value is:
                *         [{
                *                tip: "VerySmall",
                *                name: "xx-small",
                *                text: "VerySmall"
                *            }, {
                *                tip: "Smaller",
                *                name: "x-small",
                *                text: "Smaller"
                *            }, {
                *                tip: "Small",
                *                name: "small",
                *                text: "Small"
                *            }, {
                *                tip: "Medium",
                *                name: "medium",
                *                text: "Medium"
                *            }, {
                *                tip: "Large",
                *                name: "large",
                *                text: "Large"
                *            }, {
                *                tip: "Larger",
                *                name: "x-large",
                *                text: "Larger"
                *            }, {
                *                tip: "VeryLarge",
                *                name: "xx-large",
                *                text: "VeryLarge"
                *            }]
                *
                * Note: The following Font size’ value is built-in font size, and
                * please refer https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#the-fontsize-command
                *     1: x-small
                *     2: small
                *     3: medium
                *     4: large
                *     5: x-large
                *     6: xx-large
                *     7: xxx-large
                * Except these values, user can set the "pt" and "px" value to "name".
                */
                this.fontSizes = [
                    {
                        tip: "VerySmall",
                        name: "xx-small",
                        text: "VerySmall"
                    }, {
                        tip: "Smaller",
                        name: "x-small",
                        text: "Smaller"
                    }, {
                        tip: "Small",
                        name: "small",
                        text: "Small"
                    }, {
                        tip: "Medium",
                        name: "medium",
                        text: "Medium"
                    }, {
                        tip: "Large",
                        name: "large",
                        text: "Large"
                    }, {
                        tip: "Larger",
                        name: "x-large",
                        text: "Larger"
                    }, {
                        tip: "VeryLarge",
                        name: "xx-large",
                        text: "VeryLarge"
                    }];
                /**
                * The fontNames option specifies the list of font name
                * which will be shown in the font name drop down list.
                * Use the option to customize font names.
                * @remarks
                * Each item includes:
                * tip: the dropdown item’s tip.
                * name: the really fontname's value that apply.
                * text: the font name text that show on dropdown item.
                *   the default value is:
                *           [{
                *                tip: "Arial",
                *                 name: "fn1",
                *             text: "Arial"
                *           }, {
                *              tip: "Courier New",
                *                name: "fn2",
                *                text: "Courier New"
                *            }, {
                *                tip: "Garamond",
                *                name: "fn3",
                *                text: "Garamond"
                *            }, {
                *                tip: "Tahoma",
                *                name: "fn4",
                *                text: "Tahoma"
                *            }, {
                *                tip: "Times New Roman",
                *                name: "fn5",
                *                text: "Times New Roman"
                *            }, {
                *                tip: "Verdana",
                *                name: "fn6",
                *                text: "Verdana"
                *            }, {
                *                tip: "Wingdings",
                *                name: "fn7",
                *                text: "Wingdings"
                *            }]
                * Note: The "fn1, fn2,..., fn7" are wijmo built-in font size, indicate the safe web font family,
                * user can set others font family like css.
                */
                this.fontNames = [
                    {
                        tip: "Arial",
                        name: "fn1",
                        text: "Arial"
                    }, {
                        tip: "Courier New",
                        name: "fn2",
                        text: "Courier New"
                    }, {
                        tip: "Garamond",
                        name: "fn3",
                        text: "Garamond"
                    }, {
                        tip: "Tahoma",
                        name: "fn4",
                        text: "Tahoma"
                    }, {
                        tip: "Times New Roman",
                        name: "fn5",
                        text: "Times New Roman"
                    }, {
                        tip: "Verdana",
                        name: "fn6",
                        text: "Verdana"
                    }, {
                        tip: "Wingdings",
                        name: "fn7",
                        text: "Wingdings"
                    }];
                /** Select whether to show the path selector in the left side of the footer.
                * @remarks
                *       When you click in the content of the design view, the path selector shows HTML tags
                *       indicating where you are in the source view.If you set showFooter to false, this option is ignored.
                */
                this.showPathSelector = true;
                /** Specify which toolbar to render. Ribbon and simple modes allow you to customize the toolbar.
                * @remarks
                *       For more information on customizing the toolbar,
                *       see editor samples "Customize" and "Customize Simple."
                *       ribbon -- Includes the most commonly used tool buttons.
                *       simple -- Includes fewer buttons, is much smaller, and takes up less space.
                *        bbcode -- Includes buttons used with Bulletin Board Code,
                *                   a markup language used to format posts in message boards.
                */
                this.mode = "ribbon";
                /** Occurs when the command button is clicked.
                * @event
                * @dataKey {string} commandName The command name of the button.
                * @dataKey {string} name The parent name of the button which means
                *                      if the drop down item is clicked, then the name specifies the command name of the drop down button.
                */
                this.commandButtonClick = null;
                /** Specify an array of commands to display in customizing the simple toolbar.
                * @remarks
                *       Note that you must specify every command that you want to display,
                *       as these commands are used in place of the default commands.Therefore,
                *       the sample code shown below would only render two commands in the toolbar.
                *       The simple mode commands displayed by default are:
                *       "BlockQuote", "Bold", "BulletedList", "InsertCode", "InsertDate", "InsertImage",
                *       "Italic", "Link", "NumberedList", "NumberedList"
                *       Note: The buildin simple commands support the following commands:
                *       "Form","Image","TextArea","Button","TextBox","List","DropDownList",
                *       "HiddenField","Radio","CheckBox","JustifyLeft,"JustifyCenter",
                *       "JustifyRight","JustifyFull","Border","NumberedList","BulletedList",
                *       "Outdent","Indent","BackColor","ForeColor","Bold","Italic","UnderLine",
                *       "SubScript","SuperScript","Template","RemoveFormat","InsertBreak",
                *       "InsertParagraph","InsertPrint","InsertHR","Undo","Redo","Preview","Cleanup",
                *       "Cut","Copy","Paste","SelectAll","Media","InsertSpecialChar","InsertDate","Find",
                *       "Inspect","InsertImage","Link","FontName","FontSize","BlockQuote","InsertCode"
                *       The default simple mode commands are:
                *       ["Bold", "Italic", "Link", "BlockQuote",
                *       "StrikeThrough", "InsertDate", "InsertImage",
                *       "NumberedList", "BulletedList", "InsertCode"]
                * @example
                *        $("#wijeditor").wijeditor({
                *            mode: "simple",
                *            simpleModeCommands: ["Bold","Undo"]
                *         });
                */
                this.simpleModeCommands = null;
                /** Specify whether to show the footer at the bottom of the editor,
                *   where users can toggle full screen mode, word wrap, and view mode.
                * @remarks
                *       When you are in design view, the footer also displays the path selector,
                *       HTML tags showing your location in source view.
                */
                this.showFooter = true;
                /** Determines whether the custom context menu is shown.
                * @remarks
                *       Instead of the standard context menu items shown by the browser,
                *       the custom context menu has only three commands:
                *        Cut, Copy, and Paste.Note that the context menu is invalid in Safari.
                */
                this.customContextMenu = true;
                /** Set the text that appears in the editor.
                * @type {string}
                * @remarks
                *       Note that this overrides any text that you add in tags
                *       inside the textarea object that displays the widget.
                *       You can use HTML(or BBCode markup if you set the mode to bbcode) inside the string.
                */
                this.text = null;
                /** Occurs when the text changed.
                * @event
                * @dataKey {String} text The text of the editor.
                */
                this.textChanged = null;
                /** Use the localization option in order to localize text which not depends on culture.
                * @default {
                *       // tab names
                *       insertTab:               "Insert",
                *       formatTab:               "Format",
                *
                *       // group Names
                *       specialGroup:            "Special",
                *       formsGroup:              "Forms",
                *       breaksGroup:             "Breaks",
                *       tablesGroup:             "Tables",
                *       reviewGroup:             "Review",
                *       paragraphGroup:          "Paragraph",
                *       fontGroup:               "Font",
                *       actionsGroup:            "Actions",
                *
                *       // context Menu
                *       contextMenuCut:          "Cut",
                *       contextMenuCopy:         "Copy",
                *       contextMenuPaste:        "Paste",
                *
                *       // buttons
                *       formButtonTip:              "Form",
                *       imagebuttonButtonTip:       "Image Button",
                *       textareaButtonTip:          "TextArea",
                *       fontnameButtonTip:          "Font Name",
                *       fontnameButtonText:         "Font Name",
                *       fontsizeButtonTip:          "Font Size",
                *       fontsizeButtonText:         "Font Size",
                *       buttonButtonTip:            "Button",
                *       textboxButtonTip:           "TextBox",
                *       listButtonTip:              "ListBox",
                *       passwordfieldButtonTip:     "Password Field",
                *       dropdownlistButtonTip:      "DropDownList",
                *       hiddenfieldButtonTip:       "Hidden Field",
                *       radioButtonTip:             "RadioButton",
                *       checkboxButtonTip:          "CheckBox",
                *       insertcolButtonTip:         "Insert Column",
                *       insertrowButtonTip:         "Insert Row",
                *       insertcellButtonTip:        "Insert Cell",
                *       splitcellButtonTip:         "Split Cell",
                *       mergecellButtonTip:         "Merge Cell",
                *       deletecolButtonTip:         "Delete Column",
                *       deleterowButtonTip:         "Delete Row",
                *       deletecellButtonTip:        "Delete Cell",
                *       justifyleftButtonTip:       "Justify Left",
                *       justifycenterButtonTip:     "Justify Center",
                *       justifyrightButtonTip:      "Justify Right",
                *       justifyfullButtonTip:       "Justify Full",
                *       bordersButtonTip:           "Border",
                *       insertorderedlistButtonTip: "Numbered List",
                *       insertunorderedlistButtonTip:"Bulleted List",
                *       outdentButtonTip:            "Outdent",
                *       indentButtonTip:             "Indent",
                *       backcolorButtonTip:          "Background Color",
                *       fontcolorButtonTip:          "Font Color",
                *       boldButtonTip:               "Bold",
                *       italicButtonTip:             "Italic",
                *       strikethroughButtonTip:      "Strikethrough",
                *       underlineButtonTip:          "Underline",
                *       subscriptButtonTip:          "Subscript",
                *       superscriptButtonTip:        "Superscript",
                *       templateButtonTip:           "Template",
                *       removeformatButtonTip:       "RemoveFormat",
                *       insertbreakButtonTip:        "Insert Break",
                *       insertparagraphButtonTip:     "Insert Paragraph",
                *       insertprintpagebreakButtonTip: "Insert Print Page Break",
                *       inserthorizontalruleButtonTip: "Insert Horizontal Line",
                *       wysiwygButtonTip:              "Design View",
                *       splitButtonTip:                 "Split View",
                *       codeButtonTip:                  "Source View",
                *       wordwrapButtonTip:              "Wordwrap",
                *       fullscreenButtonTip:            "Fullscreen",
                *       undoButtonTip:                  "Undo",
                *       redoButtonTip:                  "Redo",
                *       previewButtonTip:               "Preview",
                *       cleanupButtonTip:               "Clean up",
                *       cutButtonTip:                   "Cut",
                *       copyButtonTip:                  "Copy",
                *       pasteButtonTip:                 "Paste",
                *       selectallButtonTip:             "Select All",
                *       mediaButtonTip:                  "Media",
                *       specialcharButtonTip:            "Insert Special Character",
                *       datetimeButtonTip:               "Insert Date Time",
                *       findButtonTip:                   "Find And Replace",
                *       findButtonText:                  "Find",
                *       inspectButtonTip:                "Tag Inspect",
                *       inspectButtonText:               "Inspect",
                *       saveButtonText:                  "Save",
                *       saveButtonTip:                   "Save",
                *       imagebrowserButtonTip:           "Image Browser",
                *       linkButtonTip:                   "Link",
                *       linkButtonText:                  "Link",
                *       blockquoteButtonTip:             "Block Quote",
                *       insertcodeButtonTip:             "Insert Code",
                *
                *       // table button
                *       tableButtonTip: "Table",
                *       tableButtonText: "Table",
                *       insertTableButtonTip:       "Insert Table",
                *       insertTableButtonText:      "Insert",
                *       editTableButtonTip:         "Edit Table",
                *       editTableButtonText:        "Edit",
                *
                *       // error message
                *       errorMessageCutError:		            "This function is not supported in current browser.  Plesse use (Ctrl + X).",
                *       errorMessageCopyError:  	            "This function is not supported in current browser. Plesse use (Ctrl + C).",
                *       errorMessagePasteError:	                "This function is not supported in current browser. Plesse use (Ctrl + V).",
                *       errorMessageTemplateNameError:	        "Please input a template name!",
                *       errorMessageTemplateFileError:	        "Please select a template file.",
                *       errorMessageValidTemplateFileError:		"Please select a valid template file.",
                *       errorMessageSelectImageError:		    "Please select a image.",
                *       errorMessageImageWidthError: 		    "Please input a number for 'Image width' textbox.",
                *       errorMessageImageHeightError:		    "Please input a number for 'Image height' textbox.",
                *       errorMessageAddressError:		        "Please input address!",
                *       errorMessageDisplayTextError:	        "Please input display text!",
                *       errorMessageHyperLinkImageUrlError:	    "Please input image url!,
                *       errorMessageHyperLinkImageWidthError	Please input correct image width!",
                *       errorMessageHyperLinkImageHeightError:	"Please input correct image height!",
                *       errorMessageHyperLinkUrl:		        "Please input correct url!",
                *       errorMessageHyperLinkAnchor:	        "Please input correct anchor!",
                *       errorMessageHyperLinkEmail:		        "Please input correct email!",
                *       errorMessageCopyToClipboardError:       "Copy text to Clipboard \n If you are using firefox please do the following :\n  1. Write in your url box : 'about:config'\n 2. Change signed.applets.codebase_principal_support = true\n",
                *       errorMessageRowsError: 	                "Please input a number for 'Rows' textbox.",
                *       errorMessageColumnsError:		        "Please input a number for 'Columns' textbox.",
                *       errorMessageTableWidthError: 	        "Please input a number for 'Table Width ' textbox.",
                *       errorMessageTableHeightError:	        "Please input a number for 'Table Height' textbox.",
                *       errorMessageSelectTableError:	        "Please select a table!",
                *       errorMessageReplaceStringError:         "please input replace string!",
                *       errorMessageFindTextError:		        "String Not Found!",
                *       errorMessageUrlEmptyError:		        "URL is empty!",
                *       errorMessageUrlCorrectError:	        "please input correct URL!",
                *       errorMessageMediaWidthError:	        "please input width of the media!",
                *       errorMessageMediaHeightError:	        "please input height of the media!",
                *       tableDialogBorderError:	                "Please input a number for 'Border thickness' textbox.",
                *       tableDialogCellPaddingError:	        "Please input a number for 'Cell Padding' textbox.",
                *       tableDialogCellSpacingError:	        "Please input a number for 'Cell Spacing' textbox.",
                *       notFindCommandError:                    "Cannot find the dialog with command name '",
                *
                *       // dialog common
                *       dialogOK:	    "OK",
                *       dialogCancel:  "Cancel",
                *       dialogPixel:	"px",
                
                *       // back color dialog
                *       backColorDialogTitle:		        "Set BackColor",
                *       backColorDialogSelectedColor:		"Selected Color:",
                *
                *       // specialCharacter Dialog
                *       specialCharacterDialogTitle:		"Insert special character",
                *
                *       // fore Color Dialog
                *       foreColorDialogTitle:		        "Set ForeColor",
                
                *       // insertCode Dialog
                *       insertCodeDialogInsertCode:		    "Insert Code",
                *       insertCodeDialogEnterSourceCode: 	"Enter source code:",
                *
                *       // template dialog
                *       templateDialogName:             	"Name :",
                *       templateDialogDescription:	        "Description :",
                *       templateDialogSelectTemplate:	    "Select Template:",
                *       templateDialogTemplatePreview:	    "Template Preview:",
                *       templateDialogDeleteSelected: 	    "Delete selected",
                *       templateDialogSaveCurrentPage:	    "Save current page as template",
                *       templateDialogApplyTemplate:		"Apply Template",
                *
                *       // image editor dialog
                *       imageEditorDialogImageSrc:		 "Image Src:",
                *       imageEditorDialogImageAltText:	 "Image alt text:",
                *       imageEditorDialogImageWidth:	 "Image width:",
                *       imageEditorDialogImageHeight:	 "Image height:",
                *       imageEditorDialogCssText:		 "Css text:",
                *       imageEditorDialogImageSrc:		 "Image Src:",
                *       imageEditorDialogImageBrowser: 	 "Image Browser",
                *
                *       // hyper link dialog
                *       hyperLinkDialogTarget:		    "Target :",
                *       hyperLinkDialogCss:			    "Css :",
                *       hyperLinkDialogAddress:		    "Address :",
                *       hyperLinkDialogUrl:			    "url",
                *       hyperLinkDialogAnchor:		    "anchor",
                *       hyperLinkDialogEmail:			"email",
                *       hyperLinkDialogIconType:		"Icon Type :",
                *       hyperLinkDialogText:			"text",
                *       hyperLinkDialogImage:			"image",
                *       hyperLinkDialogTextToDisplay:	"Text to display :",
                *       hyperLinkDialogInserthyperLink: "Insert hyperLink",
                *       insertHyperLinkMailTo:		     "mailto:",
                *
                *       // tab inspector dialog
                *       tagInspectorDialogSelectedTag:	                 "Selected tag :",
                *       tagInspectorDialogDisplayNotEmptyAttributes:	 "Display not empty attributes only",
                *       tagInspectorDialogAttributes:		             "Attributes:",
                *       tagInspectorDialogInnerHTML:		             "Inner HTML:",
                *       tagInspectorDialogCSSText:			             "Css Text:",
                *       tagInspectorDialogSave:		                     "Save",
                *       tagInspectorDialogTitle:	                     "Tag Inspector",
                *
                *       // table dialog
                *       tableDialogRows:				"Rows :",
                *       tableDialogColumns:				"Columns :",
                *       tableDialogTableWidth:			"Table Width :",
                *       tableDialogPixels:				"pixels",
                *       tableDialogBorder:				"Border thickness:",
                *       tableDialogCellPadding:			"Cell Padding :",
                *       tableDialogCellSpacing:			"Cell Spacing :",
                *       tableDialogCssText:				"Css Text :",
                *       tableDialogBackgroundColor:		"Background Color:",
                *       insertTableDialogTitle:	        "Insert Table",
                *       editTableDialogTitle:		    "Edit Table",
                *
                *       // preview dialog
                *       previewDialogPreviewSize:		"Preview Size:",
                *       previewDialogSplit:				"Split pages",
                *       previewDialogPrintAll:			"Print All",
                *       previewDialogPrintPage:			"Print Page",
                *       previewDialogPrevPage:			"Prev page",
                *       previewDialogNextPage:			"Next page",
                *       previewDialogPreview:		    "Preview",
                *
                *       // find and replace dialog
                *       findAndReplaceDialogFind:				"Find",
                *       findAndReplaceDialogReplace:			"Replace",
                *       findAndReplaceDialogFindButton:		    "Find",
                *       findAndReplaceDialogReplaceButton:	    "Replace",
                *       findAndReplaceDialogTitle: 		        "Find and replace",
                *
                *       // media dialog
                *       mediaDialogMediaType:			"Media Type :",
                *       mediaDialogMediaUrl:			"Media Url :",
                *       mediaDialogWidth:				"Width :",
                *       mediaDialogHeight:				"Height :",
                *       mediaDialogTitle:		        "Insert media",
                *
                *       // clean up dialog
                *       cleanUpDialogStripSpanTag:		        "Strip SPAN tag",
                *       cleanUpDialogStripClass:		        "Strip CLASS tag",
                *       cleanUpDialogStripStyle:		        "Strip STYLE attribute",
                *       cleanUpDialogReplaceSymbol:		        "Replace &amp;nbsp; symbol",
                *       cleanUpDialogTransformParagraphToDIV:	"Transform Paragraph to DIV",
                *       cleanUpDialogTitle:		                "Clean up source HTML document",
                *       cleanUpDialogDocumentSource:            "Document source"
                *}
                * @type {object}
                * @example $("#editor").wijeditor(
                *					{
                *						localization: {
                *							formButtonTip: "Add Form",
                *							insertTab: "Insert to Editor"
                *						}
                *					});
                */
                this.localization = null;
                /** Determine if wijeditor is in readonly mode
                * @default false
                */
                this.readOnly = false;
            }
            return wijeditor_options;
        })();
        ;
        wijeditor.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijeditor_options());

        //A value indicates whether to show the virtual border for table in the edit.
        //It only works when the border style is not set in table.
        wijeditor.prototype.options.tableVirtualBorderShowing = true;
        $.wijmo.registerWidget("wijeditor", wijeditor.prototype);

        //wijDoc = document,
        //wijParseInt = parseInt,
        //css_editor = "wijmo-wijeditor",
        var css_editor_colorcanvas = css_editor + "-colorcanvas", css_editor_color = css_editor + "-color", css_editor_wheel = css_editor + "-wheel", css_editor_overlay = css_editor + "-overlay", css_editor_marker = css_editor + "-marker";

        /** @ignore */
        $.fn.wijeditorcolorcanvas = function (callback, initColor) {
            //$.wijeditorcolorcanvas(this, callback, initColor);
            var container = this.get(0);
            return container.wijeditorcolorcanvas || (container.wijeditorcolorcanvas = new _wijeditorcolorcanvas(container, callback, initColor));
            return this;
        };

        /** @ignore */
        var _wijeditorcolorcanvas = (function () {
            function _wijeditorcolorcanvas(container, callback, initColor) {
                // Store editorcolorcanvas object
                var fb = this, markup = "", e, alphaImageLoader;

                alphaImageLoader = "progid:DXImageTransform.Microsoft.AlphaImageLoader" + "(enabled=true, sizingMethod=crop, ";

                markup += "<div class='" + css_editor_colorcanvas + "'>";
                markup += "<div class='" + css_editor_color + "'></div>";
                markup += "<div class='" + css_editor_wheel + "'></div>";
                markup += "<div class='" + css_editor_overlay + "'></div>";
                markup += "<div class='h-marker " + css_editor_marker + "'></div>";
                markup += "<div class='sl-marker " + css_editor_marker + "'></div></div>";

                $(container).html(markup);

                e = $("." + css_editor_colorcanvas, container);
                fb.wheel = $("." + css_editor_wheel, container).get(0);

                // Dimensions
                fb.radius = 84;
                fb.square = 100;
                fb.width = 194;

                // Fix background PNGs in IE6
                if ($.browser.msie && parseInt($.browser.version, 10) < 7) {
                    $('*', e).each(function () {
                        var imgEl = this, bgImg = imgEl.currentStyle.backgroundImage;

                        if (bgImg !== 'none') {
                            bgImg = bgImg.substring(5, bgImg.length - 2);

                            $(imgEl).css({
                                'backgroundImage': 'none',
                                'filter': alphaImageLoader + "src='" + bgImg + "')"
                            });
                        }
                        return this;
                    });
                }

                /**
                * Link to the given element(s) or callback.
                */
                fb.linkTo = function (callback) {
                    // Unbind previous nodes
                    if (typeof fb.callback === 'object') {
                        $(fb.callback).unbind('keyup', fb.updateValue);
                    }

                    // Reset color
                    fb.color = null;

                    // Bind callback or elements
                    if (typeof callback === 'function') {
                        fb.callback = callback;
                    } else if (typeof callback === 'object' || typeof callback === 'string') {
                        fb.callback = $(callback);
                        fb.callback.bind('keyup', fb.updateValue);
                        if (fb.callback.get(0).value) {
                            fb.setColor(fb.callback.get(0).value);
                        }
                    }
                    return this;
                };

                fb.updateValue = function (event) {
                    var self = this;
                    if (self.value && self.value !== fb.color) {
                        fb.setColor(self.value);
                    }
                };

                /**
                * Change color with HTML syntax #123456
                */
                fb.setColor = function (color) {
                    var unpack = fb.unpack(color);
                    if (fb.color !== color && unpack) {
                        fb.color = color;
                        fb.rgb = unpack;
                        fb.hsl = fb.RGBToHSL(fb.rgb);
                        fb.updateDisplay();
                    }
                    return this;
                };

                /**
                * Change color with HSL triplet [0..1, 0..1, 0..1]
                */
                fb.setHSL = function (hsl) {
                    fb.hsl = hsl;
                    fb.rgb = fb.HSLToRGB(hsl);
                    fb.color = fb.pack(fb.rgb);
                    fb.updateDisplay();
                    return this;
                };

                /**
                * Retrieve the coordinates of the given event relative to the center
                * of the widget.
                */
                fb.widgetCoords = function (event) {
                    var x, y, el, reference, pos;
                    el = event.target || event.srcElement;
                    reference = fb.wheel;

                    // Use absolute coordinates
                    pos = fb.absolutePosition(reference);
                    x = (event.pageX || 0 * (event.clientX + $('html').get(0).scrollLeft)) - pos.x;
                    y = (event.pageY || 0 * (event.clientY + $('html').get(0).scrollTop)) - pos.y;

                    // Subtract distance to middle
                    return { x: x - fb.width / 2, y: y - fb.width / 2 };
                };

                /**
                * Mousedown handler
                */
                fb.mousedown = function (event) {
                    // Capture mouse
                    if (!wijDoc.dragging) {
                        $(wijDoc).bind('mousemove', fb.mousemove).bind('mouseup', fb.mouseup);
                        wijDoc.dragging = true;
                    }

                    // Check which area is being dragged
                    var pos = fb.widgetCoords(event);

                    //document.title = pos.x + "|" + pos.y;
                    fb.circleDrag = Math.max(Math.abs(pos.x), Math.abs(pos.y)) * 2 > fb.square;

                    // Process
                    fb.mousemove(event);
                    return false;
                };

                /**
                * Mousemove handler
                */
                fb.mousemove = function (event) {
                    // Get coordinates relative to color picker center
                    var pos = fb.widgetCoords(event), hue, sat, lum;

                    // Set new HSL parameters
                    if (fb.circleDrag) {
                        hue = Math.atan2(pos.x, -pos.y) / 6.28;
                        if (hue < 0) {
                            hue += 1;
                        }
                        fb.setHSL([hue, fb.hsl[1], fb.hsl[2]]);
                    } else {
                        sat = Math.max(0, Math.min(1, -(pos.x / fb.square) + 0.5));
                        lum = Math.max(0, Math.min(1, -(pos.y / fb.square) + 0.5));
                        fb.setHSL([fb.hsl[0], sat, lum]);
                    }
                    return false;
                };

                /**
                * Mouseup handler
                */
                fb.mouseup = function () {
                    // Uncapture mouse
                    $(wijDoc).unbind('mousemove', fb.mousemove).unbind('mouseup', fb.mouseup);

                    wijDoc.dragging = false;
                };

                /**
                * Update the markers and styles
                */
                fb.updateDisplay = function () {
                    // Markers
                    var angle = fb.hsl[0] * 6.28, inputEl;
                    $('.h-marker', e).css({
                        left: Math.round(Math.sin(angle) * fb.radius + fb.width / 2) + 'px',
                        top: Math.round(-Math.cos(angle) * fb.radius + fb.width / 2) + 'px'
                    });

                    $('.sl-marker', e).css({
                        left: Math.round(fb.square * (0.5 - fb.hsl[1]) + fb.width / 2) + 'px',
                        top: Math.round(fb.square * (0.5 - fb.hsl[2]) + fb.width / 2) + 'px'
                    });

                    // Saturation/Luminance gradient
                    $("." + css_editor_color, e).css('backgroundColor', fb.pack(fb.HSLToRGB([fb.hsl[0], 1, 0.5])));

                    // Linked elements or callback
                    if (typeof fb.callback === 'object') {
                        // Set background/foreground color
                        $(fb.callback).css({
                            backgroundColor: fb.color,
                            color: fb.hsl[2] > 0.5 ? '#000' : '#fff'
                        });

                        // Change linked value
                        $(fb.callback).each(function () {
                            inputEl = this;
                            if (inputEl.value && inputEl.value !== fb.color) {
                                inputEl.value = fb.color;
                            }
                            return this;
                        });
                    } else if (typeof fb.callback === 'function') {
                        fb.callback.call(fb, fb.color);
                    }
                };

                /**
                * Get absolute position of element
                */
                fb.absolutePosition = function (el) {
                    var r = { x: el.offsetLeft, y: el.offsetTop }, tmp;

                    // Resolve relative to offsetParent
                    if (el.offsetParent) {
                        tmp = fb.absolutePosition(el.offsetParent);
                        r.x += tmp.x;
                        r.y += tmp.y;
                    }
                    return r;
                };

                /* Various color utility functions */
                fb.pack = function (rgb) {
                    var r = Math.round(rgb[0] * 255), g, b;
                    g = Math.round(rgb[1] * 255);
                    b = Math.round(rgb[2] * 255);
                    return '#' + (r < 16 ? '0' : '') + r.toString(16) + (g < 16 ? '0' : '') + g.toString(16) + (b < 16 ? '0' : '') + b.toString(16);
                };

                fb.unpack = function (color) {
                    if (color.length === 7) {
                        return [
                            wijParseInt('0x' + color.substring(1, 3)) / 255,
                            wijParseInt('0x' + color.substring(3, 5)) / 255,
                            wijParseInt('0x' + color.substring(5, 7)) / 255];
                    } else if (color.length === 4) {
                        return [
                            wijParseInt('0x' + color.substring(1, 2)) / 15,
                            wijParseInt('0x' + color.substring(2, 3)) / 15,
                            wijParseInt('0x' + color.substring(3, 4)) / 15];
                    }
                };

                fb.HSLToRGB = function (hsl) {
                    var m1, m2, h, s, l, self = this;
                    h = hsl[0];
                    s = hsl[1];
                    l = hsl[2];
                    m2 = (l <= 0.5) ? l * (s + 1) : l + s - l * s;
                    m1 = l * 2 - m2;
                    return [
                        self.hueToRGB(m1, m2, h + 0.33333),
                        self.hueToRGB(m1, m2, h),
                        self.hueToRGB(m1, m2, h - 0.33333)];
                };

                fb.hueToRGB = function (m1, m2, h) {
                    h = (h < 0) ? h + 1 : ((h > 1) ? h - 1 : h);
                    if (h * 6 < 1) {
                        return m1 + (m2 - m1) * h * 6;
                    }
                    if (h * 2 < 1) {
                        return m2;
                    }
                    if (h * 3 < 2) {
                        return m1 + (m2 - m1) * (0.66666 - h) * 6;
                    }
                    return m1;
                };

                fb.RGBToHSL = function (rgb) {
                    var min, max, delta, h, s, l, r, g, b;
                    r = rgb[0];
                    g = rgb[1];
                    b = rgb[2];
                    min = Math.min(r, Math.min(g, b));
                    max = Math.max(r, Math.max(g, b));
                    delta = max - min;
                    l = (min + max) / 2;
                    s = 0;
                    if (l > 0 && l < 1) {
                        s = delta / (l < 0.5 ? (2 * l) : (2 - 2 * l));
                    }
                    h = 0;
                    if (delta > 0) {
                        if (max === r && max !== g) {
                            h += (g - b) / delta;
                        }
                        if (max === g && max !== b) {
                            h += (2 + (b - r) / delta);
                        }
                        if (max === b && max !== r) {
                            h += (4 + (r - g) / delta);
                        }
                        h /= 6;
                    }
                    return [h, s, l];
                };

                // Install mousedown handler (the others are set on the document on-demand)
                $('*', e).mousedown(fb.mousedown);

                // Init color
                fb.setColor(initColor || '#000000');

                // Set linked elements/callback
                if (callback) {
                    fb.linkTo(callback);
                }
            }
            return _wijeditorcolorcanvas;
        })();
        editor._wijeditorcolorcanvas = _wijeditorcolorcanvas;
    })(wijmo.editor || (wijmo.editor = {}));
    var editor = wijmo.editor;
})(wijmo || (wijmo = {}));



;
/// <reference path="../Base/jquery.wijmo.widget.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*globals jQuery, window*/
    /*
    * Depends:
    *   jquery.js
    *   jquery.ui.core.js
    *   jquery.ui.widget.js
    *   jquery.wijmo.widget.js
    *   jquery.wijmo.util.js
    */
    (function (rating) {
        var $ = jQuery;

        /** @widget */
        var wijrating = (function (_super) {
            __extends(wijrating, _super);
            function wijrating() {
                _super.apply(this, arguments);
            }
            wijrating.prototype._setOption = function (key, value) {
                var o = this.options, resetButton = $("." + o.wijCSS.wijratingResetButton, this.ratingElement[0]), starContainer = $("." + o.wijCSS.wijratingStarContainer, this.ratingElement[0]), stars = $("." + o.wijCSS.wijratingNormalStar, this.ratingElement[0]);

                if ($.isPlainObject(o[key])) {
                    switch (key) {
                        case "resetButton":
                            if (typeof (value.disabled) !== 'undefined') {
                                if (value.disabled !== o[key].disabled) {
                                    if (value.disabled) {
                                        resetButton.hide();

                                        //add aria support.
                                        resetButton.attribute("aria-hidden", true);
                                    } else {
                                        if (!this._isDisabled()) {
                                            resetButton.show();

                                            //add aria support.
                                            resetButton.attribute("aria-hidden", false);
                                        }
                                    }
                                }
                            }
                            if (typeof (value.hint) !== 'undefined') {
                                if (value.hint !== o[key].hint) {
                                    if (value.hint === null) {
                                        resetButton.attr("title", "");
                                    } else {
                                        resetButton.attr("title", value.hint);
                                    }
                                }
                            }
                            if (value.position && value.position.length) {
                                if (value.position !== o[key].position) {
                                    if (value.position === "rightOrBottom") {
                                        resetButton.parent().append(resetButton);
                                    } else {
                                        resetButton.parent().prepend(resetButton);
                                    }
                                }
                            }
                            if (typeof (value.customizedClass) !== 'undefined') {
                                if (value.customizedClass !== o[key].customizedClass) {
                                    if (o[key].customizedClass.length) {
                                        resetButton.removeClass(o[key].customizedClass);
                                    }
                                    if (value.customizedClass.length) {
                                        resetButton.addClass(value.customizedClass);
                                    }
                                }
                            }
                            break;
                        case "hint":
                            if (typeof (value.disabled) !== 'undefined') {
                                if (value.disabled !== o[key].disabled) {
                                    if (value.disabled) {
                                        stars.removeAttr("title");
                                    } else {
                                        this._resetHint(o.hint.content);
                                    }
                                }
                            }
                            if (typeof (value.content) !== 'undefined') {
                                if (value.content !== o[key].content) {
                                    if (!value.disabled) {
                                        this._resetHint(value.content);
                                    }
                                }
                            }
                            break;
                        case "icons":
                            if (typeof (value.iconsClass) !== 'undefined') {
                                if (o[key].iconsClass && o[key].iconsClass.length) {
                                    this._removeCustomizedIconsClass(o[key].iconsClass);
                                }
                                this._addCustomizedIconsClass(value.iconsClass, o.split);
                            }
                            if (typeof (value.hoverIconsClass) !== 'undefined') {
                                if (o[key].hoverIconsClass && o[key].hoverIconsClass.length) {
                                    this._removeCustomizedIconsClass(o[key].hoverIconsClass);
                                }
                            }
                            if (typeof (value.ratedIconsClass) !== 'undefined') {
                                if (o[key].ratedIconsClass && o[key].ratedIconsClass.length) {
                                    this._removeCustomizedIconsClass(o[key].ratedIconsClass);
                                }
                                this._resetValue(o.value, o.ratingMode, value.ratedIconsClass);
                            }
                            break;
                        default:
                            break;
                    }
                    $.extend(true, o[key], value);
                } else {
                    if (value === o[key]) {
                        return;
                    }
                    switch (key) {
                        case "count":
                            this._createStars(o.split, value, starContainer);
                            break;
                        case "split":
                            this._createStars(value, o.count, starContainer);
                            break;
                        case "totalValue":
                            this._resetTotalValue(value);
                            break;
                        case "orientation":
                            if (value === "vertical") {
                                this.ratingElement.addClass(o.wijCSS.wijvRating);
                            } else {
                                this.ratingElement.removeClass(o.wijCSS.wijvRating);
                            }
                            if (o.split > 1) {
                                o[key] = value;
                                this._createStars(o.split, o.count, starContainer);
                            }
                            break;
                        case "direction":
                            o[key] = value;
                            this._createStars(o.split, o.count, starContainer);
                            break;
                        case "ratingMode":
                            this._resetValue(o.value, value, o.icons.ratedIconsClass);
                            break;
                        case "value":
                            if (o.min && value < o.min) {
                                return;
                            }
                            if (o.max && value > o.max) {
                                return;
                            }
                            this._resetValue(value, o.ratingMode, o.icons.ratedIconsClass);
                            break;
                        case "iconWidth":
                            o[key] = value;
                            this._createStars(o.split, o.count, starContainer);
                            break;
                        case "iconHeight":
                            o[key] = value;
                            this._createStars(o.split, o.count, starContainer);
                            break;
                        default:
                            break;
                    }
                    _super.prototype._setOption.call(this, key, value);
                }
            };

            wijrating.prototype._innerDisable = function () {
                var o = this.options, resetButton = $("." + o.wijCSS.wijratingResetButton, this.ratingElement[0]);
                _super.prototype._innerDisable.call(this);

                this._unbindLiveEvents();
                resetButton.hide();
                resetButton.attribute("aria-hidden", true);
            };

            wijrating.prototype._innerEnable = function () {
                var o = this.options, resetButton = $("." + o.wijCSS.wijratingResetButton, this.ratingElement[0]);
                _super.prototype._innerEnable.call(this);

                this._bindLiveEvents();
                if (!o.resetButton.disabled) {
                    resetButton.show();
                    resetButton.attribute("aria-hidden", false);
                }
            };

            wijrating.prototype._create = function () {
                var o = this.options, ratingElement;

                if (this.element.is("select")) {
                    this._parseSelect();
                    this.element.hide();
                    ratingElement = $("<div></div>");
                    this.element.after(ratingElement);
                } else if (this.element.is("div")) {
                    if (this.element.children("input[type='radio']").length > 0) {
                        this._parseRadio();
                        this.element.hide();
                        ratingElement = $("<div></div>");
                        this.element.after(ratingElement);
                    } else {
                        ratingElement = this.element;
                    }
                } else {
                    return;
                }
                this.ratingElement = ratingElement;
                this._createRating();
                if (!this._isDisabled()) {
                    this._bindLiveEvents();
                }

                _super.prototype._create.call(this);
            };

            /** The destroy() method will remove the rating functionality completely
            * and will return the element to its pre-init state.
            */
            wijrating.prototype.destroy = function () {
                var o = this.options;
                this._unbindLiveEvents();
                if (this.element !== this.ratingElement) {
                    this.ratingElement.remove();
                    this.element.show();
                } else {
                    this.element.removeClass(o.wijCSS.widget).removeClass(o.wijCSS.wijrating).removeClass(o.wijCSS.wijvRating).empty();
                }
                _super.prototype.destroy.call(this);
            };

            wijrating.prototype._unbindLiveEvents = function () {
                var o = this.options;
                this.ratingElement.off(".wijrating", "." + o.wijCSS.wijratingNormalStar).off(".wijrating", "." + o.wijCSS.wijratingResetButton);
            };

            wijrating.prototype._bindLiveEvents = function () {
                var self = this, o = self.options, isStar = "." + o.wijCSS.wijratingNormalStar, isRestButton = "." + o.wijCSS.wijratingResetButton, args, starProxyObj = {
                    element: self.ratingElement,
                    mouseover: function (e) {
                        var tar = $(e.target), allStars = $(isStar, self.ratingElement[0]);
                        if (tar.is(isStar)) {
                            allStars.removeClass(o.wijCSS.wijratingHoverStar);
                            tar.addClass(o.wijCSS.wijratingHoverStar);
                            if (o.ratingMode === "continuous") {
                                if (o.direction === "reversed") {
                                    tar.parent().nextAll().children().addClass(o.wijCSS.wijratingHoverStar);
                                } else {
                                    tar.parent().prevAll().children().addClass(o.wijCSS.wijratingHoverStar);
                                }
                            }
                            self._addCustomizedHoverIconsClass(o.icons.hoverIconsClass, o.split, tar);
                            args = {
                                value: parseFloat(tar.html()),
                                target: tar
                            };
                            self._trigger("hover", e, args);
                        }
                    },
                    mouseout: function (e) {
                        var tar = $(e.target), allStars = $(isStar, self.ratingElement[0]);
                        if (tar.is(isStar)) {
                            allStars.removeClass(o.wijCSS.wijratingHoverStar);
                            self._removeCustomizedIconsClass(o.icons.hoverIconsClass);
                        }
                    },
                    click: function (e) {
                        var tar = $(e.target), val = parseFloat(tar.html()), allStars = $(isStar, self.ratingElement[0]), animation = {
                            duration: 500,
                            easing: null,
                            delay: 250,
                            animated: null
                        }, animations = $.wijmo.wijrating.animations, animated;
                        $.extend(true, animation, o.animation);
                        animated = animation.animated;

                        if (!tar.is(isStar)) {
                            return;
                        }
                        if (o.max && val > o.max) {
                            return;
                        }
                        if (o.min && val < o.min) {
                            return;
                        }
                        args = {
                            oldValue: o.value,
                            newValue: val,
                            target: tar
                        };
                        if (self._trigger("rating", e, args) === false) {
                            return false;
                        }
                        o.value = val;
                        self._resetValue(val, o.ratingMode, o.icons.ratedIconsClass);
                        allStars.removeClass(o.wijCSS.wijratingHoverStar);
                        self._removeCustomizedIconsClass(o.icons.hoverIconsClass);
                        args = {
                            value: val,
                            target: tar
                        };

                        if (animated) {
                            if (animations && animations[animated]) {
                                animations[animated](o, allStars, function () {
                                    self._trigger("rated", e, args);
                                });
                            } else if ($.effects && ($.effects[animated] || ($.effects.effect && $.effects.effect[animated]))) {
                                //individual effects in jqueryui 1.9 are now defined on
                                // $.effects.effect rather than directly on $.effects.
                                self._playJqueryAnimation(animation, allStars, function () {
                                    //remove filter style to fix jquery animation
                                    //bug in ie8.
                                    if ($.browser.msie && parseInt($.browser.version) < 9) {
                                        allStars.css("filter", "");
                                    }
                                    self._trigger("rated", e, args);
                                });
                            } else {
                                self._trigger("rated", e, args);
                            }
                        } else {
                            self._trigger("rated", e, args);
                        }
                    }
                }, resetButtonProxy = {
                    element: self.ratingElement,
                    mouseover: function (e) {
                        var tar = $(e.target);
                        tar = tar.closest("." + o.wijCSS.wijratingResetButton);
                        tar.addClass(o.wijCSS.wijratingHoverResetButton).addClass(o.wijCSS.stateHover);
                        if (o.resetButton.customizedHoverClass && o.resetButton.customizedHoverClass.length) {
                            tar.addClass(o.resetButton.customizedHoverClass);
                        }
                    },
                    mouseout: function (e) {
                        var tar = $(e.target);
                        tar = tar.closest("." + o.wijCSS.wijratingResetButton);
                        tar.removeClass(o.wijCSS.wijratingHoverResetButton).removeClass(o.wijCSS.stateHover);
                        if (o.resetButton.customizedHoverClass && o.resetButton.customizedHoverClass.length) {
                            tar.removeClass(o.resetButton.customizedHoverClass);
                        }
                    },
                    click: function (e) {
                        var tar = $(e.target);
                        self._setOption("value", 0);
                        args = {
                            target: tar
                        };
                        self._trigger("reset", e, args);
                    }
                };
                this.ratingElement.on("mouseover.wijrating", isStar, $.proxy(starProxyObj.mouseover, starProxyObj)).on("mouseout.wijrating", isStar, $.proxy(starProxyObj.mouseout, starProxyObj)).on("click.wijrating", isStar, $.proxy(starProxyObj.click, starProxyObj)).on("mouseover.wijrating", isRestButton, $.proxy(resetButtonProxy.mouseover, resetButtonProxy)).on("mouseout.wijrating", isRestButton, $.proxy(resetButtonProxy.mouseout, resetButtonProxy)).on("click.wijrating", isRestButton, $.proxy(resetButtonProxy.click, resetButtonProxy));
            };

            wijrating.prototype._createRating = function () {
                var element = this.ratingElement, o = this.options, resetButton, resetIcon, starContainer;
                element.addClass(o.wijCSS.wijrating).addClass(o.wijCSS.widget);
                if (o.orientation === "vertical") {
                    element.addClass(o.wijCSS.wijvRating);
                }

                //add reset button.
                resetButton = $("<div></div>").addClass(o.wijCSS.wijratingResetButton).addClass(o.wijCSS.cornerAll).addClass(o.wijCSS.stateDefault);
                if (o.resetButton.customizedClass && o.resetButton.customizedClass.length) {
                    resetButton.addClass(o.resetButton.customizedClass);
                }
                resetButton.appendTo(element);

                //add aria support.
                resetButton.attr("role", "button").attribute("aria-label", "reset").attribute("aria-hidden", false);

                if (o.resetButton.hint && o.resetButton.hint.length) {
                    resetButton.attr("title", o.resetButton.hint);
                }
                if (o.resetButton.disabled || this._isDisabled()) {
                    resetButton.hide();

                    //add aria support
                    resetButton.attribute("aria-hidden", true);
                }

                resetIcon = $("<span></span>");
                resetIcon.addClass(o.wijCSS.icon).addClass(o.wijCSS.iconClose);
                resetButton.append(resetIcon);

                //add star container.
                starContainer = $("<div></div>");

                //add aria support.
                starContainer.attr("role", "radiogroup").addClass(o.wijCSS.wijratingStarContainer);
                if (o.resetButton.position === "leftOrTop") {
                    starContainer.appendTo(element);
                } else {
                    starContainer.prependTo(element);
                }

                // create stars.
                this._createStars(o.split, o.count, starContainer);
            };

            wijrating.prototype._createStars = function (split, starCount, starContainer) {
                var o = this.options, hint = o.hint, content, star, val, nextVal = 0, idx = 0, splitIdx = 0, starWidth = Math.ceil(o.iconWidth / split), starHeight = Math.ceil(o.iconHeight / split), ratedIconsClass = o.icons.ratedIconsClass, customizedIconIdx, customizedIconClass, isCustomizedClass = ratedIconsClass && ratedIconsClass.length;
                starContainer.empty();
                for (idx; idx < starCount * split; idx++, splitIdx++) {
                    val = Math.round((idx + 1) * o.totalValue * 100 / starCount / split) / 100;
                    nextVal = Math.round((idx + 2) * o.totalValue * 100 / starCount / split) / 100;
                    if (splitIdx === split) {
                        splitIdx = 0;
                    }
                    star = $("<div></div>");

                    //add aria support.
                    star.attr("role", "radio").attribute("aria-checked", false);
                    if (o.orientation === "vertical") {
                        star.width(o.iconWidth).height(starHeight);
                    } else {
                        star.width(starWidth).height(o.iconHeight);
                    }
                    star.addClass(o.wijCSS.wijratingStar);
                    content = $("<div>" + val + "</div>");
                    content.addClass(o.wijCSS.wijratingNormalStar).width(o.iconWidth).height(o.iconHeight);

                    //add aria support.
                    star.attribute("aria-label", val);
                    if (splitIdx > 0 && o.direction === "normal") {
                        if (o.orientation === "vertical") {
                            content.css({
                                "margin-top": "-" + splitIdx * starHeight + "px"
                            });
                        } else {
                            content.css({
                                "margin-left": "-" + splitIdx * starWidth + "px"
                            });
                        }
                    } else if (splitIdx < split - 1 && o.direction === "reversed") {
                        if (o.orientation === "vertical") {
                            content.css({
                                "margin-top": "-" + (split - 1 - splitIdx) * starHeight + "px"
                            });
                        } else {
                            content.css({
                                "margin-left": "-" + (split - 1 - splitIdx) * starWidth + "px"
                            });
                        }
                    }
                    if (!hint.disabled) {
                        if (hint.content && hint.content.length) {
                            if (idx <= hint.content.length) {
                                content.attr("title", hint.content[idx]);

                                //add aria support.
                                star.attribute("aria-label", hint.content[idx]);
                            }
                        } else {
                            content.attr("title", val);
                        }
                    }
                    if (isCustomizedClass) {
                        if (typeof (ratedIconsClass) === "string") {
                            customizedIconClass = ratedIconsClass;
                        } else if ($.isArray(ratedIconsClass)) {
                            customizedIconIdx = Math.floor(idx / split);
                            if (ratedIconsClass.length > customizedIconIdx) {
                                customizedIconClass = ratedIconsClass[customizedIconIdx];
                            }
                        }
                    }
                    if (val === o.value || (nextVal > o.value && val < o.value && o.ratingMode === "single")) {
                        content.addClass(o.wijCSS.wijratingRatedStar);
                        if (isCustomizedClass) {
                            content.addClass(customizedIconClass);
                        }

                        //add aria support.
                        star.attribute("aria-checked", true);
                    } else if (val < o.value && o.ratingMode === "continuous") {
                        content.addClass(o.wijCSS.wijratingRatedStar);
                        if (isCustomizedClass) {
                            content.addClass(customizedIconClass);
                        }
                    }
                    content.appendTo(star);
                    if (o.direction === "reversed") {
                        star.prependTo(starContainer);
                    } else {
                        star.appendTo(starContainer);
                    }
                }

                //add customized class
                this._addCustomizedIconsClass(o.icons.iconsClass, split);
            };

            wijrating.prototype._resetValue = function (value, ratingMode, ratedIconsClass) {
                var o = this.options, stars = $("." + o.wijCSS.wijratingNormalStar, this.ratingElement[0]), rMode = ratingMode || o.ratingMode, isCustomizedClass = ratedIconsClass && ratedIconsClass.length, customizedIconIdx = 0, customizedIconClass;
                $.each(stars, function (idx, ele) {
                    var content = $(ele), val = parseFloat(content.html()), nextVal;
                    if (idx < stars.length - 1) {
                        nextVal = parseFloat($(stars[idx + 1]).html());
                    } else {
                        nextVal = o.direction === "normal" ? o.totalValue + 1 : -1;
                    }
                    content.removeClass(o.wijCSS.wijratingRatedStar);

                    //add aria support.
                    content.parent().attribute("aria-checked", false);
                    if (isCustomizedClass) {
                        if (typeof (ratedIconsClass) === "string") {
                            content.removeClass(ratedIconsClass);
                            customizedIconClass = ratedIconsClass;
                        } else if ($.isArray(ratedIconsClass)) {
                            $.each(ratedIconsClass, function (i, cl) {
                                content.removeClass(cl);
                            });

                            if (o.direction === "reversed") {
                                customizedIconIdx = Math.floor((stars.length - 1 - idx) / o.split);
                            } else {
                                customizedIconIdx = Math.floor(idx / o.split);
                            }
                            if (ratedIconsClass.length > customizedIconIdx) {
                                customizedIconClass = ratedIconsClass[customizedIconIdx];
                            }
                        }
                    }

                    if (val === value || (nextVal > value && val < value && rMode === "single")) {
                        content.addClass(o.wijCSS.wijratingRatedStar);
                        if (isCustomizedClass) {
                            content.addClass(customizedIconClass);
                        }

                        //add aria support.
                        content.parent().attribute("aria-checked", true);
                    } else if (rMode === "continuous") {
                        if (val < value) {
                            content.addClass(o.wijCSS.wijratingRatedStar);
                            if (isCustomizedClass) {
                                content.addClass(customizedIconClass);
                            }
                        }
                    }
                });
            };

            wijrating.prototype._resetTotalValue = function (value) {
                var o = this.options, content = o.hint, stars = $("." + o.wijCSS.wijratingNormalStar, this.ratingElement[0]), starsLen = stars.length;
                $.each(stars, function (idx, star) {
                    var jStar = $(star), newVal = Math.round((idx + 1) * value * 100 / starsLen) / 100, val = parseFloat(jStar.html());

                    //set new value.
                    if (val === o.value) {
                        o.value = newVal;
                    }
                    jStar.html(newVal.toString());
                    if (content && content.length && content.length >= idx && content[idx] && content[idx].length) {
                        jStar.attr("title", content[idx]);
                    } else {
                        jStar.attr("title", newVal);
                    }
                });
            };

            wijrating.prototype._resetHint = function (content) {
                var o = this.options, stars = $("." + o.wijCSS.wijratingNormalStar, this.ratingElement[0]);
                $.each(stars, function (idx, star) {
                    var jStar = $(star), val = parseFloat(jStar.html());
                    if (content && content.length && content.length >= idx && content[idx] && content[idx].length) {
                        jStar.attr("title", content[idx]);
                    } else {
                        jStar.attr("title", val);
                    }
                });
            };

            wijrating.prototype._clearIntentTimer = function () {
                if (this.intentTimers && this.intentTimers.length) {
                    $.each(this.intentTimers, function (i, timer) {
                        if (timer) {
                            window.clearTimeout(timer);
                            timer = null;
                        }
                    });
                }
                this.intentTimers = [];
            };

            wijrating.prototype._playJqueryAnimation = function (animation, allStars, animationComplete) {
                var _this = this;
                var self = this, o = self.options, animationOption = {
                    easing: animation.easing
                }, animated = animation.animated;
                self._clearIntentTimer();
                $.each(allStars, function (i, star) {
                    var hideDelay = Math.floor(i / o.split) * animation.delay, intentHideTimer;
                    intentHideTimer = window.setTimeout(function () {
                        $(star).hide(animated, animationOption, animation.duration, function () {
                            if (i !== allStars.length - 1) {
                                return;
                            }
                            $.each(allStars, function (idx, showStar) {
                                var showDelay = Math.floor(idx / o.split) * animation.delay, intentShowTimer;
                                intentShowTimer = window.setTimeout(function () {
                                    $(showStar).show(animated, animationOption, animation.duration, function () {
                                        if (idx === allStars.length - 1) {
                                            if (animationComplete && $.isFunction(animationComplete)) {
                                                animationComplete.call(_this);
                                            }
                                        }
                                    });
                                }, showDelay);
                                self.intentTimers.push(intentShowTimer);
                            });
                        });
                    }, hideDelay);
                    self.intentTimers.push(intentHideTimer);
                });
            };

            wijrating.prototype._addCustomizedIconsClass = function (iconsClass, split) {
                var self = this, o = self.options, stars, idx = 0, iconsIdx = 0;
                if (iconsClass && iconsClass.length) {
                    stars = $("." + o.wijCSS.wijratingNormalStar, self.ratingElement[0]);
                    $.each(stars, function (i, star) {
                        if (idx === split) {
                            idx = 0;
                            iconsIdx++;
                        }
                        if (typeof (iconsClass) === "string") {
                            $(star).addClass(iconsClass);
                        } else if ($.isArray(iconsClass)) {
                            var len = iconsClass.length;
                            if (iconsIdx < len) {
                                if (self.options.direction === "reversed") {
                                    $(star).addClass(iconsClass[len - iconsIdx - 1]);
                                } else {
                                    $(star).addClass(iconsClass[iconsIdx]);
                                }
                            }
                        }
                        idx++;
                    });
                }
            };

            wijrating.prototype._addCustomizedHoverIconsClass = function (hoverIconsClass, split, target) {
                var o = this.options, direction = o.direction, ratingMode = o.ratingMode, allStars = $("." + o.wijCSS.wijratingNormalStar, this.ratingElement[0]), tarIdx = allStars.index(target), iconIdx = 0, idx;
                if (hoverIconsClass && hoverIconsClass.length) {
                    if (typeof (hoverIconsClass) === "string") {
                        target.addClass(hoverIconsClass);
                        if (ratingMode !== "single") {
                            if (direction === "reversed") {
                                target.parent().nextAll().children().addClass(hoverIconsClass);
                            } else {
                                target.parent().prevAll().children().addClass(hoverIconsClass);
                            }
                        }
                    } else if ($.isArray(hoverIconsClass)) {
                        if (ratingMode === "single") {
                            if (direction === "reversed") {
                                idx = allStars.length - 1 - tarIdx;
                            } else {
                                idx = tarIdx;
                            }
                            iconIdx = Math.floor(idx / split);
                            if (hoverIconsClass.length > iconIdx) {
                                target.addClass(hoverIconsClass[iconIdx]);
                            }
                        } else {
                            if (direction === "reversed") {
                                for (idx = allStars.length - 1; idx >= tarIdx; idx--) {
                                    iconIdx = Math.floor((allStars.length - 1 - idx) / split);
                                    if (hoverIconsClass.length > iconIdx) {
                                        $(allStars[idx]).addClass(hoverIconsClass[iconIdx]);
                                    }
                                }
                            } else {
                                for (idx = 0; idx <= tarIdx; idx++) {
                                    iconIdx = Math.floor(idx / split);
                                    if (hoverIconsClass.length > iconIdx) {
                                        $(allStars[idx]).addClass(hoverIconsClass[iconIdx]);
                                    }
                                }
                            }
                        }
                    }
                }
            };

            wijrating.prototype._removeCustomizedIconsClass = function (iconsClass) {
                var o = this.options, allStars = $("." + o.wijCSS.wijratingNormalStar, this.ratingElement[0]);
                if (iconsClass && iconsClass.length) {
                    if (typeof (iconsClass) === "string") {
                        allStars.removeClass(iconsClass);
                    } else if ($.isArray(iconsClass)) {
                        $.each(iconsClass, function (idx, iconClass) {
                            allStars.removeClass(iconClass);
                        });
                    }
                }
            };

            wijrating.prototype._parseSelect = function () {
                var o = this.options, hintValues = [], opts = $("option", this.element);
                if (opts.length) {
                    o.count = opts.length;
                    o.totalValue = opts.length;
                    $.each(opts, function (idx, opt) {
                        var jOpt = $(opt);
                        hintValues.push(jOpt.html());
                        if (jOpt.is(":selected")) {
                            o.value = idx + 1;
                        }
                    });
                    o.hint.content = hintValues;
                }
            };

            wijrating.prototype._parseRadio = function () {
                var self = this, o = self.options, hintValues = [], radios = $("input[type='radio']", self.element);
                if (radios.length) {
                    o.count = radios.length;
                    o.totalValue = radios.length;
                    $.each(radios, function (idx, radio) {
                        var jRadio = $(radio), radioId = jRadio.attr("id"), jLabel;
                        if (radioId && radioId.length > 0) {
                            jLabel = $("label[for='" + radioId + "']", self.element);
                            if (jLabel.length) {
                                hintValues.push(jLabel.html());
                            } else {
                                hintValues.push("");
                            }
                        } else {
                            hintValues.push("");
                        }
                        if (jRadio.is(":checked")) {
                            o.value = idx + 1;
                        }
                    });
                    o.hint.content = hintValues;
                }
            };
            return wijrating;
        })(wijmo.wijmoWidget);
        rating.wijrating = wijrating;

        var wijrating_options = (function () {
            function wijrating_options() {
                /** @ignore*/
                this.wijCSS = {
                    wijrating: "wijmo-wijrating",
                    wijratingStarContainer: "wijmo-wijrating-starcontainer",
                    wijratingResetButton: "wijmo-wijrating-reset",
                    wijratingHoverResetButton: "wijmo-wijrating-resethover",
                    wijratingStar: "wijmo-wijrating-star",
                    wijratingNormalStar: "wijmo-wijrating-normal",
                    wijratingHoverStar: "wijmo-wijrating-hover",
                    wijratingRatedStar: "wijmo-wijrating-rated",
                    wijvRating: "wijmo-wijrating-vertical"
                };
                /** @ignore*/
                this.wijMobileCSS = {
                    iconClose: "ui-icon-delete"
                };
                /** A value that determines whether or not to disable the rating widget. */
                this.disabled = false;
                /** A value that determines the number of stars to display. */
                this.count = 5;
                /** An option that determines the number of sections into which each star will be split. */
                this.split = 1;
                /** An option that determines the total value of the rating widget.
                * @remarks For example, in a rating widget with 5 stars the count is 5. A split of 2 means that each star is split into two parts.
                * If the totalValue of the stars is 100, then each part of the split star has a value of 10 and each whole star has a value of 20.
                * The step can be represented by this equation: 100/(5 * 2) = 10 and the value of one star can be represented by this equation: 10*(1 * 2) = 20.
                */
                this.totalValue = 5;
                /** An option that determines the rated value of the rating widget. */
                this.value = 0;
                /** An option that defines the minimum value that can be rated using the rating widget.
                * @type {number}
                */
                this.min = null;
                /** An option that defines the maximum value that can be rated using the rating widget.
                * @type {number}
                */
                this.max = null;
                /** The resetButton option determines the properties of the widget's reset button.
                * @remarks The reset button is used to reset the rated value to 0.
                * If the rating widget is disabled, the reset button will be hidden.
                */
                this.resetButton = {
                    /** An option that determines whether to show the reset button. */
                    disabled: false,
                    /** An option that controls the text shown when hovering over the button. */
                    hint: "cancel this rating!",
                    /** The position sub-property defines the resetButton's position in relation to the rating widget.
                    * @remarks Options are "leftOrTop", "rightOrBottom".
                    */
                    position: "leftOrTop",
                    /** The value that controls the customized class added to the reset button. */
                    customizedClass: "",
                    /** An option that controls the customized class added to the reset button when a user hovers over it. */
                    customizedHoverClass: ""
                };
                /** A value that controls the hint information shown when hovering over the rating star. */
                this.hint = {
                    /** An option that determines whether or not to show the hint. */
                    disabled: false,
                    /** An option that determines the values that will be shown when a star is hovered over.
                    * @type {array}
                    * @remarks If the content is null and disabled is false, then the hint will
                    * show the value of each star.
                    */
                    content: null
                };
                /** The orientation option determines the orientation of the rating widget.
                * @remarks Options are "horizontal" and "vertical".
                */
                this.orientation = "horizontal";
                /** The direction option determines the direction in which items are rated.
                * @remarks Options are "normal" and "reversed". The "normal" represents rating
                * from left to right or top to bottom.
                */
                this.direction = "normal";
                /** The ratingMode option determines how the widget performs the rating function.
                * The widget can rate things continuously or singly.
                * @remarks Options are "continuous" and "single". The "single" option represents
                * that only one star can be rated, while "continuous" represents that
                * all the stars from first to the rated one will be rated.
                */
                this.ratingMode = "continuous";
                /** A value that indicates the settings for customized rating icons. */
                this.icons = {
                    /** A string or an array value that indicates the urls of icons.
                    * @type {string|array}
                    * @remarks If the value is a string, then all the star will apply the iconsClass.
                    * If the value is an array, then each star will apply the related
                    * iconsClass value by index.
                    */
                    iconsClass: null,
                    /** A string or an array value indicates the urls of hover icons.
                    * @type {string|array}
                    * @remarks If the value is a string, then all the star will apply the iconsClass when hovered over.
                    * If the value is an array, then each star will apply the
                    * related iconsClass value by index when hovered over.
                    */
                    hoverIconsClass: null,
                    /** A string or an array value indicates the urls of rated icons.
                    * @type {string|array}
                    * @remarks If the value is a string, then all the rated star will apply the iconsClass.
                    * If the value is an array, then each rated star will apply the related
                    * iconsClass value by index.
                    */
                    ratedIconsClass: null
                };
                /** An option that determines the width of the icon. All icons should have the same width. */
                this.iconWidth = 16;
                /** An option that determines the height of the icon. All icons should have the same height. */
                this.iconHeight = 16;
                /** An option that controls aspects of the widget's animation,
                * such as the animation effect  and easing.
                * @type {object}
                * @remarks animation.animated defines the animation effect for the rating widget.
                * animation.duration defines the length of the animation effect in milliseconds.
                * animation.easing defines the easing effect of an animation.
                * animation.delay defines the length of the delay in milliseconds.
                */
                this.animation = null;
                /** The rating event fires before widget rating.
                * You can use this event if you'd like to track the rated values.
                * You can cancel this event by returning false.
                * @event
                * @dataKey {number} oldValue The previously rated value.
                * @dataKey {number} newValue The new value that is to be rated.
                * @dataKey target The rated object.
                */
                this.rating = null;
                /** The rated event fires after the widget is rated.
                * @event
                * @dataKey {number} value The rated value.
                * @dataKey target The rated object.
                */
                this.rated = null;
                /** The reset event fires when the reset button is clicked.
                * @event
                */
                this.reset = null;
                /** The hover event fires when a user hovers over a rating icon.
                * You can use this event to trigger something, such as an alert,
                * when a user hovers over one of the rating icons.
                * @event
                * @dataKey {number} value The value of hovered object.
                * @dataKey target The hovered object.
                */
                this.hover = null;
            }
            return wijrating_options;
        })();

        wijrating.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijrating_options());

        $.wijmo.registerWidget("wijrating", wijrating.prototype);

        //prevent jqm's default behavior for <select> markup.
        if ($.mobile && $.mobile.selectmenu && $.mobile.selectmenu.initSelector) {
            $.mobile.selectmenu.initSelector = $.mobile.selectmenu.initSelector + ":not( :jqmData(role='wijrating') )";
        }

        $.extend($.wijmo.wijrating, {
            animations: {
                scroll: function (options, stars, animationComplete) {
                    var o = options, aniCmp = animationComplete, duration = 250, delay = 500, easing = "linear", starDelay = 250, starsArr = jQuery.makeArray(stars);
                    starsArr.reverse();
                    $.each(starsArr, function (i, star) {
                        var hideDelay = Math.floor(i / o.split) * starDelay, showAnimate = {
                            width: 0
                        }, intentHideTimer, delayTimer;
                        intentHideTimer = window.setTimeout(function () {
                            $(star).animate(showAnimate, duration, easing, function () {
                                window.clearTimeout(intentHideTimer);
                                if (i !== stars.length - 1) {
                                    return;
                                }
                                delayTimer = window.setTimeout(function () {
                                    $.each(stars, function (idx, showStar) {
                                        var showDelay = Math.floor(idx / o.split) * starDelay, hideAnimate = {
                                            width: o.iconWidth
                                        }, intentShowTimer;
                                        intentShowTimer = window.setTimeout(function () {
                                            $(showStar).animate(hideAnimate, duration, easing, function () {
                                                window.clearTimeout(intentShowTimer);
                                                if (idx === stars.length - 1) {
                                                    if (aniCmp && $.isFunction(aniCmp)) {
                                                        //aniCmp.call(this);
                                                        aniCmp.call();
                                                    }
                                                }
                                            });
                                        }, showDelay);
                                    });
                                    window.clearTimeout(delayTimer);
                                }, delay);
                            });
                        }, hideDelay);
                    });
                    if (animationComplete && $.isFunction(animationComplete)) {
                        //animationComplete.call(this);
                        animationComplete.call();
                    }
                }
            }
        });

        ;

        ;
    })(wijmo.rating || (wijmo.rating = {}));
    var rating = wijmo.rating;
})(wijmo || (wijmo = {}));

;
/// <reference path="../wijchart/jquery.wijmo.wijchartcore.ts"/>
/// <reference path="../external/declarations/globalize.d.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*globals $, Raphael, jQuery, document, window, navigator*/
    /*
    * Depends:
    *  jquery.js
    *	raphael.js
    *  jquery.wijmo.raphael.js
    *	globalize.min.js
    *	jquery.ui.widget.js
    *	jquery.wijmo.wijchartcore.js
    *
    */
    (function (chart) {
        /**
        * @widget
        */
        var wijscatterchart = (function (_super) {
            __extends(wijscatterchart, _super);
            function wijscatterchart() {
                _super.apply(this, arguments);
            }
            wijscatterchart.prototype._create = function () {
                var self = this;
                self._handleChartStyles();
                _super.prototype._create.call(this);
                self.chartElement.addClass(self.options.wijCSS.scatter);
            };

            /**
            * Remove the functionality completely. This will return the element back to its pre-init state
            */
            wijscatterchart.prototype.destroy = function () {
                var self = this;

                self.chartElement.removeClass(self.options.wijCSS.scatter);
                _super.prototype.destroy.call(this);
            };

            /** Returns the scatter element with the given series index and scatter index.
            * @param {number} seriesIndex The index of the series
            * @param {number} scatterIndex The index of the scatter element
            * @returns {Raphael Element} if scatterIndex is not specified, return a list of scatters of specified seriesIndex,
            * else return the specified scatter element
            */
            wijscatterchart.prototype.getScatter = function (seriesIndex, scatterIndex) {
                var self = this, fields = self.chartElement.data("fields"), und, len, scatters, scatter;
                if (fields && fields.chartElements) {
                    scatters = fields.chartElements.scatters;
                    if (scatters && scatters.length) {
                        len = scatters.length;
                        if (seriesIndex < 0 || seriesIndex >= len) {
                            return und;
                        }
                        scatter = scatters[seriesIndex];
                        if (typeof scatterIndex === "undefined") {
                            return scatter;
                        }
                        len = scatter.length;
                        if (scatter && len) {
                            if (scatterIndex < 0 || scatterIndex >= len) {
                                return und;
                            }
                            return scatter[scatterIndex];
                        }
                    }
                    return und;
                }
            };

            wijscatterchart.prototype._getLegendbasicInfo = function () {
                var legendSize, legendOptions = _super.prototype._getLegendbasicInfo.call(this);

                legendSize = $.extend(true, {
                    width: 20,
                    height: 10,
                    r: 6
                }, this.options.legend.size);

                legendOptions.iconSize = $.extend(true, legendOptions.iconSize, legendSize);

                return legendOptions;
            };

            wijscatterchart.prototype._getLegendInfoFromSeries = function (seriesIdx, series, seriesStyle) {
                if (series.LegendEntry === false) {
                    return undefined;
                }

                var legendSize, iconStyle, markerStyle, legendInfo = _super.prototype._getLegendInfoFromSeries.call(this, seriesIdx, series, seriesStyle);

                iconStyle = legendInfo.iconStyle;
                markerStyle = $.extend({
                    fill: iconStyle.fill,
                    stroke: iconStyle.stroke,
                    opacity: 1
                }, series.markerStyle);

                legendInfo.iconStyle = markerStyle;

                if (series.markerType) {
                    legendInfo.icon = series.markerType;
                } else {
                    legendInfo.icon = "circle";
                }

                legendInfo.markers = undefined;
                legendInfo.markerVisible = false;
                legendInfo.markerStyle = undefined;

                return legendInfo;
            };

            wijscatterchart.prototype._showSerieEles = function (seriesEle) {
                if (seriesEle.isTrendline) {
                    chart.TrendlineRender.showSerieEles(seriesEle);
                    return;
                }
                $.each(seriesEle, function (i, dot) {
                    dot.show();
                    if (dot.label) {
                        dot.label.show();
                    }
                    if ($(dot.element).data("wijchartDataObj")) {
                        $(dot.element).data("wijchartDataObj").visible = true;
                    }
                });
            };

            wijscatterchart.prototype._hideSerieEles = function (seriesEle) {
                if (seriesEle.isTrendline) {
                    chart.TrendlineRender.hideSerieEles(seriesEle);
                    return;
                }
                $.each(seriesEle, function (i, dot) {
                    dot.hide();
                    if (dot.label) {
                        dot.label.hide();
                    }
                    if ($(dot.element).data("wijchartDataObj")) {
                        $(dot.element).data("wijchartDataObj").visible = false;
                    }
                });
            };

            wijscatterchart.prototype._indicatorLineShowing = function (objs) {
                _super.prototype._indicatorLineShowing.call(this, objs);
                $.each(objs, function (i, obj) {
                    if (obj.dot) {
                        obj.dot.attr(obj.hoverStyle);
                        obj.dot.scale(1.5, 1.5);
                    }
                });
            };

            wijscatterchart.prototype._removeIndicatorStyles = function (objs) {
                $.each(objs, function (i, obj) {
                    if (obj.dot) {
                        obj.dot.attr(obj.style);
                        obj.dot.scale(1, 1);
                    }
                });
            };

            wijscatterchart.prototype._paintTooltip = function () {
                var self = this, element = self.chartElement, fields = element.data("fields");
                _super.prototype._paintTooltip.call(this);
                if (self.tooltip) {
                    if (fields && fields.chartElements && fields.chartElements.tooltipTars) {
                        self.tooltip.setTargets(fields.chartElements.tooltipTars);
                        self.tooltip.setOptions({ mouseTrailing: false });
                    }
                }
            };

            wijscatterchart.prototype._getTooltipText = function (fmt, target) {
                var dataObj = $(target).data("wijchartDataObj"), obj = {
                    data: dataObj,
                    label: dataObj.label,
                    x: dataObj.x,
                    y: dataObj.y,
                    type: dataObj.markerType,
                    target: target,
                    fmt: fmt
                };
                return $.proxy(fmt, obj)();
            };

            wijscatterchart.prototype._onBeforeTooltipShowing = function (tooltip) {
                var self = this, o = tooltip.options, hintStyle = self.options.hint.style, target = tooltip.target, obj, dotStyle;

                if (target) {
                    if ($.browser.msie && parseInt($.browser.version) < 9) {
                        obj = $(target).data().wijchartDataObj;
                        dotStyle = obj.style;
                        o.style.stroke = hintStyle.stroke || dotStyle.stroke || dotStyle.fill || "#ffffff";
                    } else {
                        o.style.stroke = hintStyle.stroke || target.getAttribute("stroke") || target.getAttribute("fill") || "#ffffff";
                    }
                    target.attrs = { stroke: o.style.stroke };
                }

                _super.prototype._onBeforeTooltipShowing.call(this, tooltip);
            };

            wijscatterchart.prototype._clearChartElement = function () {
                var self = this, fields = self.chartElement.data("fields");

                self._stopAnimation();

                if (self.legendEles.length) {
                    $.each(self.legendEles, function (idx, legendEle) {
                        legendEle.wijRemove();
                        legendEle = null;
                    });
                    self.legendEles = [];
                }
                if (self.legends.length) {
                    $.each(self.legends, function (idx, legend) {
                        legend.wijRemove();
                        legend = null;
                    });
                    self.legends = [];
                }
                if (self.legendIcons.length) {
                    $.each(self.legendIcons, function (idx, legendIcon) {
                        legendIcon.wijRemove();
                        legendIcon = null;
                    });
                    self.legendIcons = [];
                }
                if (self.legendDots.length) {
                    $.each(self.legendDots, function (idx, legendDot) {
                        legendDot = null;
                    });
                    self.legendDots = [];
                }
                if (self.axisEles.length) {
                    $.each(self.axisEles, function (idx, axisEle) {
                        axisEle.wijRemove();
                        axisEle = null;
                    });
                    self.axisEles = [];
                }
                if (self.chartLabelEles.length) {
                    $.each(self.chartLabelEles, function (idx, chartLabelEle) {
                        chartLabelEle.wijRemove();
                        chartLabelEle = null;
                    });
                    self.chartLabelEles = [];
                }

                if (fields && fields.chartElements) {
                    $.each(fields.chartElements, function (key, eles) {
                        if (eles.length) {
                            $.each(eles, function (i, ele) {
                                if (ele[0] !== null) {
                                    if (ele.remove) {
                                        ele.remove();
                                    }
                                    eles[i] = null;
                                }
                            });
                        }
                        fields.chartElements[key] = null;
                    });
                    fields.chartElements = {};
                    $(fields.clipRect.element).stop().remove();
                    fields.render.destroy();
                    fields.clipRect.destroy();
                }

                self.dataPoints = null;
                self.pointXs = null;

                self.canvas.clear();
                self.innerState = {};
            };

            wijscatterchart.prototype._paintPlotArea = function () {
                var self = this, o = self.options;

                this.scatterRender = new ScatterChartRender(this.chartElement, {
                    annotations: o.annotations,
                    bounds: self.canvasBounds,
                    widgetName: self.widgetName,
                    canvas: self.canvas,
                    tooltip: self.tooltip,
                    axis: o.axis,
                    animation: o.animation,
                    seriesTransition: o.seriesTransition,
                    seriesList: o.seriesList,
                    seriesStyles: o.seriesStyles,
                    seriesHoverStyles: o.seriesHoverStyles,
                    hint: o.hint,
                    disabled: this._isDisabled(),
                    //plotInfo: plotInfo,
                    isXTime: self.axisInfo.x.isTime,
                    isYTime: self.axisInfo.y[0].isTime,
                    zoomOnHover: o.zoomOnHover,
                    mouseDown: $.proxy(self._mouseDown, self),
                    mouseUp: $.proxy(self._mouseUp, self),
                    mouseOver: $.proxy(self._mouseOver, self),
                    mouseOut: $.proxy(self._mouseOut, self),
                    mouseMove: $.proxy(self._mouseMove, self),
                    click: $.proxy(self._click, self),
                    showChartLabels: o.showChartLabels,
                    chartLabelStyle: o.chartLabelStyle,
                    chartLabelFormatString: o.chartLabelFormatString,
                    chartLabelFormatter: o.chartLabelFormatter,
                    culture: self._getCulture(),
                    wijCSS: o.wijCSS,
                    widget: this
                });
                this.scatterRender.render();
            };

            wijscatterchart.prototype._stopAnimation = function () {
                if (this.scatterRender) {
                    this.scatterRender.stopAnimation();
                }
            };
            return wijscatterchart;
        })(chart.wijchartcore);
        chart.wijscatterchart = wijscatterchart;

        wijscatterchart.prototype.widgetEventPrefix = "wijscatterchart";

        var wijscatterchart_css = (function (_super) {
            __extends(wijscatterchart_css, _super);
            function wijscatterchart_css() {
                _super.apply(this, arguments);
                this.scatter = "wijmo-wijscatterchart";
                this.scatterElement = "wijscatterchart";
            }
            return wijscatterchart_css;
        })(chart.wijchartcore_css);
        chart.wijscatterchart_css = wijscatterchart_css;

        var wijscatterchart_options = (function (_super) {
            __extends(wijscatterchart_options, _super);
            function wijscatterchart_options() {
                _super.apply(this, arguments);
                /**
                * Selector option for auto self initialization. This option is internal.
                * @ignore
                */
                this.initSelector = ":jqmData(role='wijscatterchart')";
                /**
                * @ignore
                */
                this.wijCSS = new wijmo.chart.wijscatterchart_css();
                /**
                * An option that controls aspects of the widget's animation, such as duration and easing.
                */
                this.animation = {
                    /**
                    * A value that determines whether to show animation.
                    */
                    enabled: true,
                    /**
                    * A value that indicates the duration for the animation.
                    */
                    duration: 2000,
                    /**
                    * Sets the type of animation easing effect that users experience when the wijscatterchart series is loaded to the page.
                    * @remarks
                    * For example, a user can have the wijscatterchart series bounce several times as it loads.
                    * The easing is defined in Raphael, the documentation is: http://raphaeljs.com/reference.html#Raphael.easing_formulas
                    */
                    easing: ">"
                };
                /**
                * A value that indicates whether to show default chart labels.
                */
                this.showChartLabels = false;
                /**
                * The seriesTransition option is used to animate series in the chart when just their values change.
                * @remarks
                * This is helpful for visually showing changes in data for the same series.
                */
                this.seriesTransition = {
                    /**
                    * A value that determines whether to show animation when reloading data.
                    */
                    enabled: true,
                    /**
                    * A value that indicates the duration for the series transition.
                    */
                    duration: 2000,
                    /**
                    * A value that indicates the easing for the series transition.
                    * @remarks
                    * The easing is defined in Raphael, the documentation is: http://raphaeljs.com/reference.html#Raphael.easing_formulas
                    */
                    easing: ">"
                };
                /**
                * A value that indicates whether to zoom in on the marker on hover.
                */
                this.zoomOnHover = true;
                /**
                * Occurs when the user clicks a mouse button.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {IScatterChartEventArgs} data Information about an event
                */
                this.mouseDown = null;
                /**
                * Fires when the user releases a mouse button while the pointer is over the chart element.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {IScatterChartEventArgs} data Information about an event
                */
                this.mouseUp = null;
                /**
                * Fires when the user first places the pointer over the chart element.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {IScatterChartEventArgs} data Information about an event
                */
                this.mouseOver = null;
                /**
                * Fires when the user moves the pointer off of the chart element.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {IScatterChartEventArgs} data Information about an event
                */
                this.mouseOut = null;
                /**
                * Fires when the user moves the mouse pointer while it is over a chart element.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {IScatterChartEventArgs} data Information about an event
                */
                this.mouseMove = null;
                /**
                * Fires when the user clicks the chart element.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {IScatterChartEventArgs} data Information about an event
                */
                this.click = null;
            }
            return wijscatterchart_options;
        })(chart.wijchartcore_options);

        wijscatterchart.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijscatterchart_options());

        $.wijmo.registerWidget("wijscatterchart", wijscatterchart.prototype);

        /** @ignore */
        var ScatterChartRender = (function (_super) {
            __extends(ScatterChartRender, _super);
            function ScatterChartRender(element, options) {
                _super.call(this, element, options);
                this.scatters = [];
                this.chartLabels = [];
                this.tooltipTars = [];
                this.seriesEles = [];
                this.paths = [];
                this.aniPathsAttr = [];
                this.fieldsAniPathAttr = [];
            }
            ScatterChartRender.prototype._init = function () {
                _super.prototype._init.call(this);
                var self = this, element = self.element, o = self.options, canvas = o.canvas, bounds = o.bounds, minX = o.axis.x.min, minY = o.axis.y.min, maxX = o.axis.x.max, maxY = o.axis.y.max;

                self.plotInfo = {
                    minX: minX,
                    minY: minY,
                    maxX: maxX,
                    maxY: maxY,
                    width: self.width,
                    height: self.height,
                    kx: self.width / (maxX - minX),
                    ky: self.height / (maxY - minY)
                };

                if (element.find("svg").length > 0) {
                    self.chartRender = chart.render.createRender(canvas, element.find("svg").get(0), element.width(), element.height());
                } else {
                    self.chartRender = chart.render.createRender(canvas, element.children(":first").addClass("vmlcontainer").get(0), element.width(), element.height());
                }

                self.clipRect = self.chartRender.clipRect(0, 0, 0, element.height());
                self.g = self.chartRender.g();
                self.g.clip(self.clipRect);
                self.g.add();

                self.fields.render = self.chartRender;
                self.fields.clipRect = self.clipRect;
                self.animationSet = self.options.canvas.set();
            };

            ScatterChartRender.prototype.bindLiveEvents = function () {
                var isFunction = $.isFunction, o = this.options, wijCSS = o.wijCSS, element = this.element, widgetName = o.widgetName, mouseDown = o.mouseDown, mouseUp = o.mouseUp, mouseOver = o.mouseOver, mouseOut = o.mouseOut, mouseMove = o.mouseMove, click = o.click, zoomOnHover = o.zoomOnHover, seriesHoverStyles = o.seriesHoverStyles, seriesStyles = o.seriesStyles, disabled = o.disabled, touchEventPre = "";

                if ($.support.isTouchEnabled && $.support.isTouchEnabled()) {
                    touchEventPre = "wij";
                }

                $("." + wijCSS.scatterElement, element[0]).on(touchEventPre + "mousedown." + widgetName, function (e) {
                    if (disabled) {
                        return;
                    }
                    if (isFunction(mouseDown)) {
                        var dataObj = $(e.target).data("wijchartDataObj");
                        if (!dataObj) {
                            dataObj = $(e.target.parentNode).data("wijchartDataObj");
                        }
                        mouseDown.call(element, e, dataObj);
                    }
                }).on(touchEventPre + "mouseup." + widgetName, function (e) {
                    if (disabled) {
                        return;
                    }
                    if (isFunction(mouseUp)) {
                        var dataObj = $(e.target).data("wijchartDataObj");
                        if (!dataObj) {
                            dataObj = $(e.target.parentNode).data("wijchartDataObj");
                        }
                        mouseUp.call(element, e, dataObj);
                    }
                }).on(touchEventPre + "mouseover." + widgetName, function (e) {
                    if (disabled) {
                        return;
                    }
                    var dataObj = $(e.target).data("wijchartDataObj"), seriesIndex, style, dot;
                    if (!dataObj) {
                        dataObj = $(e.target.parentNode).data("wijchartDataObj");
                    }
                    dot = dataObj.dot;
                    if (zoomOnHover) {
                        seriesIndex = dataObj.seriesIndex;
                        if (dot.attr) {
                            //								style = $.extend(true, dot.attr(),
                            //									seriesHoverStyles[seriesIndex]);
                            style = $.extend(true, {}, seriesHoverStyles[seriesIndex]);
                            dot.attr(style);
                        }
                        if (document.createElementNS) {
                            dot.scale(1.5, 1.5);
                        } else {
                            dot.attr("stroke-width", 5);
                        }
                    }
                    if (isFunction(mouseOver)) {
                        mouseOver.call(element, e, dataObj);
                    }
                }).on(touchEventPre + "mouseout." + widgetName, function (e) {
                    if (disabled) {
                        return;
                    }
                    var dataObj = $(e.target).data("wijchartDataObj"), seriesIndex, dot;
                    if (!dataObj) {
                        dataObj = $(e.target.parentNode).data("wijchartDataObj");
                    }
                    dot = dataObj.dot;
                    if (zoomOnHover) {
                        seriesIndex = dataObj.seriesIndex;
                        if (dot.attr) {
                            dot.attr($.extend(true, {}, seriesStyles[seriesIndex]));
                        }
                    }
                    if (document.createElementNS) {
                        dot.scale(1, 1);
                    }
                    if (isFunction(mouseOut)) {
                        mouseOut.call(element, e, dataObj);
                    }
                }).on(touchEventPre + "mousemove." + widgetName, function (e) {
                    if (disabled) {
                        return;
                    }
                    if (isFunction(mouseMove)) {
                        var dataObj = $(e.target).data("wijchartDataObj");
                        if (!dataObj) {
                            dataObj = $(e.target.parentNode).data("wijchartDataObj");
                        }
                        mouseMove.call(element, e, dataObj);
                    }
                }).on(touchEventPre + "click." + widgetName, function (e) {
                    if (disabled) {
                        return;
                    }
                    if (isFunction(click)) {
                        var dataObj = $(e.target).data("wijchartDataObj");
                        if (!dataObj) {
                            dataObj = $(e.target.parentNode).data("wijchartDataObj");
                        }
                        click.call(element, e, dataObj);
                    }
                });
                chart.TrendlineRender.bindLiveEvents(element, widgetName, mouseDown, mouseUp, mouseOver, mouseOut, mouseMove, click, disabled, wijCSS, false);
            };

            ScatterChartRender.prototype.unbindLiveEvents = function () {
                var o = this.options, widgetName = o.widgetName, wijCSS = o.wijCSS;
                $("." + wijCSS.scatterElement, this.element).off(widgetName).off("." + widgetName);

                chart.TrendlineRender.unbindLiveEvents(this.element, widgetName, wijCSS);
            };

            ScatterChartRender.prototype.paintDefaultChartLabel = function (x, y, points) {
                var o = this.options, textStyle = $.extend(true, { "font-size": "10px", fill: "#888", "font-family": "Arial" }, o.textStyle, o.chartLabelStyle), text, chartLabelFormatString = o.chartLabelFormatString, dcl, val = points.y, processedChartLabel;

                if (o.isYTime) {
                    text = Globalize.format(val, "f", o.culture);
                } else {
                    text = $.round(val, 2);
                }

                processedChartLabel = chart.ChartUtil.getChartLabel(chartLabelFormatString, text, o.culture, {
                    index: points.sIdx,
                    data: { x: points.x, y: points.y },
                    value: val,
                    chartLabelFormatter: o.chartLabelFormatter
                });

                text = processedChartLabel.text;
                dcl = this.chartRender.text(x, y, text);
                dcl.raphaelObj.wijAttr(textStyle);
                return dcl;
            };

            ScatterChartRender.prototype.paintScatters = function () {
                var self = this, o = self.options, seriesList = o.seriesList, seriesStyles = o.seriesStyles, seriesHoverStyles = o.seriesHoverStyles, isXTime = o.isXTime, isYTime = o.isYTime, bounds = o.bounds, plotInfo = this.plotInfo, wijCSS = o.wijCSS, showChartLabels = o.showChartLabels, labelStyle = o.chartLabelStyle, widget = o.widget, shadowPaths = [];

                self.annoPoints = {};
                $.each(seriesList, function (i, series) {
                    var data = series.data, type, markerWidth = series.markerWidth || 5, style = seriesStyles[i], hoverStyle = seriesHoverStyles[i], valuesX = data.x, valuesY = data.y, scatter = [], seriesEle = [], pointX;

                    if (series.isTrendline) {
                        chart.TrendlineRender.renderSingleTrendLine(series, seriesStyles[i], seriesHoverStyles[i], o.axis, undefined, self.fieldsAniPathAttr, o.animation, o.seriesTransition, i, bounds, o.canvas, self.paths, shadowPaths, self.animationSet, self.aniPathsAttr, wijCSS, self.seriesEles, false, o.shadow);
                        return true;
                    }
                    series = $.extend(true, {
                        visible: true,
                        markerType: "circle"
                    }, series);
                    type = series.markerType;

                    if (series.display === "exclude") {
                        return true;
                    }

                    if (!style.fill && style.stroke) {
                        style.fill = style.stroke;
                    }
                    if (valuesX === undefined) {
                        return true;
                    }
                    $.each(valuesY, function (j, valY) {
                        var valX = valuesX[j], X = 0, Y = 0, val, dot, chartLabel, dotData = {};
                        if (isXTime) {
                            valX = $.toOADate(valX);
                        }
                        if (isYTime) {
                            valY = $.toOADate(valY);
                        }
                        if (typeof (valX) === "undefined") {
                            return false;
                        }

                        if (isNaN(valX) || typeof valX === "string") {
                            val = j;
                        } else {
                            val = valX;
                        }
                        X = bounds.startX + (val - plotInfo.minX) * plotInfo.kx;
                        Y = bounds.endY - (valY - plotInfo.minY) * plotInfo.ky;

                        if (style.opacity) {
                            style["fill-opacity"] = style.opacity;
                            style["stroke-opacity"] = style.opacity;
                            delete (style.opacity);
                        }

                        if (type === "cross" && style["stroke-width"] !== undefined && style["stroke-width"] === 0) {
                            style["stroke-width"] = 1;
                        }

                        //handle gradient fill.
                        //fill = style.fill;
                        //fill = fill.replace(/[\(\)\s,\xb0#]/g, "_");
                        dot = self.chartRender.symbol(type, X, Y, markerWidth);
                        dot.attr(style);
                        dot.add(self.g);
                        dot.attr({
                            "class": wijCSS.canvasObject + " " + wijCSS.scatterElement
                        });

                        dotData = $.extend(false, {
                            dot: dot,
                            x: valuesX[j],
                            y: valuesY[j],
                            seriesIndex: i,
                            index: j,
                            markerType: type,
                            type: "scatter",
                            style: style,
                            hoverStyle: hoverStyle,
                            visible: true
                        }, series);

                        // paint label
                        if (showChartLabels) {
                            chartLabel = self.paintDefaultChartLabel(X, Y - 6, { x: valuesX[j], y: valuesY[j], sIdx: i });
                            chartLabel.add(self.g);
                            dot.label = chartLabel;
                            self.chartLabels.push(chartLabel);
                        }

                        if (self.annoPoints[i] == null)
                            self.annoPoints[i] = {};
                        self.annoPoints[i][j] = { x: X, y: Y };

                        // cache the bar position to show indicator line.
                        widget.dataPoints = widget.dataPoints || {};
                        widget.pointXs = widget.pointXs || [];

                        pointX = $.round(X, 2);

                        if (!widget.dataPoints[pointX.toString()]) {
                            widget.dataPoints[pointX.toString()] = [];
                            widget.pointXs.push(pointX);
                        }

                        widget.dataPoints[pointX.toString()].push(dotData);

                        $(dot.element).data("wijchartDataObj", dotData);
                        scatter.push(dot);

                        self.tooltipTars.push($.extend({}, dot, { node: dot.element }));
                        seriesEle.push(dot);
                        if (series.visible === false) {
                            dot.hide();
                        }
                    });
                    self.scatters.push(scatter);
                    self.seriesEles.push(seriesEle);
                });
                self.fields.trendLines = self.paths;
            };

            ScatterChartRender.prototype.playAnimation = function () {
                var self = this, o = self.options, ani = o.animation, element = self.element, bgColor = element.css("background-color");

                if (ani.enabled) {
                    if (bgColor === "transparent") {
                        bgColor = "white";
                    }
                    if (self.clipRect.getCSS) {
                        $(self.clipRect.members[0].element).animate({ width: element.width() }, {
                            duration: ani.duration,
                            step: function (val) {
                                self.clipRect.width = val;
                                var clipcss = self.clipRect.getCSS();
                                $(this).css(clipcss);
                            }
                        });
                    } else {
                        $(self.clipRect.element).animate({ width: element.width() }, {
                            duration: ani.duration,
                            step: function (val) {
                                self.clipRect.attr("width", val);
                            }
                        });
                    }
                } else {
                    if (self.clipRect.getCSS) {
                        $(self.clipRect.members[0].element).css({ width: element.width() });
                        self.clipRect.width = element.width();
                        $(self.clipRect.members[0].element).css(self.clipRect.getCSS());
                    } else {
                        $(self.clipRect.element).css({ width: element.width() });
                        self.clipRect.attr("width", element.width());
                    }
                }
            };

            ScatterChartRender.prototype.playTrendLineAnimation = function () {
                var self = this, o = self.options, animation = o.animation, animated = animation && animation.enabled, seriesTransition = o.seriesTransition, trendLines = self.fields.trendLines, duration, easing;

                if (animated) {
                    duration = animation.duration || 2000;
                    easing = animation.easing || "linear";
                    if (trendLines && trendLines.length) {
                        chart.TrendlineRender.playAnimation(animated, duration, easing, seriesTransition, o.bounds, trendLines, self.fieldsAniPathAttr, o.axis, o.widget.extremeValue);
                    }
                }
            };

            ScatterChartRender.prototype.stopAnimation = function () {
                if (this.clipRect.members && this.clipRect.members.length > 0) {
                    $(this.clipRect.members[0].element).stop(true);
                } else {
                    $(this.clipRect.element).stop(true);
                }
            };

            ScatterChartRender.prototype.render = function () {
                this.paintScatters();
                this.playAnimation();
                this.playTrendLineAnimation();
                this.unbindLiveEvents();
                this.bindLiveEvents();
                this.chartEles = {
                    animationSet: this.animationSet,
                    tooltipTars: this.tooltipTars,
                    scatters: this.scatters,
                    labels: this.chartLabels,
                    trendLines: this.paths
                };
                if (!this.fields.chartElements) {
                    this.fields.chartElements = {};
                }
                this.fields.seriesEles = this.seriesEles;
                $.extend(true, this.fields.chartElements, this.chartEles);
                this.element.data("fields", this.fields);
                _super.prototype.render.call(this);
            };
            return ScatterChartRender;
        })(chart.BaseChartRender);
        chart.ScatterChartRender = ScatterChartRender;

        
    })(wijmo.chart || (wijmo.chart = {}));
    var chart = wijmo.chart;
})(wijmo || (wijmo = {}));

var wijmo;
(function (wijmo) {
    (function (chart) {
        /** @ignore */
        (function (render) {
            var doc = document, each = $.each, isIE = $.browser.msie, docMode8 = doc.documentMode === 8, SVG_NS = 'http://www.w3.org/2000/svg', hasSVG = !!doc.createElementNS && !!doc.createElementNS(SVG_NS, 'svg')["createSVGRect"], _counter = 0, DIV = 'div', ABSOLUTE = 'absolute', HIDDEN = 'hidden', PREFIX = 'scatterchart-', VISIBLE = 'visible', VISIBILITY = "visibility", PX = 'px', NONE = 'none', M = 'M', L = 'L', regRadialGradient = /^r(?:\(([^,]+?)[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*([^\)]+?)\))?/, regLinearGradient = /^(\d{1,3})\-(?:((?:[a-zA-Z]+)|(?:\#[0-9a-fA-F]{6})|(?:\#[0-9a-fA-F]{3}))\-)(?:(?:((?:(?:[a-zA-Z]+)|(?:\#[0-9a-fA-F]{6})|(?:\#[0-9a-fA-F]{3}))(?:\:\d{1,3})?)\-)?)*((?:[a-zA-Z]+)|(?:\#[0-9a-fA-F]{6})|(?:\#[0-9a-fA-F]{3}))$/;

            function isString(s) {
                return typeof s === 'string';
            }

            function isNumber(n) {
                return typeof n === 'number';
            }

            function defined(obj) {
                return obj !== undefined && obj !== null;
            }

            function attr(elem, prop, value) {
                var setAttr = 'setAttribute', ret;

                if (isString(prop)) {
                    if (defined(value)) {
                        elem[setAttr](prop, value);
                    } else if (elem && elem.getAttribute) {
                        ret = elem.getAttribute(prop);
                    }
                } else if (defined(prop) && $.isPlainObject(prop)) {
                    $.each(prop, function (key, val) {
                        elem[setAttr](key, val);
                    });
                }
                return ret;
            }

            function css(el, styles) {
                if (isIE) {
                    if (styles && styles.opacity !== undefined) {
                        styles.filter = 'alpha(opacity=' + (styles.opacity * 100) + ')';
                    }
                }
                $.extend(el.style, styles);
            }

            function createElement(tag, attribs, styles) {
                var el = doc.createElement(tag);
                if (attribs) {
                    $.extend(el, attribs);
                }
                if (styles) {
                    css(el, styles);
                }
                return el;
            }

            function destroyObjectProperties(obj) {
                $.each(obj, function (key, node) {
                    if (obj[key] && obj[key].destroy) {
                        obj[key].destroy();
                    }
                    delete obj[key];
                });
            }

            var ChartElement = (function () {
                function ChartElement() {
                }
                ChartElement.prototype.attr = function (hash, val) {
                };
                ChartElement.prototype.scale = function (x, y) {
                };
                ChartElement.prototype.symbolAttr = function (hash) {
                };
                ChartElement.prototype.clip = function (clipRect) {
                };
                ChartElement.prototype.crisp = function (strokeWidth, x, y, width, height) {
                };
                ChartElement.prototype.css = function (styles) {
                };
                ChartElement.prototype.getBBox = function () {
                };
                ChartElement.prototype.show = function () {
                };
                ChartElement.prototype.hide = function () {
                };
                ChartElement.prototype.add = function (parent) {
                };
                ChartElement.prototype.destroy = function () {
                };
                ChartElement.prototype.empty = function () {
                };
                ChartElement.prototype.remove = function () {
                };
                return ChartElement;
            })();
            render.ChartElement = ChartElement;

            var ChartRender = (function () {
                function ChartRender(raphaelCanvas, container, width, height) {
                }
                ChartRender.prototype.destroy = function () {
                };
                ChartRender.prototype.createElement = function (nodeName) {
                };
                ChartRender.prototype.path = function (path) {
                    return this._element;
                };
                ChartRender.prototype.circle = function (x, y, r) {
                    return this._element;
                };
                ChartRender.prototype.rect = function (x, y, width, height, r, strokeWidth) {
                    return this._element;
                };
                ChartRender.prototype.setSize = function (width, height) {
                };
                ChartRender.prototype.g = function (name) {
                    return this._element;
                };
                ChartRender.prototype.text = function (x, y, text) {
                    return this._element;
                };
                ChartRender.prototype.symbol = function (_symbol, x, y, radius, options) {
                    return this._element;
                };

                ChartRender.prototype.clipRect = function (x, y, width, height) {
                    return this._element;
                };
                return ChartRender;
            })();
            render.ChartRender = ChartRender;

            var SVGElement = (function (_super) {
                __extends(SVGElement, _super);
                function SVGElement() {
                    _super.apply(this, arguments);
                }
                SVGElement.prototype.init = function (renderer, nodeName) {
                    this.element = doc.createElementNS(SVG_NS, nodeName);
                    this.renderer = renderer;
                };

                SVGElement.prototype.attr = function (hash, val) {
                    var key, value, element = this.element, renderer = this.renderer, nodeName = element.nodeName, skipAttr, raphaelObj, ret = this;

                    if (hash === undefined) {
                        return;
                    }

                    if (isString(hash) && defined(val)) {
                        key = hash;
                        hash = {};
                        hash[key] = val;
                    }

                    if (isString(hash)) {
                        key = hash;
                        if (nodeName === 'circle') {
                            key = { x: 'cx', y: 'cy' }[key] || key;
                        }
                        ret = attr(element, key) || this[key] || 0;

                        if (key !== 'd' && key !== VISIBILITY) {
                            ret = parseFloat(ret);
                        }
                    } else if (hash) {
                        raphaelObj = this.raphaelObj;
                        if (raphaelObj && raphaelObj.attr) {
                            raphaelObj.attr(hash);

                            $.each(["visibility", "class"], function (keyIdx, keyNm) {
                                if (keyNm in hash) {
                                    value = hash[keyNm];
                                    switch (keyNm) {
                                        case "visibility":
                                            if (value === VISIBLE) {
                                                raphaelObj.show();
                                            } else if (value === HIDDEN) {
                                                raphaelObj.hide();
                                            }
                                            break;
                                        default:
                                            attr(element, keyNm, value);
                                            break;
                                    }
                                }
                            });

                            return ret;
                        }

                        $.each(hash, function (key, v) {
                            skipAttr = false;
                            value = hash[key];
                            if (key === 'd') {
                                if (value && value.join) {
                                    value = value.join(' ');
                                }
                                if (/(NaN| {2}|^$)/.test(value)) {
                                    value = 'M 0 0';
                                }
                                this.d = value;
                                // apply gradients
                            } else if (key === 'fill') {
                                value = renderer._color(value, element, key);
                            } else if (key === 'transform') {
                                value = renderer._transform(hash[key], element);
                            } else if (nodeName === 'circle' && (key === 'x' || key === 'y')) {
                                key = { x: 'cx', y: 'cy' }[key] || key;
                            }

                            if (jQuery.browser.safari && key === 'stroke-width' && value === 0) {
                                value = 0.000001;
                            }
                            if (!skipAttr) {
                                attr(element, key, value);
                            }

                            // Fixed an issue that in composite chart, when show the tooltip, the chart will throw javascript exception
                            // save the attribute to attrs
                            element.attrs = element.attrs || {};
                            element.attrs[key] = value;
                        });
                    }
                    return ret;
                };

                SVGElement.prototype.scale = function (x, y) {
                    this.attr("transform", "S" + x + "," + y);
                };

                SVGElement.prototype.symbolAttr = function (hash) {
                    var self = this;
                    each(['x', 'y', 'r', 'start', 'end', 'width', 'height', 'innerR'], function (i, key) {
                        if (hash[key]) {
                            self[key] = hash[key];
                        } else {
                            self[key] = self[key];
                        }
                    });

                    self.attr({
                        d: self.renderer.symbols[self.symbolName](Math.round(self.x * 2) / 2, Math.round(self.y * 2) / 2, self.r, {
                            start: self.start,
                            end: self.end,
                            width: self.width,
                            height: self.height,
                            innerR: self.innerR
                        })
                    });
                };

                SVGElement.prototype.clip = function (clipRect) {
                    return this.attr('clip-path', 'url(' + this.renderer.url + '#' + clipRect.id + ')');
                };
                SVGElement.prototype.crisp = function (strokeWidth, x, y, width, height) {
                    var self = this, key, attr = {}, values = {}, normalizer;

                    strokeWidth = strokeWidth || self.strokeWidth || 0;
                    normalizer = strokeWidth % 2 / 2;
                    values.x = Math.floor(x || self.x || 0) + normalizer;
                    values.y = Math.floor(y || self.y || 0) + normalizer;
                    values.width = Math.floor((width || self.width || 0) - 2 * normalizer);
                    values.height = Math.floor((height || self.height || 0) - 2 * normalizer);
                    values.strokeWidth = strokeWidth;

                    for (key in values) {
                        if (self[key] !== values[key]) {
                            self[key] = attr[key] = values[key];
                        }
                    }

                    return attr;
                };

                SVGElement.prototype.css = function (styles) {
                    var self = this, elem = self.element, textWidth = styles && styles.width && elem.nodeName === 'text', serializedCss = '', hyphenate = function (a, b) {
                        return '-' + b.toLowerCase();
                    };

                    if (styles && styles.color) {
                        styles.fill = styles.color;
                    }
                    styles = $.extend(self.styles, styles);
                    self.styles = styles;
                    if (isIE && !hasSVG) {
                        if (textWidth) {
                            delete styles.width;
                        }
                        css(self.element, styles);
                    } else {
                        $.each(styles, function (i, n) {
                            serializedCss += n.replace(/([A-Z])/g, hyphenate) + ':' + styles[n] + ';';
                        });
                        self.attr({
                            style: serializedCss
                        });
                    }

                    return self;
                };

                SVGElement.prototype.getBBox = function () {
                    var bBox, width, height, rotation = this.rotation, rad = rotation * Math.PI * 2 / 360;

                    try  {
                        bBox = $.extend({}, this.element.getBBox());
                    } catch (e) {
                        bBox = { width: 0, height: 0 };
                    }
                    width = bBox.width;
                    height = bBox.height;
                    if (rotation) {
                        bBox.width = Math.abs(height * Math.sin(rad)) + Math.abs(width * Math.cos(rad));
                        bBox.height = Math.abs(height * Math.cos(rad)) + Math.abs(width * Math.sin(rad));
                    }

                    return bBox;
                };

                SVGElement.prototype.show = function () {
                    return this.attr({ visibility: VISIBLE });
                };

                SVGElement.prototype.hide = function () {
                    return this.attr({ visibility: HIDDEN });
                };

                SVGElement.prototype.add = function (parent) {
                    var self = this, renderer = self.renderer, parentWrapper = parent || renderer, parentNode = parentWrapper.element || renderer.box, childNodes = parentNode.childNodes, element = self.element, zIndex = attr(element, 'zIndex'), otherElement, otherZIndex, i;

                    if (parent && self.htmlNode) {
                        if (!parent.htmlNode) {
                            parent.htmlNode = [];
                        }
                        parent.htmlNode.push(self);
                    }
                    if (zIndex) {
                        parentWrapper.handleZ = true;
                        zIndex = parseInt(zIndex, 10);
                    }
                    if (parentWrapper.handleZ) {
                        for (i = 0; i < childNodes.length; i++) {
                            otherElement = childNodes[i];
                            otherZIndex = attr(otherElement, 'zIndex');
                            if (otherElement !== element && (parseInt(otherZIndex, 10) > zIndex || (!defined(zIndex) && defined(otherZIndex)))) {
                                parentNode.insertBefore(element, otherElement);
                                return self;
                            }
                        }
                    }
                    parentNode.appendChild(element);

                    self.added = true;

                    return self;
                };

                SVGElement.prototype._safeRemoveChild = function (element) {
                    var parentNode = element.parentNode;
                    if (parentNode) {
                        parentNode.removeChild(element);
                    }
                };

                SVGElement.prototype.destroy = function () {
                    var wrapper = this, element = wrapper.element || {}, shadows = wrapper.shadows, box = wrapper.box, i;

                    // remove events
                    element.onclick = element.onmouseout = element.onmouseover = element.onmousemove = null;

                    if (wrapper.clipPath) {
                        wrapper.clipPath = wrapper.clipPath.destroy();
                    }

                    // Destroy stops in case this is a gradient object
                    if (wrapper.stops) {
                        for (i = 0; i < wrapper.stops.length; i++) {
                            wrapper.stops[i] = wrapper.stops[i].destroy();
                        }
                        wrapper.stops = null;
                    }

                    // remove element
                    wrapper._safeRemoveChild(element);

                    // destroy shadows
                    if (shadows) {
                        each(shadows, function (shadow) {
                            wrapper._safeRemoveChild(shadow);
                        });
                    }

                    // destroy label box
                    if (box) {
                        box.destroy();
                    }

                    $.each(wrapper, function (key, obj) {
                        delete wrapper[key];
                    });
                    return null;
                };

                SVGElement.prototype.empty = function () {
                    var element = this.element, childNodes = element.childNodes, i = childNodes.length;

                    while (i--) {
                        element.removeChild(childNodes[i]);
                        $(childNodes[i]).remove();
                    }
                };

                SVGElement.prototype.remove = function () {
                    var ele = this.element, parentNode = ele.parentNode;
                    parentNode.removeChild(ele);
                    $(ele).remove();
                };
                return SVGElement;
            })(ChartElement);

            var SVGRender = (function (_super) {
                __extends(SVGRender, _super);
                function SVGRender(raphaelCanvas, container, width, height) {
                    _super.call(this, raphaelCanvas, container, width, height);
                    this.gradientCache = {};
                    this.init(raphaelCanvas, container, width, height);
                }
                SVGRender.prototype.init = function (raphaelCanvas, container, width, height) {
                    var self = this, loc = doc.location, boxWrapper;
                    this.RaphaelCanvas = raphaelCanvas;
                    this.symbols = SVGRender._symbols;
                    this.Element = SVGElement;

                    if ($(container).is("svg")) {
                        self.box = container;
                        boxWrapper = new self.Element();
                        boxWrapper.element = container;
                        boxWrapper.render = self;
                        self.defs = $("defs", container).get(0);
                        self.gradients = {};
                    } else {
                        boxWrapper = self.createElement('svg').attr({
                            xmlns: SVG_NS,
                            version: '1.1'
                        });
                        container.appendChild(boxWrapper.element);
                        self.box = boxWrapper.element;
                        self.boxWrapper = boxWrapper;
                        self.defs = this.createElement('defs').add();
                        self.gradients = {};
                        self.setSize(width, height);
                    }
                    self.url = isIE ? '' : loc.href.replace(/#.*?$/, '');
                };

                SVGRender.prototype.destroy = function () {
                    var self = this;
                    self.box = null;
                    destroyObjectProperties(self.gradients || {});
                    self.gradients = null;
                    return null;
                };

                SVGRender.prototype.createElement = function (nodeName) {
                    var wrapper = new this.Element();
                    wrapper.init(this, nodeName);
                    return wrapper;
                };

                SVGRender.prototype.path = function (path) {
                    var ret = this.createElement('path');
                    ret.attr({
                        d: path,
                        fill: NONE
                    });
                    return ret;
                };

                SVGRender.prototype.circle = function (x, y, r) {
                    var attr = $.isPlainObject(x) ? x : {
                        x: x,
                        y: y,
                        r: r
                    }, ret = this.createElement('circle');
                    ret.attr(attr);
                    return ret;
                };

                SVGRender.prototype.rect = function (x, y, width, height, r, strokeWidth) {
                    if ($.isPlainObject(x)) {
                        y = x.y;
                        width = x.width;
                        height = x.height;
                        r = x.r;
                        strokeWidth = x.strokeWidth;
                        x = x.x;
                    }
                    var wrapper = this.createElement('rect');
                    wrapper.attr({
                        rx: r,
                        ry: r,
                        fill: NONE
                    });

                    wrapper.attr(wrapper.crisp(strokeWidth, x, y, Math.max(width, 0), Math.max(height, 0)));
                    return wrapper;
                };

                SVGRender.prototype.setSize = function (width, height) {
                    var self = this;
                    self.width = width;
                    self.height = height;

                    self.boxWrapper.attr({
                        width: width,
                        height: height
                    });
                };

                SVGRender.prototype.g = function (name) {
                    var elem = this.createElement('g');
                    if (defined(name)) {
                        elem.attr({ 'class': PREFIX + name });
                    }
                    return elem;
                };

                SVGRender.prototype.text = function (x, y, text) {
                    if ($.isPlainObject(x)) {
                        y = x.y;
                        text = x.text;
                        x = x.x;
                    }
                    var wrapper = new this.Element(), canvas = this.RaphaelCanvas;

                    if (canvas && canvas.text) {
                        var raphaelText = canvas.text(x, y, text);

                        wrapper.raphaelObj = raphaelText;
                        wrapper.element = raphaelText.node;

                        wrapper.renderer = this;
                        wrapper.attr({
                            "text-anchor": "middle"
                        });
                    } else {
                        wrapper = this.createElement('text');
                        wrapper.attr({
                            x: x,
                            y: y,
                            "text-anchor": "middle"
                        });
                        wrapper.element.textContent = text;
                    }

                    return wrapper;
                };

                SVGRender.prototype.symbol = function (symbol, x, y, radius, options) {
                    var obj, self = this, symbolFn = self.symbols[symbol], path = symbolFn && symbolFn(Math.round(x), Math.round(y), radius, options);

                    if (path) {
                        obj = self.path(path);
                        $.extend(obj, {
                            symbolName: symbol,
                            x: x,
                            y: y,
                            r: radius
                        });
                        if (options) {
                            $.extend(obj, options);
                        }
                    } else {
                        obj = self.circle(x, y, radius);
                    }

                    return obj;
                };

                SVGRender.prototype.clipRect = function (x, y, width, height) {
                    var wrapper, id = PREFIX + _counter++, clipPath = this.createElement('clipPath');
                    clipPath.attr({
                        id: id
                    });
                    $(this.defs).append(clipPath.element);
                    wrapper = this.rect(x, y, width, height, 0).add(clipPath);
                    wrapper.id = id;
                    wrapper.clipPath = clipPath;
                    return wrapper;
                };

                SVGRender.prototype._parsegradientcolor = function (gradient) {
                    var self = this, dots = [], dot, par, i, start, end, ii, j, d;

                    if (self.gradientCache[gradient]) {
                        return self.gradientCache[gradient];
                    }
                    for (i = 0, ii = gradient.length; i < ii; i++) {
                        dot = {};
                        par = gradient[i].match(/^([^:]*):?([\d\.]*)/);
                        dot.color = Raphael.getRGB(par[1]);
                        if (dot.color.error) {
                            return null;
                        }
                        dot.color = dot.color.hex;
                        if (par[2]) {
                            dot.offset = par[2] + "%";
                        }
                        dots.push(dot);
                    }
                    for (i = 1, ii = dots.length - 1; i < ii; i++) {
                        if (!dots[i].offset) {
                            start = parseFloat(dots[i - 1].offset || 0);
                            end = 0;
                            for (j = i + 1; j < ii; j++) {
                                if (dots[j].offset) {
                                    end = dots[j].offset;
                                    break;
                                }
                            }
                            if (!end) {
                                end = 100;
                                j = ii;
                            }
                            end = parseFloat(end);
                            d = (end - start) / (j - i + 1);
                            for (; i < j; i++) {
                                start += d;
                                dots[i].offset = start + "%";
                            }
                        }
                    }
                    self.gradientCache[gradient] = dots;
                    return dots;
                };

                SVGRender.prototype._color = function (color, elem, prop) {
                    var self = this, type = "color", fx = 0.5, fy = 0.5, gradients = self.gradients, gradientObject, gradient, x1, y1, x2, y2, stopColor, vector, max, stopOpacity, key = color, id, angle, stops;

                    if (regLinearGradient.test(color)) {
                        type = "linear";
                    } else {
                        color = color.replace(regRadialGradient, function (all, _fx, _fy) {
                            type = "radial";
                            if (_fx && _fy) {
                                fx = parseFloat(_fx);
                                fy = parseFloat(_fy);
                                var dir = ((fy > 0.5) ? 1 : 0 * 2 - 1);
                                if (Math.pow(fx - 0.5, 2) + Math.pow(fy - 0.5, 2) > 0.25 && (fy = Math.sqrt(0.25 - Math.pow(fx - 0.5, 2)) * dir + 0.5) && fy !== 0.5) {
                                    fy = parseFloat(fy.toFixed(5)) - 1e-5 * dir;
                                }
                            }
                            return "";
                        });
                    }

                    if (type === "linear" || type === "radial") {
                        gradient = color.split(/\s*\-\s*/);

                        if (type === "linear") {
                            angle = gradient.shift();
                            angle = -parseFloat(angle);
                            if (isNaN(angle)) {
                                return color;
                            }
                            vector = [
                                0, 0, Math.cos(Raphael.rad(angle)),
                                Math.sin(Raphael.rad(angle))];
                            max = 1 / (Math.max(Math.abs(vector[2]), Math.abs(vector[3])) || 1);
                            vector[2] *= max;
                            vector[3] *= max;
                            if (vector[2] < 0) {
                                vector[0] = -vector[2];
                                vector[2] = 0;
                            }
                            if (vector[3] < 0) {
                                vector[1] = -vector[3];
                                vector[3] = 0;
                            }

                            x1 = vector[0];
                            y1 = vector[1];
                            x2 = vector[2];
                            y2 = vector[3];
                        }

                        // If the gradient with the same setup is already created, reuse it
                        if (gradients[key]) {
                            id = attr(gradients[key].element, 'id');
                            // If not, create a new one and keep the reference.
                        } else {
                            stops = this._parsegradientcolor(gradient);
                            $.each(stops, function (i, stop) {
                                stop.offset = stop.offset ? stop.offset : i ? "100%" : "0%";
                            });

                            id = PREFIX + _counter++;
                            gradientObject = self.createElement(type + "Gradient");
                            if (type === "radial") {
                                gradientObject.attr({
                                    id: id,
                                    fx: fx,
                                    fy: fy
                                });
                            } else {
                                gradientObject.attr({
                                    id: id,
                                    x1: x1,
                                    y1: y1,
                                    x2: x2,
                                    y2: y2
                                });
                            }

                            $(this.defs).append(gradientObject.element);

                            // The gradient needs to keep a list of stops
                            // to be able to destroy them
                            gradientObject.stops = [];
                            $.each(stops, function (i, stop) {
                                var stopObject;
                                stopColor = stop.color;
                                stopOpacity = 1;

                                stopObject = self.createElement('stop');
                                stopObject.attr({
                                    offset: stop.offset,
                                    'stop-color': stopColor,
                                    'stop-opacity': stopOpacity
                                }).add(gradientObject);

                                // Add the stop element to the gradient
                                gradientObject.stops.push(stopObject);
                            });

                            // Keep a reference to the gradient object so it is
                            // possible to reuse it and destroy it later
                            gradients[key] = gradientObject;
                        }
                        return 'url(#' + id + ')';
                    } else {
                        // Remove the opacity attribute added above.
                        // Does not throw if the attribute is not there.
                        elem.removeAttribute(prop + '-opacity');

                        return color;
                    }
                };

                // This method returns a string which can describe the tranform matrix.
                // Parameters:  transform: command string.
                //              element: SVGElement object.
                // Most of the code come from RaphaelJS method "extractTransform".
                SVGRender.prototype._transform = function (transform, element) {
                    var self = this, tdata = Raphael.parseTransformString(transform), el = element, m = Raphael.matrix(1, 0, 0, 1, 0, 0);
                    if (tdata) {
                        for (var i = 0, ii = tdata.length; i < ii; i++) {
                            var t = tdata[i], tlen = t.length, command = String(t[0]).toLowerCase(), absolute = t[0] != command, inver, x1, y1, x2, y2, bb;
                            if (absolute) {
                                inver = m.invert();
                            }

                            if (command == "t" && tlen == 3) {
                                if (absolute) {
                                    x1 = inver.x(0, 0);
                                    y1 = inver.y(0, 0);
                                    x2 = inver.x(t[1], t[2]);
                                    y2 = inver.y(t[1], t[2]);
                                    m.translate(x2 - x1, y2 - y1);
                                } else {
                                    m.translate(parseFloat(t[1]), parseFloat(t[2]));
                                }
                            } else if (command == "r") {
                                if (tlen == 2) {
                                    bb = bb || element.getBBox();
                                    m.rotate(parseFloat(t[1]), bb.x + bb.width / 2, bb.y + bb.height / 2);
                                } else if (tlen == 4) {
                                    if (absolute) {
                                        x2 = inver.x(t[2], t[3]);
                                        y2 = inver.y(t[2], t[3]);
                                        m.rotate(parseFloat(t[1]), x2, y2);
                                    } else {
                                        m.rotate(parseFloat(t[1]), parseFloat(t[2]), parseFloat(t[3]));
                                    }
                                }
                            } else if (command == "s") {
                                if (tlen == 2 || tlen == 3) {
                                    bb = bb || element.getBBox();
                                    m.scale(parseFloat(t[1]), parseFloat(t[tlen - 1]), bb.x + bb.width / 2, bb.y + bb.height / 2);
                                } else if (tlen == 5) {
                                    if (absolute) {
                                        x2 = inver.x(t[3], t[4]);
                                        y2 = inver.y(t[3], t[4]);
                                        m.scale(parseFloat(t[1]), parseFloat(t[2]), x2, y2);
                                    } else {
                                        m.scale(parseFloat(t[1]), parseFloat(t[2]), parseFloat(t[3]), parseFloat(t[4]));
                                    }
                                }
                            } else if (command == "m" && tlen == 7) {
                                m.add(parseFloat(t[1]), parseFloat(t[2]), parseFloat(t[3]), parseFloat(t[4]), parseFloat(t[5]), parseFloat(t[6]), m);
                            }
                        }
                    }
                    return m.toString();
                };
                SVGRender._symbols = {
                    'box': function (x, y, radius) {
                        var len = 0.707 * radius;
                        return [
                            M, x - len, y - len,
                            L, x + len, y - len,
                            x + len, y + len,
                            x - len, y + len,
                            'Z'
                        ];
                    },
                    'tri': function (x, y, radius) {
                        return [
                            M, x, y - 1.33 * radius,
                            L, x + radius, y + 0.67 * radius,
                            x - radius, y + 0.67 * radius,
                            'Z'
                        ];
                    },
                    'invertedTri': function (x, y, radius) {
                        return [
                            M, x, y + 1.33 * radius,
                            L, x - radius, y - 0.67 * radius,
                            x + radius, y - 0.67 * radius,
                            'Z'
                        ];
                    },
                    'diamond': function (x, y, radius) {
                        return [
                            M, x, y - radius,
                            L, x + radius, y,
                            x, y + radius,
                            x - radius, y,
                            'Z'
                        ];
                    },
                    'cross': function (x, y, radius) {
                        var offset = 0.707 * radius;
                        return [
                            M, x - offset, y - offset, L, x + offset, y + offset,
                            M, x - offset, y + offset, L, x + offset, y - offset];
                    },
                    'arc': function (x, y, radius, options) {
                        var start = options.start, end = options.end - 0.000001, innerRadius = options.innerR, cosStart = Math.cos(start), sinStart = Math.sin(start), cosEnd = Math.cos(end), sinEnd = Math.sin(end), longArc = options.end - start < Math.PI ? 0 : 1;

                        return [
                            M,
                            x + radius * cosStart,
                            y + radius * sinStart,
                            'A',
                            radius,
                            radius,
                            0,
                            longArc,
                            1,
                            x + radius * cosEnd,
                            y + radius * sinEnd,
                            L,
                            x + innerRadius * cosEnd,
                            y + innerRadius * sinEnd,
                            'A',
                            innerRadius,
                            innerRadius,
                            0,
                            longArc,
                            0,
                            x + innerRadius * cosStart,
                            y + innerRadius * sinStart,
                            'Z'
                        ];
                    }
                };
                return SVGRender;
            })(ChartRender);

            var VMLElement = (function (_super) {
                __extends(VMLElement, _super);
                function VMLElement() {
                    _super.apply(this, arguments);
                }
                VMLElement.prototype.init = function (renderer, nodeName) {
                    var markup = ['<', nodeName, ' filled="f" stroked="f"'], style = ['position: ', ABSOLUTE, ';'];

                    if (nodeName === 'shape' || nodeName === DIV) {
                        style.push('left:0;top:0;width:10px;height:10px;');
                    }
                    if (docMode8) {
                        style.push('visibility: ', nodeName === DIV ? HIDDEN : VISIBLE);
                    }

                    markup.push(' style="', style.join(''), '"/>');
                    if (nodeName) {
                        markup = nodeName === DIV || nodeName === 'span' || nodeName === 'img' ? markup.join('') : renderer.prepVML(markup);
                        this.element = createElement(markup);
                    }
                    this.renderer = renderer;
                };

                VMLElement.prototype.add = function (parent) {
                    var self = this, renderer = self.renderer, element = self.element, box = renderer.box, inverted = parent && parent.inverted, parentNode = parent ? parent.element || parent : box;

                    if (inverted) {
                        // to do this method?
                        //renderer.invertChild(element, parentNode);
                    }
                    if (docMode8 && parentNode.gVis === HIDDEN) {
                        css(element, { visibility: HIDDEN });
                    }
                    parentNode.appendChild(element);
                    self.added = true;
                    return self;
                };

                VMLElement.prototype.attr = function (hash, val) {
                    var key, value, i, self = this, element = self.element || {}, elemStyle = element.style, nodeName = element.nodeName, symbolName = self.symbolName, renderer = self.renderer, childNodes, hasSetSymbolSize, shadows = self.shadows, skipAttr, convertedPath, raphaelObj, ret = self;

                    if (hash === undefined) {
                        return ret;
                    }

                    if (isString(hash) && defined(val)) {
                        key = hash;
                        hash = {};
                        hash[key] = val;
                    }
                    if (isString(hash)) {
                        key = hash;
                        if (key === 'strokeWidth' || key === 'stroke-width') {
                            ret = self.strokeweight;
                        } else {
                            ret = self[key];
                        }
                    } else if (hash) {
                        raphaelObj = this.raphaelObj;
                        if (raphaelObj && raphaelObj.attr) {
                            raphaelObj.attr(hash);

                            $.each(["visibility", "class"], function (keyIdx, keyNm) {
                                if (keyNm in hash) {
                                    skipAttr = false;
                                    value = hash[keyNm];
                                    switch (keyNm) {
                                        case "visibility":
                                            if (value === VISIBLE) {
                                                raphaelObj.show();
                                            } else if (value === HIDDEN) {
                                                raphaelObj.hide();
                                            }
                                            skipAttr = true;
                                            break;
                                        case "class":
                                            element.className = value;
                                            break;
                                    }
                                    if (!skipAttr) {
                                        if (docMode8) {
                                            element[keyNm] = value;
                                        } else {
                                            attr(element, keyNm, value);
                                        }
                                    }
                                }
                            });

                            return ret;
                        }

                        $.each(hash, function (key, v) {
                            value = v;
                            skipAttr = false;
                            if (symbolName && /^(x|y|r|start|end|width|height|innerR)/.test(key)) {
                                if (!hasSetSymbolSize) {
                                    self.symbolAttr(hash);

                                    hasSetSymbolSize = true;
                                }
                                skipAttr = true;
                            } else if (key === 'd') {
                                value = value || [];
                                self.d = value.join(' ');
                                i = value.length;
                                convertedPath = [];
                                while (i--) {
                                    if (isNumber(value[i])) {
                                        convertedPath[i] = Math.round(value[i] * 10) - 5;
                                    } else if (value[i] === 'Z') {
                                        convertedPath[i] = 'x';
                                    } else {
                                        convertedPath[i] = value[i];
                                    }
                                }
                                value = convertedPath.join(' ') || 'x';
                                element.path = value;
                                if (shadows) {
                                    i = shadows.length;
                                    while (i--) {
                                        shadows[i].path = value;
                                    }
                                }
                                skipAttr = true;
                            } else if (key === 'zIndex' || key === VISIBILITY) {
                                if (docMode8 && key === VISIBILITY && nodeName === DIV) {
                                    element.gVis = value;
                                    childNodes = element.childNodes;
                                    i = childNodes.length;
                                    while (i--) {
                                        css(childNodes[i], { visibility: value });
                                    }
                                    if (value === VISIBLE) {
                                        value = null;
                                    }
                                }
                                if (value) {
                                    elemStyle[key] = value;
                                }
                                skipAttr = true;
                            } else if (key === 'class') {
                                element.className = value;
                            } else if (key === 'stroke') {
                                key = 'strokecolor';
                            } else if (key === 'stroke-width' || key === 'strokeWidth') {
                                element.stroked = value ? true : false;
                                key = 'strokeweight';
                                self[key] = value;
                                if (isNumber(value)) {
                                    value += PX;
                                }
                            } else if (key === 'fill') {
                                if (nodeName === 'SPAN') {
                                    elemStyle.color = value;
                                } else {
                                    element.filled = value !== NONE ? true : false;
                                    value = renderer.color(value, element, key);
                                    key = 'fillcolor';
                                }
                            }
                            if (!skipAttr) {
                                if (key === "opacity") {
                                    key = "fill-opacity";
                                }
                                if (docMode8) {
                                    element[key] = value;
                                } else {
                                    attr(element, key, value);
                                }
                            }

                            //save the attribute to attrs
                            element.attrs = element.attrs || {};
                            element.attrs[key] = value;
                        });
                    }
                    return ret;
                };

                VMLElement.prototype.scale = function (x, y) {
                    var self = this, strokeWidth = self.attr("stroke-width") || 0;
                    self.css({
                        filter: "progid:DXImageTransform.Microsoft.Matrix(M11=" + x + "," + ", M12=0, M21=0, M22=" + y + ", Dx=0, Dy=0, sizingmethod='auto expand')"
                    }).attr("stroke-width", strokeWidth);
                };

                VMLElement.prototype.clip = function (clipRect) {
                    var self = this, clipMembers = clipRect.members;

                    clipMembers.push(self);
                    return self.css(clipRect.getCSS(self.inverted));
                };

                VMLElement.prototype.css = function (styles) {
                    var self = this, element = self.element, textWidth = styles && element.tagName === 'SPAN' && styles.width;
                    if (textWidth) {
                        delete styles.width;
                        self.textWidth = textWidth;
                    }

                    self.styles = $.extend(self.styles, styles);
                    css(self.element, styles);

                    return self;
                };

                VMLElement.prototype.destroy = function () {
                    var self = this;
                    if (self["destroyClip"]) {
                        self["destroyClip"]();
                    }
                    return SVGElement.prototype.destroy.apply(self);
                };

                VMLElement.prototype.empty = function () {
                    var element = this.element, childNodes = element.childNodes, i = childNodes.length, node;
                    while (i--) {
                        node = childNodes[i];
                        node.parentNode.removeChild(node);
                        $(node).remove();
                    }
                };

                VMLElement.prototype.getBBox = function () {
                    var self = this, element = self.element, bBox = self.bBox;

                    if (!bBox) {
                        if (element.nodeName === 'text') {
                            element.style.position = ABSOLUTE;
                        }

                        bBox = self.bBox = {
                            x: element.offsetLeft,
                            y: element.offsetTop,
                            width: element.offsetWidth,
                            height: element.offsetHeight
                        };
                    }
                    return bBox;
                };
                return VMLElement;
            })(SVGElement);

            var VMLRender = (function (_super) {
                __extends(VMLRender, _super);
                function VMLRender() {
                    _super.apply(this, arguments);
                    this.isIE8 = $.browser.msie && parseInt($.browser.version) === 8;
                }
                VMLRender.prototype.init = function (raphaelCanvas, container, width, height) {
                    var self = this, boxWrapper;
                    this.RaphaelCanvas = raphaelCanvas;
                    this.Element = VMLElement;
                    this.symbols = VMLRender._symbols;
                    if ($(container).hasClass("vmlcontainer")) {
                        self.box = container;
                        boxWrapper = new this.Element();
                        boxWrapper.element = container;
                        boxWrapper.render = this;
                        self.boxWrapper = boxWrapper;
                    } else {
                        boxWrapper = self.createElement(DIV);
                        container.appendChild(boxWrapper.element);
                        self.box = boxWrapper.element;
                        self.boxWrapper = boxWrapper;
                        self.setSize(width, height);
                    }
                    if (!doc.namespaces["v"]) {
                        doc.namespaces.add('v', 'urn:schemas-microsoft-com:vml');
                        doc.createStyleSheet().cssText = 'v\\:fill, v\\:path, v\\:shape, v\\:stroke' + '{ behavior:url(#default#VML); display: inline-block; } ';
                    }
                };

                VMLRender.prototype.clipRect = function (x, y, width, height) {
                    var clipRect = this.createElement();
                    $.extend(clipRect, {
                        members: [],
                        left: x,
                        top: y,
                        width: width,
                        height: height,
                        getCSS: function (inverted) {
                            var rect = this, top = rect.top, left = rect.left, right = left + rect.width, bottom = top + rect.height, ret = {
                                clip: 'rect(' + Math.round(inverted ? left : top) + 'px,' + Math.round(inverted ? bottom : right) + 'px,' + Math.round(inverted ? right : bottom) + 'px,' + Math.round(inverted ? top : left) + 'px)'
                            };
                            if (!inverted && docMode8) {
                                $.extend(ret, {
                                    width: right + PX,
                                    height: bottom + PX
                                });
                            }
                            return ret;
                        },
                        updateClipping: function () {
                            each(clipRect.members, function (i, member) {
                                member.css(clipRect.getCSS(member.inverted));
                            });
                        }
                    });
                    return clipRect;
                };

                VMLRender.prototype.color = function (color, elem, prop) {
                    var markup, self = this, type = "color", gradient, stopColor, color1, color2, colors = [], ele, strokeNodes, fxfy, stops, angle = 0;

                    if (regLinearGradient.test(color)) {
                        type = "linear";
                    } else {
                        color = color.replace(regRadialGradient, function (all, fx, fy) {
                            type = "radial";
                            if (fx && fy) {
                                fx = parseFloat(fx);
                                fy = parseFloat(fy);
                                if (Math.pow(fx - 0.5, 2) + Math.pow(fy - 0.5, 2) > 0.25) {
                                    fy = Math.sqrt(0.25 - Math.pow(fx - 0.5, 2)) * ((fy > 0.5 ? 1 : 0) * 2 - 1) + 0.5;
                                }
                                fxfy = fx + " " + fy;
                            }
                            return "";
                        });
                        //type = "radial";
                    }

                    if (type === "linear" || type === "radial") {
                        gradient = color.split(/\s*\-\s*/);
                        if (type === "linear") {
                            angle = gradient.shift();
                            angle = -parseFloat(angle.toString());
                        }
                        stops = self._parsegradientcolor(gradient);

                        $.each(stops, function (i, stop) {
                            stop.offset = stop.offset ? stop.offset : i ? "100%" : "0%";
                            colors.push(stop.offset + " " + stop.color);
                            stopColor = stop.color;

                            if (!i) {
                                color1 = stopColor;
                            } else {
                                color2 = stopColor;
                            }
                        });

                        if (type === "radial") {
                            markup = [
                                '<fill colors="', colors.join(), '" angle="0"',
                                '" focusposition="', fxfy, '" color="', color1,
                                '" color2="', color2, '" focussize="0 0"',
                                ' type="gradientTitle" focus="100%" method="none" />'];
                        } else {
                            markup = [
                                '<fill colors="', colors.join(), '" angle="',
                                angle.toString(),
                                '" type="gradient" focus="100%" method="sigma" />'];
                        }
                        ele = createElement(self.prepVML(markup));
                        $(elem).append(ele);
                    } else {
                        strokeNodes = elem.getElementsByTagName(prop);
                        if (strokeNodes.length) {
                            strokeNodes[0].opacity = 1;
                        }
                        return color;
                    }
                };

                VMLRender.prototype.prepVML = function (markup) {
                    var vmlStyle = 'display:inline-block;behavior:url(#default#VML);', isIE8 = this.isIE8;

                    markup = markup.join('');

                    if (isIE8) {
                        markup = markup.replace('/>', ' xmlns="urn:schemas-microsoft-com:vml" />');
                        if (markup.indexOf('style="') === -1) {
                            markup = markup.replace('/>', ' style="' + vmlStyle + '" />');
                        } else {
                            markup = markup.replace('style="', 'style="' + vmlStyle);
                        }
                    } else {
                        markup = markup.replace('<', '<v:');
                    }

                    return markup;
                };

                VMLRender.prototype.path = function (path) {
                    var ret = this.createElement('shape');
                    ret.attr({
                        coordsize: '100 100',
                        d: path
                    });
                    return ret;
                };
                VMLRender.prototype.g = function (name) {
                    var wrapper, attribs;
                    if (name) {
                        attribs = { 'className': PREFIX + name, 'class': PREFIX + name };
                    }
                    wrapper = this.createElement(DIV).attr(attribs);

                    return wrapper;
                };

                VMLRender.prototype.text = function (x, y, text) {
                    var wrapper, ele, width, height, canvas = this.RaphaelCanvas;

                    if (canvas && canvas.text) {
                        wrapper = new this.Element();

                        var raphaelText = canvas.text(x, y, text);

                        $(raphaelText.node).css({ visibility: VISIBLE });
                        wrapper.raphaelObj = raphaelText;
                        wrapper.element = raphaelText.node;

                        wrapper.renderer = this;
                    } else {
                        wrapper = this.createElement("span");
                        ele = wrapper.element;
                        ele.innerHTML = text;
                        $(ele).appendTo("body");
                        width = $(ele).width();
                        height = $(ele).height();
                        x -= width / 2;
                        y -= height / 2;
                        wrapper.x = x;
                        wrapper.y = y;
                        $(ele).css({
                            position: "absolute",
                            "white-space": "nowrap",
                            "font-family": "Arial",
                            "font-size": "10",
                            left: x + "px",
                            top: y + "px"
                        });
                    }
                    return wrapper;
                };

                VMLRender._symbols = $.extend({}, SVGRender._symbols, {
                    arc: function (x, y, radius, options) {
                        var start = options.start, end = options.end, cosStart = Math.cos(start), sinStart = Math.sin(start), cosEnd = Math.cos(end), sinEnd = Math.sin(end), innerRadius = options.innerR, circleCorrection = 0.07 / radius, innerCorrection = (innerRadius && 0.1 / innerRadius) || 0;

                        if (end - start === 0) {
                            return ['x'];
                        } else if (2 * Math.PI - end + start < circleCorrection) {
                            cosEnd = -circleCorrection;
                        } else if (end - start < innerCorrection) {
                            cosEnd = Math.cos(start + innerCorrection);
                        }

                        return [
                            'wa',
                            x - radius,
                            y - radius,
                            x + radius,
                            y + radius,
                            x + radius * cosStart,
                            y + radius * sinStart,
                            x + radius * cosEnd,
                            y + radius * sinEnd,
                            'at',
                            x - innerRadius,
                            y - innerRadius,
                            x + innerRadius,
                            y + innerRadius,
                            x + innerRadius * cosEnd,
                            y + innerRadius * sinEnd,
                            x + innerRadius * cosStart,
                            y + innerRadius * sinStart,
                            'x',
                            'e'
                        ];
                    },
                    circle: function (x, y, r) {
                        return [
                            'wa',
                            x - r,
                            y - r,
                            x + r,
                            y + r,
                            x + r,
                            y,
                            x + r,
                            y,
                            'e'
                        ];
                    },
                    rect: function (left, top, r, options) {
                        if (!defined(options)) {
                            return [];
                        }
                        var width = options.width, height = options.height, right = left + width, bottom = top + height;
                        r = Math.min(r, width, height);

                        return [
                            M,
                            left + r, top,
                            L,
                            right - r, top,
                            'wa',
                            right - 2 * r, top,
                            right, top + 2 * r,
                            right - r, top,
                            right, top + r,
                            L,
                            right, bottom - r,
                            'wa',
                            right - 2 * r, bottom - 2 * r,
                            right, bottom,
                            right, bottom - r,
                            right - r, bottom,
                            L,
                            left + r, bottom,
                            'wa',
                            left, bottom - 2 * r,
                            left + 2 * r, bottom,
                            left + r, bottom,
                            left, bottom - r,
                            L,
                            left, top + r,
                            'wa',
                            left, top,
                            left + 2 * r, top + 2 * r,
                            left, top + r,
                            left + r, top,
                            'x',
                            'e'
                        ];
                    }
                });
                return VMLRender;
            })(SVGRender);

            function createRender(raphaelCanvas, container, width, height) {
                if (hasSVG) {
                    return new SVGRender(raphaelCanvas, container, width, height);
                } else {
                    return new VMLRender(raphaelCanvas, container, width, height);
                }
            }
            render.createRender = createRender;
        })(chart.render || (chart.render = {}));
        var render = chart.render;
    })(wijmo.chart || (wijmo.chart = {}));
    var chart = wijmo.chart;
})(wijmo || (wijmo = {}));

;
/// <reference path="../wijchart/jquery.wijmo.wijchartcore.ts"/>
/// <reference path="../external/declarations/globalize.d.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*globals jQuery, Globalize*/
    /*
    * Depends:
    *  raphael.js
    *  globalize.js
    *  jquery.ui.widget.js
    *  jquery.wijmo.wijchartcore.js
    *
    */
    (function (chart) {
        var maxSize = 10000;

        /** @ignore */
        var BubbleAxisAdjust = (function () {
            function BubbleAxisAdjust(widget) {
                this.bubMax = 0;
                this.bubMin = 0;
                this.bubDiff = 0;
                this.y1Array = [];
                this.y1ValueGroup = {};
                this.bubbleRadius = {};
                this.chartDatas = [];
                var o = widget.options;
                this.widget = widget;
                this.seriesList = o.seriesList;
                this.maximumSize = o.maximumSize || 20;
                this.minimumSize = o.minimumSize || 5;
                this.sizingMethod = o.sizingMethod || "diameter";
                this._init();
                this._calculateMaxMin();
            }
            BubbleAxisAdjust.prototype._init = function () {
                var _this = this;
                var data, markers, markerType;
                $.each(this.seriesList, function (i, n) {
                    markers = n.markers || {}, markerType = markers.type || "circle";
                    data = n.data;
                    if (data && data.y1 && data.x && data.y) {
                        $.each(data.y1, function (j, m) {
                            _this.y1Array.push(m);
                            if (!_this.y1ValueGroup[markerType]) {
                                _this.y1ValueGroup[markerType] = [];
                            }
                            _this.y1ValueGroup[markerType].push(m);
                            _this.chartDatas.push({
                                x: data.x[j],
                                y: data.y[j],
                                y1: data.y1[j]
                            });
                        });
                    }
                });
            };

            BubbleAxisAdjust.prototype._calculateMaxMin = function () {
                this.bubMax = Math.max.apply(null, this.y1Array);
                this.bubMin = Math.min.apply(null, this.y1Array);
                this.bubDiff = this.bubMax - this.bubMin;
            };

            BubbleAxisAdjust.prototype._calculateRadius = function (yval, maxSize, minSize, bounds, bubMax, bubDiff, sizingMethod, markerType) {
                var yscale, val = yval, bubSizeDiff = maxSize - minSize, width = bounds.endX - bounds.startX, height = bounds.endY - bounds.startY;

                if (val < 0) {
                    val = 0;
                }
                if (bubDiff === 0) {
                    val = 1;
                } else {
                    val /= bubMax;
                }
                val = this._calculateRadiusByArea(val, sizingMethod, markerType);

                val *= bubSizeDiff;
                val += minSize;
                yscale = Math.min(width, height);
                val *= yscale / 200.0;
                return val;
            };

            BubbleAxisAdjust.prototype._calculateRadiusByArea = function (yval, sizingMethod, markerType) {
                var val = yval;
                if (sizingMethod === "area") {
                    switch (markerType) {
                        case "circle":
                            val = Math.sqrt(val / Math.PI);
                            break;
                        case "tri":
                        case "invertedTri":
                            val = Math.sqrt(val / (3 * Math.sin(Math.PI / 6) * Math.cos(Math.PI / 6)));
                            break;
                        case "box":
                            val = Math.sqrt(val / 2);
                            break;
                        case "diamond":
                        case "cross":
                            val = Math.sqrt(val / 2);
                            break;
                        default:
                            val = Math.sqrt(4 * val / Math.PI);
                            break;
                    }
                }
                return val;
            };

            BubbleAxisAdjust.prototype.calculateRadius = function () {
                var _this = this;
                var bounds = this.widget.canvasBounds;
                this.bubbleRadius = {};
                $.each(this.y1ValueGroup, function (type, values) {
                    $.each(values, function (i, value) {
                        _this.bubbleRadius[value] = _this._calculateRadius(value, _this.maximumSize, _this.minimumSize, bounds, _this.bubMax, _this.bubDiff, _this.sizingMethod, type);
                    });
                });
            };

            BubbleAxisAdjust.prototype.getAdjust = function (axisInfo, options) {
                var _this = this;
                var bounds = this.widget.canvasBounds, max = axisInfo.max, min = axisInfo.min, minPoint = [], maxPoint = [], diff = 0, unitMinor = options.unitMinor, origin = options.origin, width = bounds.endX - bounds.startX, height = bounds.endY - bounds.startY, omax, omin, length, xStrings = [], xHash = {}, isAdjust = false;

                this.calculateRadius();

                // if the x value is string. get the string index in seriesList.
                $.each(this.chartDatas, function (i, data) {
                    var x = data.x;
                    if (isNaN(x) && !_this.widget._isDate(x) && $.inArray(x, xStrings) === -1) {
                        xStrings.push(x);
                    }
                });

                $.each(xStrings, function (i, x) {
                    xHash[x] = i;
                });

                $.each(this.chartDatas, function (i, data) {
                    var x = data.x, y = data.y, y1 = data.y1, r = _this.bubbleRadius[y1];

                    if (_this.widget._isDate(x)) {
                        x = $.toOADate(x);
                    } else if (isNaN(x)) {
                        x = xHash[x];
                    }
                    if (_this.widget._isDate(y)) {
                        y = $.toOADate(y);
                    }

                    if (axisInfo.id === "x") {
                        length = width;
                        diff = r * (max - min) / length;
                        minPoint.push(x - diff);
                        maxPoint.push(x + diff);
                    } else {
                        length = height;
                        diff = r * (max - min) / length;
                        minPoint.push(y - diff);
                        maxPoint.push(y + diff);
                    }
                });

                omax = Math.max.apply(null, maxPoint);
                omin = Math.min.apply(null, minPoint);
                if (omax > max) {
                    max += Math.ceil((omax - max) / unitMinor) * unitMinor;
                    isAdjust = true;
                }

                if (omin < min) {
                    min -= Math.ceil((min - omin) / unitMinor) * unitMinor;
                    isAdjust = true;
                }

                // Fixed an issue that if the origin is less than the min value and more than the max value,
                // the axis will adjust wrong value.
                if (origin !== null && origin !== undefined) {
                    if (origin < min) {
                        min = origin;
                    } else if (origin > max) {
                        max = origin;
                    }
                }

                // If adjust the min and max, the bubble radius need to recalculate again using new max and min, So here need to recall this method again.
                if (isAdjust) {
                    axisInfo.max = max;
                    axisInfo.min = min;
                    this.widget._calculateMajorMinor(options, axisInfo);
                    return this.getAdjust(axisInfo, options);
                } else {
                    return {
                        max: max,
                        min: min
                    };
                }
            };

            BubbleAxisAdjust.prototype.dispose = function () {
                this.y1Array = [];
                this.bubbleRadius = null;
                this.y1ValueGroup = null;
            };
            return BubbleAxisAdjust;
        })();
        chart.BubbleAxisAdjust = BubbleAxisAdjust;

        /**
        * @widget
        */
        var wijbubblechart = (function (_super) {
            __extends(wijbubblechart, _super);
            function wijbubblechart() {
                _super.apply(this, arguments);
            }
            wijbubblechart.prototype._setOption = function (key, value) {
                var self = this, o = self.options;

                //self.bubbles = [];
                //self.bubbleInfos = [];
                if (key === "minimumSize" || key === "minimumSize") {
                    if (isNaN(value) || value < 0) {
                        value = 0;
                    } else if (value > maxSize) {
                        value = maxSize;
                    }
                    o[key] = value;
                    self.redraw();
                } else if (key === "chartLabel") {
                    $.extend(o.chartLabel, value);
                    self.redraw();
                } else {
                    if (key === "chartLabelStyle") {
                        o[key] = value;
                        self._setLabelOption();
                    }
                    _super.prototype._setOption.call(this, key, value);
                }
                if (key === "seriesList") {
                    self.indexs = null;
                }
            };
            wijbubblechart.prototype._create = function () {
                var self = this, o = self.options, defFill = self._getDefFill();

                this._handleChartStyles();

                //$.each(o.seriesStyles, function (idx, style) {
                //	if (!style.fill) {
                //		style.fill = defFill[idx];
                //	}
                //});
                self._setLabelOption();
                _super.prototype._create.call(this);
                self.chartElement.addClass(o.wijCSS.bubbleChart);
            };

            wijbubblechart.prototype._paintChartArea = function () {
                if (this.bubbleAxisAdjust) {
                    this.bubbleAxisAdjust.dispose();
                }
                this.bubbleAxisAdjust = new BubbleAxisAdjust(this);
                _super.prototype._paintChartArea.call(this);
            };

            wijbubblechart.prototype._bindSeriesData = function (ds, series, sharedXList) {
                var data = series.data, dataY1 = data.y1;
                _super.prototype._bindSeriesData.call(this, ds, series, sharedXList);
                if (dataY1 && dataY1.bind) {
                    data.y1 = this._getBindData(ds, dataY1.bind);
                }
            };

            wijbubblechart.prototype._setLabelOption = function () {
                var o = this.options;

                if (!$.isPlainObject(o.chartLabel.style) && $.isPlainObject(o.chartLabelStyle)) {
                    o.chartLabel.style = o.chartLabelStyle;
                }
            };

            wijbubblechart.prototype._clearChartElement = function () {
                var self = this, o = self.options, fields = self.chartElement.data("fields");

                _super.prototype._clearChartElement.call(this);

                if (fields && fields.bubbleInfos) {
                    $.each(fields.bubbleInfos, function (i, n) {
                        if (n.bubble) {
                            n.bubble.wijRemove();
                        }
                        if (n.dcl) {
                            n.dcl.wijRemove();
                        }
                        if (n.symbol) {
                            n.symbol.wijRemove();
                        }
                    });
                }

                if (fields && fields.bubbles) {
                    self._destroyRaphaelArray(fields.bubbles);
                }
                self.element.removeData("plotInfos");

                if (!o.seriesTransition.enabled) {
                    if (fields && fields.bubblesAnimationInfos) {
                        fields.bubblesAnimationInfos = null;
                    }
                }
            };

            /**
            * Remove the functionality completely. This will return the element back to its pre-init state.
            */
            wijbubblechart.prototype.destroy = function () {
                var self = this;
                self.chartElement.removeClass(self.options.wijCSS.bubbleChart + " ui-helper-reset");
                self._destroyEles();
                if (this.bubbleAxisAdjust) {
                    this.bubbleAxisAdjust.dispose();
                    this.bubbleAxisAdjust = null;
                }
                _super.prototype.destroy.call(this);
            };

            /**
            * Returns the bubble which has a Raphael's object that represents bubbles for the series data with the given index.
            * @param {number} index The index of the bubble.
            * @returns {Raphael Element} The bubble object.
            */
            wijbubblechart.prototype.getBubble = function (index) {
                return this.chartElement.data("fields").bubbles[index];
            };

            /** @ignore*/
            wijbubblechart.prototype.redraw = function (ifNeed) {
                _super.prototype.redraw.call(this, ifNeed);
            };

            wijbubblechart.prototype._destroyEles = function () {
                var self = this, ele = self.element, fields = ele.data("fields");
                if (fields.bubbleInfos) {
                    $.each(fields.bubbleInfos, function (i, n) {
                        self._removeEle(n.bubble);
                        self._removeEle(n.dcl);
                        self._removeEle(n.symbol);
                        n = null;
                    });
                    //self.bubbleInfos = [];
                }
                ele.removeData("fields");
                //self.bubbles = [];
                //self.seriesEles = [];
                //self.tooltipbubbles = [];
            };

            wijbubblechart.prototype._removeEle = function (ele) {
                if (ele) {
                    if (ele.node) {
                        $(ele.node).removeData();
                    }
                    ele.wijRemove();
                    ele = null;
                }
            };

            wijbubblechart.prototype._paintPlotArea = function () {
                var self = this, element = this.chartElement, o = self.options, seriesList = o.seriesList, nSeries = seriesList.length, seriesStyles = [].concat(o.seriesStyles.slice(0, nSeries)), seriesHoverStyles = [].concat(o.seriesHoverStyles.slice(0, nSeries)), canvasBounds = self.canvasBounds, xaxis = self.axisInfo.x, yaxis = self.axisInfo.y[0], bubbleInfos;

                if (nSeries === 0) {
                    return;
                }

                //self._paintcircles(seriesList, seriesStyles, seriesHoverStyles,
                //	xaxis, yaxis, width, height, startLocation);
                // call this method again for if the axis's max and min are set by manual.
                this.bubbleAxisAdjust.calculateRadius();

                this.bubbleChartRender = new BubbleChartRender(this.chartElement, {
                    annotations: o.annotations,
                    axis: o.axis,
                    seriesList: seriesList,
                    seriesStyles: seriesStyles,
                    seriesHoverStyles: seriesHoverStyles,
                    canvas: self.canvas,
                    bounds: canvasBounds,
                    xAxisInfo: xaxis,
                    yAxisInfo: yaxis,
                    showChartLabels: o.showChartLabels,
                    chartLabel: o.chartLabel,
                    textStyle: o.textStyle,
                    chartLabelStyle: o.chartLabelStyle,
                    chartLabelFormatString: o.chartLabelFormatString,
                    chartLabelFormatter: o.chartLabelFormatter,
                    bubbleRadius: self.bubbleAxisAdjust.bubbleRadius,
                    animation: o.animation,
                    seriesTransition: o.seriesTransition,
                    sizingMethod: o.sizingMethod,
                    minimumSize: o.minimumSize,
                    maximumSize: o.maximumSize,
                    mouseDown: $.proxy(self._mouseDown, self),
                    mouseUp: $.proxy(self._mouseUp, self),
                    mouseOver: $.proxy(self._mouseOver, self),
                    mouseOut: $.proxy(self._mouseOut, self),
                    mouseMove: $.proxy(self._mouseMove, self),
                    click: $.proxy(self._click, self),
                    disabled: self._isDisabled(),
                    culture: self._getCulture(),
                    wijCSS: o.wijCSS,
                    shadow: o.shadow,
                    widget: this
                });

                this.bubbleChartRender.render();
                bubbleInfos = element.data("fields").bubbleInfos;
                if (!bubbleInfos) {
                    return;
                }

                self.tooltipbubbles = [];

                $.each(bubbleInfos, function (idx, bubbleInfo) {
                    self.tooltipbubbles.push(bubbleInfo.bubble);
                    if (bubbleInfo.dcl) {
                        self.tooltipbubbles.push(bubbleInfo.dcl);
                    }
                    if (bubbleInfo.symbol) {
                        self.tooltipbubbles.push(bubbleInfo.symbol);
                    }
                });

                if (self.tooltip) {
                    self.tooltip.setTargets(self.tooltipbubbles);
                }
                //self._playAnimation(self.bubbleInfos);
            };

            wijbubblechart.prototype._getLegendbasicInfo = function () {
                var legendSize, legendOptions = _super.prototype._getLegendbasicInfo.call(this);
                legendSize = legendOptions.iconSize;
                if (!legendSize.r) {
                    legendSize.r = Math.min(legendSize.width, legendSize.height);
                }

                legendOptions.iconSize = legendSize;

                return legendOptions;
            };

            wijbubblechart.prototype._getLegendInfoFromSeries = function (seriesIdx, series, seriesStyle) {
                if (series.LegendEntry === false) {
                    return undefined;
                }

                var legendSize, iconStyle, markerStyle, legendInfo;

                legendInfo = _super.prototype._getLegendInfoFromSeries.call(this, seriesIdx, series, seriesStyle);
                iconStyle = legendInfo.iconStyle;

                markerStyle = $.extend({
                    fill: iconStyle.fill,
                    stroke: iconStyle.stroke,
                    opacity: 1
                }, series.markerStyle);

                legendInfo.iconStyle = markerStyle;

                if (series.markers && series.markers.type) {
                    legendInfo.icon = series.markers.type;
                } else {
                    legendInfo.icon = "circle";
                }

                legendInfo.markers = undefined;
                legendInfo.markerVisible = false;
                legendInfo.markerStyle = undefined;

                return legendInfo;
            };

            wijbubblechart.prototype._calculateParameters = function (axisInfo, options) {
                _super.prototype._calculateParameters.call(this, axisInfo, options);
                if (!options.autoMax && !options.autoMin) {
                    return;
                }
                this._adjust(options, axisInfo);
            };

            wijbubblechart.prototype._adjust = function (options, axisInfo) {
                var unitMinor = options.unitMinor, self = this, autoMin = options.autoMin, autoMax = options.autoMax, canvasBounds = self.canvasBounds, startLocation = { x: canvasBounds.startX, y: canvasBounds.startY }, width = canvasBounds.endX - startLocation.x, height = canvasBounds.endY - startLocation.y, omax = axisInfo.max, omin = axisInfo.min, origin = options.origin, adjust = this.bubbleAxisAdjust.getAdjust(axisInfo, options);

                omax = adjust.max;
                omin = adjust.min;

                if (omax !== axisInfo.max || omin !== axisInfo.min) {
                    axisInfo.min = omin;
                    axisInfo.max = omax;
                    this._calculateMajorMinor(options, axisInfo);
                }
            };

            wijbubblechart.prototype._showSerieEles = function (seriesEle) {
                if (seriesEle.isTrendline) {
                    chart.TrendlineRender.showSerieEles(seriesEle);
                    return;
                }
                $.each(seriesEle, function (i, bubbleInfo) {
                    if (bubbleInfo.bubble) {
                        bubbleInfo.bubble.show();
                        if (bubbleInfo.bubble.shadow) {
                            bubbleInfo.bubble.shadow.show();
                        }
                        if (bubbleInfo.bubble.tracker) {
                            bubbleInfo.bubble.tracker.show();
                        }
                        if ($(bubbleInfo.bubble.node).data("wijchartDataObj")) {
                            $(bubbleInfo.bubble.node).data("wijchartDataObj").visible = true;
                        }
                    }
                    if (bubbleInfo.dcl) {
                        bubbleInfo.dcl.show();
                    }
                    if (bubbleInfo.symbol) {
                        bubbleInfo.symbol.show();
                    }
                });
            };

            wijbubblechart.prototype._hideSerieEles = function (seriesEle) {
                if (seriesEle.isTrendline) {
                    chart.TrendlineRender.hideSerieEles(seriesEle);
                    return;
                }
                $.each(seriesEle, function (i, bubbleInfo) {
                    if (bubbleInfo.bubble) {
                        bubbleInfo.bubble.hide();
                        if (bubbleInfo.bubble.shadow) {
                            bubbleInfo.bubble.shadow.hide();
                        }
                        if (bubbleInfo.bubble.tracker) {
                            bubbleInfo.bubble.tracker.hide();
                        }
                        if ($(bubbleInfo.bubble.node).data("wijchartDataObj")) {
                            $(bubbleInfo.bubble.node).data("wijchartDataObj").visible = false;
                        }
                    }
                    if (bubbleInfo.dcl) {
                        bubbleInfo.dcl.hide();
                    }
                    if (bubbleInfo.symbol) {
                        bubbleInfo.symbol.hide();
                    }
                });
            };

            wijbubblechart.prototype._indicatorLineShowing = function (objs) {
                _super.prototype._indicatorLineShowing.call(this, objs);
                $.each(objs, function (i, obj) {
                    if (obj.bubble) {
                        obj.bubble.attr(obj.hoverStyle);
                    }
                });
            };

            wijbubblechart.prototype._removeIndicatorStyles = function (objs) {
                $.each(objs, function (i, obj) {
                    if (obj.bubble) {
                        obj.bubble.attr(obj.style);
                    }
                });
            };

            wijbubblechart.prototype._parseTable = function () {
                if (!this.element.is("table")) {
                    return;
                }
                var self = this, ele = self.element, o = self.options, captions = $("caption", ele), theaders = $("thead th", ele), seriesList = [], sList = $("tbody tr", ele), label = null, series = null, xValues = [], yValues = [], y1Values = [], getValue = function (val) {
                    var ret = $.trim(val);
                    if (!isNaN(val)) {
                        ret = parseFloat(val.toString());
                    }
                    return ret;
                };

                if (captions.length) {
                    o.header = $.extend({
                        visible: true,
                        text: $.trim($(captions[0]).text())
                    }, o.header);
                    if (captions.length > 1) {
                        o.footer = $.extend({
                            visibel: true,
                            text: $.trim($(captions[1]).text())
                        }, o.footer);
                    }
                }

                //legend
                o.legend = $.extend({
                    visible: true
                }, o.legend);

                label = $.trim(theaders.eq(1).text());

                //seriesList
                sList.each(function (i, tr) {
                    var tds = $("td", tr);
                    if (tds.length >= 3) {
                        xValues.push(getValue(tds.eq(0).text()));
                        yValues.push(getValue(tds.eq(1).text()));
                        y1Values.push(getValue(tds.eq(2).text()));
                    }
                    return this;
                });

                series = {
                    label: label,
                    legendEntry: true,
                    data: {
                        x: xValues,
                        y: yValues,
                        y1: y1Values
                    }
                };
                seriesList.push(series);
                self.options.seriesList = seriesList;
            };

            wijbubblechart.prototype._unbindLiveEvents = function () {
                var self = this;
                $("." + self.options.wijCSS.bubbleElement, self.chartElement[0]).off(".wijbubblechart").off("wijbubblechart");
                if (self.tooltip) {
                    self.tooltip.destroy();
                    self.tooltip = null;
                }
            };

            wijbubblechart.prototype._paintTooltip = function () {
                var self = this, fields = self.chartElement.data("fields");

                _super.prototype._paintTooltip.call(this);

                if (self.tooltip) {
                    if (fields && fields.trackers && fields.trackers.length) {
                        self.tooltip.setTargets(fields.trackers);
                        self.tooltip.setOptions({ relatedElement: fields.trackers[0] });
                    }
                }
            };

            wijbubblechart.prototype._getTooltipText = function (fmt, target) {
                var tar = $(target.node), dataObj, obj;
                if (tar.data("owner")) {
                    tar = tar.data("owner");
                }
                dataObj = tar.data("wijchartDataObj");
                obj = {
                    data: dataObj,
                    value: dataObj.value,
                    label: dataObj.label,
                    total: dataObj.total,
                    target: target,
                    fmt: fmt,
                    x: dataObj.x,
                    y: dataObj.y,
                    y1: dataObj.y1
                };
                return $.proxy(fmt, obj)();
            };
            return wijbubblechart;
        })(chart.wijchartcore);
        chart.wijbubblechart = wijbubblechart;

        wijbubblechart.prototype.widgetEventPrefix = "wijbubblechart";

        var wijbubblechart_css = (function (_super) {
            __extends(wijbubblechart_css, _super);
            function wijbubblechart_css() {
                _super.apply(this, arguments);
                this.bubbleChart = "wijmo-wijbubblechart";
                this.bubbleElement = "wijbubblechart-bubble";
                this.bubbleTracker = "bubbletracker";
                this.bubbleLabel = "wijbubblechart-label";
                this.bubbleSymbol = "wijbubblechart-symbol";
            }
            return wijbubblechart_css;
        })(chart.wijchartcore_css);
        chart.wijbubblechart_css = wijbubblechart_css;

        var wijbubblechart_options = (function (_super) {
            __extends(wijbubblechart_options, _super);
            function wijbubblechart_options() {
                _super.apply(this, arguments);
                /**
                * Selector option for auto self initialization. This option is internal.
                * @ignore
                */
                this.initSelector = ":jqmData(role='wijbubblechart')";
                /**
                * @ignore
                */
                this.wijCSS = new wijmo.chart.wijbubblechart_css();
                /**
                * The minimum bubble size represents the percentage of the diameter (or area) of the plot area.
                */
                this.minimumSize = 5;
                /**
                * The maximum bubble size represents the percentage of the diameter (or area) of the plot area.
                */
                this.maximumSize = 20;
                /**
                * A value that indicates how to calculate the bubble size.
                * @remarks
                * Valid Values: "area" and "diameter"
                *	area: Render the bubble's area based on the y1 value.
                *	diameter: Render the bubble's diameter based on the y1 value.
                */
                this.sizingMethod = "diameter";
                /**
                * The animation option defines the animation effect and controls other aspects of the widget's animation,
                * such as duration and easing.
                */
                this.animation = {
                    /**
                    * A value that determines whether to show animation. Set this option to false in order to disable animation.
                    */
                    enabled: true,
                    /**
                    * The duration option defines the length of the animation effect in milliseconds.
                    */
                    duration: 1000,
                    /**
                    * Sets the type of animation easing effect that users experience when they load the wijbubblechart series.
                    * @remarks
                    * The easing is defined in Raphael, the documentation is:http://raphaeljs.com/reference.html#Raphael.easing_formulas
                    */
                    easing: ">"
                };
                /**
                * The seriesTransition option is used to animate series in the chart when just their values change. This is
                * helpful for visually showing changes in data for the same series.
                */
                this.seriesTransition = {
                    /**
                    * A value that determines whether to show animation when reload.
                    */
                    enabled: true,
                    /**
                    * A value that indicates the duration for the series transition.
                    */
                    duration: 400,
                    /**
                    * A value that indicates the easing for the series transition.
                    * @remarks
                    * The easing is defined in Raphael, the documentation is:http://raphaeljs.com/reference.html#Raphael.easing_formulas
                    */
                    easing: ">"
                };
                /**
                * Sets the data for the chart to display.
                * @example
                * $("#bubblechart").wijbubblechart({
                * seriesList: [{
                * label: "Q1",
                * legendEntry: true,
                * data: {
                * x: [1, 2, 3, 4, 5],
                * y: [12, 21, 9, 29, 30],
                * y1:[3, 5, 1, 6, 2]
                * }
                * }, {
                * label: "Q2",
                * legendEntry: true,
                * data: {
                * xy: [1, 21, 2, 10, 3, 19, 4, 31, 5, 20],
                * y1:[3, 5, 1, 6, 2]
                * }
                * }]
                * OR
                * seriesList: [{
                * label: "Q1",
                * legendEntry: true,
                * data: {
                * x: ["A", "B", "C", "D", "E"],
                * y: [12, 21, 9, 29, 30],
                * y1:[3, 5, 1, 6, 2]
                * }
                * }]
                * OR
                * seriesList: [{
                * label: "Q1",
                * legendEntry: true,
                * data: {
                * x: [new Date(1978, 0, 1), new Date(1980, 0, 1),
                * new Date(1981, 0, 1), new Date(1982, 0, 1),
                * new Date(1983, 0, 1)],
                * y: [12, 21, 9, 29, 30],
                * y1:[3, 5, 1, 6, 2]
                * }
                * }]
                * });
                */
                this.seriesList = [];
                /**
                * An array collection that contains the style applied to the chart elements. For more information on the available
                * style parameters.
                * @example
                * $("#bubblechart").wijbubblechart("option", "seriesHoverStyles", {
                *	seriesHoverStyles: [
                *		{fill: "rgb(255,0,0)", stroke:"none"},
                *		{ fill: "rgb(255,125,0)", stroke: "none" }
                *	]});
                */
                this.seriesHoverStyles = [
                    {
                        opacity: 1,
                        "stroke-width": 5
                    }, {
                        opacity: 1,
                        "stroke-width": 5
                    }, {
                        opacity: 1,
                        "stroke-width": 5
                    }, {
                        opacity: 1,
                        "stroke-width": 5
                    }, {
                        opacity: 1,
                        "stroke-width": 5
                    }, {
                        opacity: 1,
                        "stroke-width": 5
                    }, {
                        opacity: 1,
                        "stroke-width": 5
                    }, {
                        opacity: 1,
                        "stroke-width": 5
                    }, {
                        opacity: 1,
                        "stroke-width": 5
                    }, {
                        opacity: 1,
                        "stroke-width": 5
                    }, {
                        opacity: 1,
                        "stroke-width": 5
                    }, {
                        opacity: 1,
                        "stroke-width": 5
                    }];
                /**
                * Creates a chartLabel object that defines all of the settings used to draw a label for each bubble in the chart.
                * @example
                * // This code creates a chart with a label outside (and to the south) of each bubble with the numbers formatted
                * // as percentages with no decimal spaces, in purple size 14 font
                * $(document).ready(function () {
                *	$("#wijbubblechart").wijbubblechart({
                *		axis: {
                *			y: { text: "Number of Products" },
                *			x: { text: "Sales", annoFormatString: "C0" }
                *		},
                *		chartLabel: {
                *			chartLabelFormatString: "P0",
                *			compass: "south",
                *			position: "outside",
                *			style: { fill: "purple", "font-size": 14 }
                *		},
                *		legend: { visible: false },
                *		seriesList: [
                *        {
                *        	label: "Company A Market Share",
                *        	data: { y: [14], x: [12200], y1: [.15] }
                *        }, {
                *        	label: "Company B Market Share",
                *        	data: { y: [20], x: [60000], y1: [.23] }
                *        }, {
                *        	label: "Company C Market Share",
                *        	data: { y: [18], x: [24400], y1: [.1] }
                *        }]
                *	});
                *});
                */
                this.chartLabel = {
                    /**
                    * A value that indicates whether to draw a label inside our outside of each bubble in the chart.
                    * @remarks
                    * If set to "outside," the compass attribute sets where to draw the label.
                    * The value should be "inside" or "outside".
                    */
                    position: "inside",
                    /**
                    * A value that indicates the compass position at which to draw a chart label next to each bubble
                    * when you set the position option for the label to "outside." If the position is set to "inside,"
                    * this attribute is ignored.
                    * @remarks
                    * The value should be "north", "east", "west" or "south"
                    */
                    compass: "north",
                    /**
                    * The visible option indicates whether to draw a label on each bubble in the chart.
                    */
                    visible: true,
                    /**
                    * A value that indicates the style parameters to apply to the labels on each bubble in the chart.
                    * @remarks
                    * Note: If you do not set any value for this style, the fallback style is chartLabelStyle.
                    * The style is defined in Raphael here is the documentation: http://raphaeljs.com/reference.html#Element.attr.
                    * The style is the “attr” method’s parameters.
                    */
                    style: {},
                    /**
                    * Sets the numeric format of the chart labels that show the value of each bubble.
                    * @remarks
                    * You can use Standard Numeric Format Strings. You can also change the style of these labels using
                    * chartLabelStyle, or to hide them
                    */
                    chartLabelFormatString: ""
                };
                /**
                * Fires when the user clicks a mouse button.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {IBubbleChartEventArgs} data Information about an event
                */
                this.mouseDown = null;
                /**
                * Fires when the user releases a mouse button while the pointer is over the chart element.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {IBubbleChartEventArgs} data Information about an event
                */
                this.mouseUp = null;
                /**
                * Fires when the user first places the pointer over the chart element.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {IBubbleChartEventArgs} data Information about an event
                */
                this.mouseOver = null;
                /**
                * Fires when the user moves the pointer off of the chart element.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {IBubbleChartEventArgs} data Information about an event
                */
                this.mouseOut = null;
                /**
                * Fires when the user moves the mouse pointer while it is over a chart element.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {IBubbleChartEventArgs} data Information about an event
                */
                this.mouseMove = null;
                /**
                * Fires when the user clicks the chart element.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {IBubbleChartEventArgs} data Information about an event
                */
                this.click = null;
            }
            return wijbubblechart_options;
        })(chart.wijchartcore_options);

        wijbubblechart.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijbubblechart_options());

        //$.widget("wijmo.wijbubblechart", WijBubbleChart.prototype);
        $.wijmo.registerWidget("wijbubblechart", wijbubblechart.prototype);

        /**
        * @ignore
        */
        var BubbleChartRender = (function (_super) {
            __extends(BubbleChartRender, _super);
            function BubbleChartRender(element, options) {
                _super.call(this, element, options);
            }
            BubbleChartRender.prototype._init = function () {
                _super.prototype._init.call(this);
                var o = this.options, bounds = o.bounds;
                this.seriesList = $.arrayClone(o.seriesList);
                this.seriesStyles = o.seriesStyles;
                this.seriesHoverStyles = o.seriesHoverStyles;
                this.startLocation = { x: bounds.startX, y: bounds.startY };
                this.seriesEles = [];
                this.bubbles = [];
                this.bubbleInfos = [];
                this.trackers = this.canvas.set();
                this.animationSet = this.canvas.set();
                this.fieldsAniPathAttr = [];
                this.paths = [];
                this.aniPathsAttr = [];

                this.showBubbleLabels = o.chartLabel.visible && o.showChartLabels;
            };

            BubbleChartRender.prototype.initAnimationState = function (bubbleInfo, bounds) {
                var bubble = bubbleInfo.bubble, symbol = bubbleInfo.symbol, bbox;

                if (bubble.type === "circle") {
                    bubble.attr({
                        r: 0.0001,
                        cx: bounds.startX,
                        cy: bounds.endY
                    });
                } else {
                    bbox = bubble.wijGetBBox();

                    //when play animation, it will added the transform to move and scale the bubble element to start point and small size.
                    // the exists transform string should put behind of the animation transform.
                    bubble.transform("t" + (bounds.startX - bbox.x) + "," + (bounds.endY - bbox.y) + "s0.001...");
                    if (bubble.shadow) {
                        bubble.shadow.transform("t" + (bounds.startX - bbox.x) + "," + (bounds.endY - bbox.y) + "s0.001...");
                    }
                }
                if (symbol) {
                    symbol.hide();
                }
            };

            BubbleChartRender.prototype.playAnimation = function () {
                var self = this, o = self.options, animation = o.animation, bounds = o.bounds, bubblesAnimationInfos = self.fields.bubblesAnimationInfos, animationInfos = [], bubbleInfos = self.fields.bubbleInfos, seriesTransition = o.seriesTransition, duration, easing, rate;

                if (!bubbleInfos) {
                    return;
                }

                if (animation && animation.enabled) {
                    duration = animation.duration || 400;
                    easing = animation.easing;
                    if (bubbleInfos) {
                        $.each(bubbleInfos, function (idx, bubbleInfo) {
                            var bubble = bubbleInfo.bubble, params, bubblesAnimationInfo, bbox = bubble.wijGetBBox();

                            if (bubble.type === "circle") {
                                params = {
                                    r: bubble.attr("r"), cx: bubble.attr("cx"),
                                    cy: bubble.attr("cy")
                                };
                            } else {
                                params = {
                                    //directly use the transform srtring before playing animation.
                                    transform: bubble.matrix.toTransformString(),
                                    "stroke-width": bubble.attr("stroke-width"),
                                    width: bbox.width,
                                    x: bbox.x,
                                    y: bbox.y
                                };
                            }
                            if (bubble.shadow) {
                                bubble.shadow.hide();
                            }
                            if (bubblesAnimationInfos && seriesTransition.enabled) {
                                bubblesAnimationInfo = bubblesAnimationInfos[idx];
                                if (bubblesAnimationInfo) {
                                    if (bubble.type === "circle") {
                                        bubble.attr({
                                            cx: bubblesAnimationInfo.cx,
                                            cy: bubblesAnimationInfo.cy,
                                            r: bubblesAnimationInfo.r
                                        });
                                    } else {
                                        bbox = bubble.wijGetBBox();
                                        rate = bubblesAnimationInfo.width / bbox.width;

                                        //directly use the transform before playing animatin.
                                        params.transform = bubble.matrix.toTransformString();
                                        bubble.transform(Raphael.format("s{0}t{1}{2}...", rate, bubblesAnimationInfo.x - bbox.x, bubblesAnimationInfo.y - bbox.y));
                                        if (bubble.shadow) {
                                            bubble.shadow.transform(Raphael.format("s{0}t{1}{2}...", rate, bubblesAnimationInfo.x - bbox.x, bubblesAnimationInfo.y - bbox.y));
                                        }
                                    }
                                    duration = seriesTransition.duration;
                                    easing = seriesTransition.easing;
                                } else {
                                    self.initAnimationState(bubbleInfo, bounds);
                                }
                            } else {
                                self.initAnimationState(bubbleInfo, bounds);
                            }
                            animationInfos.push(params);
                            bubble.wijAnimate(params, duration, easing, function () {
                                if ($(bubbleInfo.bubble.node).data("wijchartDataObj") && $(bubbleInfo.bubble.node).data("wijchartDataObj").visible) {
                                    if (bubbleInfo.dcl) {
                                        bubbleInfo.dcl.show();
                                    }
                                    if (bubbleInfo.symbol) {
                                        bubbleInfo.symbol.show();
                                        bubbleInfo.bubble.wijAttr("opacity", 0.1);
                                    }
                                    if (bubble.shadow) {
                                        bubble.shadow.show();
                                    }
                                }
                            });
                        });
                    }
                    self.fields.bubblesAnimationInfos = animationInfos;
                } else {
                    $.each(bubbleInfos, function (idx, bubbleInfo) {
                        if ($(bubbleInfo.bubble.node).data("wijchartDataObj") && $(bubbleInfo.bubble.node).data("wijchartDataObj").visible) {
                            if (bubbleInfo.dcl) {
                                bubbleInfo.dcl.show();
                            }
                            if (bubbleInfo.symbol) {
                                bubbleInfo.symbol.show();
                            }
                        }
                    });
                }
            };

            BubbleChartRender.prototype.playTrendLineAnimation = function () {
                var self = this, o = self.options, animation = o.animation, animated = animation && animation.enabled, seriesTransition = o.seriesTransition, trendLines = self.fields.trendLines, duration, easing;

                if (animated) {
                    duration = animation.duration || 400;
                    easing = animation.easing || "linear";
                    if (trendLines && trendLines.length) {
                        chart.TrendlineRender.playAnimation(animated, duration, easing, seriesTransition, o.bounds, trendLines, self.fieldsAniPathAttr, o.widget.options.axis, o.widget.extremeValue);
                    }
                }
            };

            BubbleChartRender.prototype.getSymbol = function (symbols, index) {
                var symbol;
                $.each(symbols, function (i, n) {
                    if (n.index === index) {
                        symbol = n;
                        return false;
                    }
                });
                return symbol;
            };

            BubbleChartRender.prototype.getLabelVisible = function (visibles, index) {
                var visible = true;
                $.each(visibles, function (i, n) {
                    if (index === n) {
                        visible = false;
                        return false;
                    }
                });
                return visible;
            };

            BubbleChartRender.prototype.paintMarker = function (type, x, y, length) {
                var marker;
                if (this.canvas[type]) {
                    marker = this.canvas[type](x, y, length);
                }
                return marker;
            };

            BubbleChartRender.prototype.getLabelBox = function (val) {
                var text = this.canvas.text(0, 0, val), bbox = text.wijGetBBox(), ret;

                ret = {
                    width: bbox.width,
                    height: bbox.height
                };
                text.remove();
                return ret;
            };

            BubbleChartRender.prototype.applyLabelCompass = function (rf, text) {
                var compass = this.options.chartLabel.compass || "north", labelBox = this.getLabelBox(text), r = rf.r;

                switch (compass) {
                    case "north":
                        rf.y -= (r + labelBox.height / 2);
                        break;
                    case "south":
                        rf.y += (r + labelBox.height / 2);
                        break;
                    case "east":
                        rf.x += (r + labelBox.width / 2);
                        break;
                    case "west":
                        rf.x -= (r + labelBox.width / 2);
                        break;
                }
            };

            BubbleChartRender.prototype.paintDefaultChartLabel = function (rf, points) {
                var o = this.options, chartLabel = o.chartLabel, culture = o.culture, textStyle = $.extend(true, {}, o.textStyle, o.chartLabelStyle, chartLabel.style), text = $.round(points.y1, 2), chartLabelFormatString = chartLabel.chartLabelFormatString === "" ? o.chartLabelFormatString : chartLabel.chartLabelFormatString, widget = this.options.widget, dcl, processedChartLabel = chart.ChartUtil.getChartLabel(chartLabelFormatString, text, culture, {
                    index: points.sIdx,
                    data: { x: points.x, y: points.y, y1: points.y1 },
                    value: points.y1,
                    chartLabelFormatter: o.chartLabelFormatter
                });

                text = processedChartLabel.text;
                dcl = widget._text.call(widget, rf.x, rf.y, text);
                dcl.wijAttr(textStyle);
                return dcl;
            };

            // A method for getting an array which contains the index of ordered bubbles.
            BubbleChartRender.prototype._getSortedBubbleIndex = function (data) {
                if (!data || !data.y1 || !data.y1.length) {
                    return undefined;
                }
                var length = data.y1.length, tempData = [], resultIndexArray = [];
                for (var i = 0; i < length; i++) {
                    tempData.push({
                        dataIndex: i,
                        y1: data.y1[i]
                    });
                }
                tempData.sort(function (a, b) {
                    return b.y1 - a.y1;
                });
                for (var j = 0; j < length; j++) {
                    resultIndexArray.push(tempData[j].dataIndex);
                }

                return resultIndexArray;
            };

            BubbleChartRender.prototype.paintbubble = function (series, seriesStyle, seriesHoverStyle, xAxisInfo, yAxisInfo, width, height, startLocation, sIndex) {
                var data = series.data, minX = xAxisInfo.min, minY = yAxisInfo.min, maxX = xAxisInfo.max, maxY = yAxisInfo.max, kx = width / (maxX - minX), ky = height / (maxY - minY), serieEles = [], o = this.options, self = this, bounds = o.bounds, wijCSS = o.wijCSS, widget = o.widget, chartLabel = o.chartLabel, bubbleRadius = o.bubbleRadius, dcl, imgWidth, imgHeight, pointX, sortedIndexArray, trackers = [], bubbles = [];

                if (data.y1 === undefined) {
                    return;
                }

                if (data.x === undefined || data.y === undefined) {
                    return true;
                }

                sortedIndexArray = self._getSortedBubbleIndex(data);

                if (!sortedIndexArray || !sortedIndexArray.length) {
                    return;
                }

                $.each(sortedIndexArray, function (i, dataIndex) {
                    var y1 = data.y1[dataIndex], x = data.x[dataIndex], y = data.y[dataIndex], markers = series.markers || {}, markerType = markers.type || "circle", symbols = markers.symbol, invisibleMarkLabels = series.invisibleMarkLabels || [], r = bubbleRadius[y1], rf, bubbleInfo, wijchartDataObj, bubble, sX, sY, symbol, symbolEl, tracker;

                    if (xAxisInfo.isTime) {
                        x = $.toOADate(x);
                    } else if (isNaN(x)) {
                        x = dataIndex;
                    }

                    if (yAxisInfo.isTime) {
                        y = $.toOADate(y);
                    }

                    sX = bounds.startX + (x - minX) * kx;
                    sY = bounds.startY + (maxY - y) * ky;
                    if (symbols) {
                        symbol = self.getSymbol(symbols, dataIndex);
                    }
                    bubble = self.paintMarker(markerType, sX, sY, r);
                    bubble.attr(seriesStyle);
                    if (symbol) {
                        imgWidth = symbol.width || (r * 2);
                        imgHeight = symbol.height || (r * 2);
                        symbolEl = self.canvas.image(symbol.url, sX - r, sY - r, imgWidth, imgHeight);
                    }

                    if (self.options.shadow) {
                        chart.ChartUtil.paintShadow(bubble, 2, null);
                    }
                    $.wijraphael.addClass($(bubble.node), wijCSS.canvasObject + " " + wijCSS.bubbleElement);
                    if (symbol) {
                        bubble.attr("opacity", 0.1);
                    }
                    wijchartDataObj = $.extend(false, {
                        index: dataIndex,
                        bubble: bubble,
                        style: seriesStyle,
                        y1: y1,
                        x: x,
                        y: y,
                        type: "bubble",
                        hoverStyle: seriesHoverStyle,
                        visible: true
                    }, series);
                    if (symbol) {
                        wijchartDataObj.symbol = true;
                        wijchartDataObj.hoverStyle = $.extend({}, seriesHoverStyle, {
                            opacity: 0.1
                        });
                        $(symbolEl.node).data("wijchartDataObj", wijchartDataObj);
                        $.wijraphael.addClass($(symbolEl.node), wijCSS.bubbleSymbol);
                    }
                    $(bubble.node).data("wijchartDataObj", wijchartDataObj);

                    // cache the bar position to show indicator line.
                    widget.dataPoints = widget.dataPoints || {};
                    widget.pointXs = widget.pointXs || [];

                    pointX = $.round(sX, 2);

                    if (!widget.dataPoints[pointX.toString()]) {
                        widget.dataPoints[pointX.toString()] = [];
                        widget.pointXs.push(pointX);
                    }

                    widget.dataPoints[pointX.toString()].push(wijchartDataObj);

                    tracker = bubble.clone();

                    //.attr({ opacity: 0.01, fill: "white", "fill-opacity": 0.01 });
                    // in vml, if the tracker has a stroke, the boder is black.
                    if ($.browser.msie && parseInt($.browser.version) < 9) {
                        tracker.attr({
                            opacity: 0.01, fill: "white",
                            "stroke-width": 0, "fill-opacity": 0.01
                        });
                    } else {
                        tracker.attr({
                            opacity: 0.01, fill: "white",
                            "fill-opacity": 0.01
                        });
                    }

                    $(tracker.node).data("owner", $(bubble.node));
                    $.wijraphael.addClass($(tracker.node), wijCSS.canvasObject + " " + wijCSS.bubbleElement + " " + wijCSS.bubbleTracker);
                    bubble.tracker = tracker;
                    trackers[dataIndex] = tracker;

                    bubbles[dataIndex] = bubble;

                    rf = {
                        x: sX,
                        y: sY,
                        r: r
                    };
                    if (self.showBubbleLabels && self.getLabelVisible(invisibleMarkLabels, dataIndex)) {
                        if (chartLabel.position === "outside") {
                            self.applyLabelCompass(rf, y1);
                        }
                        dcl = self.paintDefaultChartLabel(rf, { x: x, y: y, y1: y1, sIdx: sIndex });
                        dcl.hide();
                        $(dcl.node).data("wijchartDataObj", wijchartDataObj);
                        $.wijraphael.addClass($(dcl.node), wijCSS.bubbleLabel);
                    }

                    if (self.annoPoints[sIndex] == null)
                        self.annoPoints[sIndex] = {};
                    self.annoPoints[sIndex][dataIndex] = { x: rf.x, y: rf.y };

                    bubbleInfo = {
                        bubble: bubble,
                        dcl: dcl,
                        symbol: symbolEl
                    };
                    serieEles[dataIndex] = bubbleInfo;
                    if (series.visible === false) {
                        bubble.hide();
                        if (dcl) {
                            dcl.hide();
                        }
                        tracker.hide();
                        if (symbolEl) {
                            symbolEl.hide();
                        }
                    }
                });
                $.each(trackers, function (tIndex, tk) {
                    if (tk) {
                        self.trackers.push(tk);
                    }
                });
                $.each(bubbles, function (bIndex, bb) {
                    if (bb) {
                        self.bubbles.push(bb);
                    }
                });
                self.fields.bubbles = self.bubbles;

                $.each(serieEles, function (sEIndex, ele) {
                    if (ele) {
                        self.bubbleInfos.push(ele);
                    }
                });
                self.fields.bubbleInfos = self.bubbleInfos;
                self.seriesEles.push(serieEles);
            };

            BubbleChartRender.prototype.paintBubbles = function () {
                var self = this, o = self.options, xAxisInfo = o.xAxisInfo, yAxisInfo = o.yAxisInfo, ani = o.animation, seTrans = o.seriesTransition, wijCSS = o.wijCSS, shadowPaths = [], canvas = o.canvas, axis = o.widget.options.axis;
                self.annoPoints = {};
                $.each(self.seriesList, function (i, series) {
                    var seriesStyle = self.seriesStyles[i], seriesHoverStyle = self.seriesHoverStyles[i];
                    if (series.isTrendline) {
                        chart.TrendlineRender.renderSingleTrendLine(series, seriesStyle, seriesHoverStyle, axis, o.hole, self.fieldsAniPathAttr, ani, seTrans, i, o.bounds, canvas, self.paths, shadowPaths, self.animationSet, self.aniPathsAttr, wijCSS, self.seriesEles, false, o.shadow);
                    } else {
                        self.paintbubble(series, seriesStyle, seriesHoverStyle, xAxisInfo, yAxisInfo, self.width, self.height, self.startLocation, i);
                    }
                });
                this.fields.trendLines = self.paths;
            };

            BubbleChartRender.prototype.bindLiveEvents = function (element, mouseDown, mouseUp, mouseOver, mouseOut, mouseMove, click, disabled) {
                var o = this.options, wijCSS = o.wijCSS, eventPrefix = "", proxyObj = {
                    mousedown: function (e) {
                        if (disabled) {
                            return;
                        }
                        var target = $(e.target), dataObj;
                        if (target.data("owner")) {
                            target = target.data("owner");
                        }
                        dataObj = target.data("wijchartDataObj");
                        mouseDown.call(element, e, dataObj);
                    },
                    mouseup: function (e) {
                        if (disabled) {
                            return;
                        }
                        var target = $(e.target), dataObj;
                        if (target.data("owner")) {
                            target = target.data("owner");
                        }
                        dataObj = target.data("wijchartDataObj");
                        mouseUp.call(element, e, dataObj);
                    },
                    mouseover: function (e) {
                        if (disabled) {
                            return;
                        }
                        var target = $(e.target), dataObj, bubble;
                        if (target.data("owner")) {
                            target = target.data("owner");
                        }
                        dataObj = target.data("wijchartDataObj");
                        bubble = dataObj.bubble;
                        if (!dataObj.hoverStyle) {
                            if (bubble) {
                                bubble.attr({ opacity: "0.8" });
                            }
                        } else {
                            bubble.attr(dataObj.hoverStyle);
                            if (bubble.shadow) {
                                bubble.shadow.attr(dataObj.hoverStyle);
                            }
                        }
                        mouseOver.call(element, e, dataObj);
                    },
                    mouseout: function (e) {
                        if (disabled) {
                            return;
                        }
                        var target = $(e.target), dataObj, bubble;
                        if (target.data("owner")) {
                            target = target.data("owner");
                        }
                        dataObj = target.data("wijchartDataObj");
                        bubble = dataObj.bubble;

                        if (dataObj.symbol) {
                            return;
                        }

                        if (!dataObj.hoverStyle) {
                            if (bubble) {
                                bubble.attr({ opacity: "1" });
                            }
                        } else {
                            if (dataObj.hoverStyle["stroke-width"] && !dataObj.style["stroke-width"]) {
                                bubble.attr("stroke-width", "");
                                if (bubble.shadow) {
                                    bubble.shadow.attr("stroke-width", "");
                                }
                            }
                            bubble.wijAttr({ transform: "" });
                            bubble.wijAttr(dataObj.style);
                            if (dataObj.style.opacity) {
                                bubble.attr("opacity", dataObj.style.opacity);
                                if (bubble.shadow) {
                                    bubble.shadow.attr("opacity", dataObj.style.opacity);
                                }
                            }
                        }
                        mouseOut.call(element, e, dataObj);
                    },
                    mousemove: function (e) {
                        if (disabled) {
                            return;
                        }
                        var target = $(e.target), dataObj, bubble;
                        if (target.data("owner")) {
                            target = target.data("owner");
                        }
                        dataObj = target.data("wijchartDataObj");

                        mouseMove.call(element, e, dataObj);
                    },
                    click: function (e) {
                        if (disabled) {
                            return;
                        }
                        var target = $(e.target), dataObj;
                        if (target.data("owner")) {
                            target = target.data("owner");
                        }
                        dataObj = target.data("wijchartDataObj");
                        click.call(element, e, dataObj);
                    }
                };

                if ($.support.isTouchEnabled && $.support.isTouchEnabled()) {
                    eventPrefix = "wij";
                }

                $.each([
                    "click", "mouseover", "mouseout", "mousemove",
                    "mousedown", "mouseup"], function (i, n) {
                    $("." + wijCSS.bubbleTracker, element).on(eventPrefix + n + ".wijbubblechart", proxyObj[n]);
                });

                chart.TrendlineRender.unbindLiveEvents(element, o.widget.widgetName, wijCSS);
                chart.TrendlineRender.bindLiveEvents(element, o.widget.widgetName, mouseDown, mouseUp, mouseOver, mouseOut, mouseMove, click, disabled, wijCSS, false);
            };

            BubbleChartRender.prototype.render = function () {
                var o = this.options, mouseDown = o.mouseDown, mouseUp = o.mouseUp, mouseOver = o.mouseOver, mouseOut = o.mouseOut, mouseMove = o.mouseMove, click = o.click, disabled = o.disabled;

                this.paintBubbles();
                this.fields.seriesEles = this.seriesEles;
                this.playAnimation();
                this.playTrendLineAnimation();
                this.trackers.toFront();
                this.fields.trackers = this.trackers;
                this.bindLiveEvents(this.element, mouseDown, mouseUp, mouseOver, mouseOut, mouseMove, click, disabled);
                this.element.data("fields", this.fields);
                _super.prototype.render.call(this);
            };
            return BubbleChartRender;
        })(chart.BaseChartRender);
        chart.BubbleChartRender = BubbleChartRender;
    })(wijmo.chart || (wijmo.chart = {}));
    var chart = wijmo.chart;
})(wijmo || (wijmo = {}));

;
/// <reference path="../Base/jquery.wijmo.widget.ts" />
/// <reference path="../wijpager/jquery.wijmo.wijpager.ts" />
/// <reference path="../wijslider/jquery.wijmo.wijslider.ts" />
/// <reference path="../External/declarations/jquery.bgiframe.d.ts" />
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*globals jQuery, window, XMLHttpRequest*/
    /*
    * Depends:
    *     jquery.ui.core.js
    *     jquery.ui.widget.js
    */
    (function (carousel) {
        var $ = jQuery, widgetName = "wijcarousel", cssPrefix = "wijmo-wijcarousel-", baseCss = "wijmo-wijcarousel ", listCss = cssPrefix + "list", itemCss = cssPrefix + "item ", clipCss = cssPrefix + "clip", currentCss = cssPrefix + "current", horizontalMultiCss = cssPrefix + "horizontal-multi", horizontalCss = cssPrefix + "horizontal", btnCss = cssPrefix + "button", verticalMultiCss = cssPrefix + "vertical-multi", verticalCss = cssPrefix + "vertical", nextBtnCss = cssPrefix + "button-next", prevBtnCss = cssPrefix + "button-previous", previewCss = cssPrefix + "preview", btnHtml = "<a><span></span></a>", ctrlSelector = ".wijmo-wijcarousel-pager,." + btnCss + ",." + nextBtnCss + ",." + prevBtnCss, captionHtml = "<div></div>", pagerHtml = "<li class=\"wijmo-wijcarousel-page\"><a></a></li>", liSel = "li.wijmo-wijcarousel-page", captionSel = ".wijmo-wijcarousel-text,.wijmo-wijcarousel-caption", previewNum = 1;

        /** @widget */
        var wijcarousel = (function (_super) {
            __extends(wijcarousel, _super);
            function wijcarousel() {
                _super.apply(this, arguments);
            }
            wijcarousel.prototype._handleDisabledOption = function (disabled, ele) {
                var self = this;

                self._handlePagerState(disabled);

                // when change the disabled option, apply the button CSS class.
                self._applyBtnClass();
            };

            wijcarousel.prototype._handlePagerState = function (disabled) {
                var self = this, o = self.options, pageSlider;
                if (self.pager && !self.pager.is(":hidden")) {
                    if (o.pagerType === "numbers") {
                        self.pager.wijpager("option", "disabled", disabled);
                    } else if ($.wijmo.wijslider && o.pagerType === "slider") {
                        pageSlider = self.pager.find(".ui-slider");
                        if (pageSlider && pageSlider.length > 0) {
                            pageSlider.wijslider("option", "disabled", disabled);
                        }
                    }
                }
            };

            wijcarousel.prototype._initStates = function (o, el) {
                var self = this;
                self.count = 0;
                self.currentIdx = o.start;
                self.timeout = null;
                self.isHorizontal = o.orientation === "horizontal";
                self.width = el.width() || 640;
                self.height = el.height() || 480;
                self.offset = 0;
            };

            wijcarousel.prototype._set_showControlsOnHover = function (value) {
                var self = this;
                self.container.unbind("mouseenter." + self.widgetName);
                self.container.unbind("mouseleave." + self.widgetName);
                if (value) {
                    self.container.bind("mouseenter." + self.widgetName, function () {
                        if (self._isDisabled()) {
                            return;
                        }
                        self._showControls();
                    }).bind("mouseleave." + self.widgetName, function () {
                        if (self._isDisabled()) {
                            return;
                        }
                        self._hideControls();
                    });
                }

                self.container.find(ctrlSelector).stop(true, true)[value ? "hide" : "show"]();
            };

            wijcarousel.prototype._create = function () {
                var self = this, o = self.options, el = self.element;

                // enable touch support:
                if (window.wijmoApplyWijTouchUtilEvents) {
                    $ = window.wijmoApplyWijTouchUtilEvents($);
                }

                self._initStates(o, el);
                self._createDom(self.isHorizontal);
                self.list.bind("click." + self.widgetName, $.proxy(self._itemClick, self));

                if (o.showControlsOnHover) {
                    self.container.bind("mouseenter." + self.widgetName, function () {
                        if (self._isDisabled()) {
                            return;
                        }
                        self._showControls();
                    }).bind("mouseleave." + self.widgetName, function () {
                        if (self._isDisabled()) {
                            return;
                        }
                        self._hideControls();
                    });

                    self.container.find(ctrlSelector).hide();
                }

                if (o.loadCallback && $.isFunction(o.loadCallback)) {
                    self._trigger("loadCallback", null, self);
                }

                if (!this._isDisabled() && o.auto) {
                    self.play();
                }

                try  {
                    o.display = parseFloat(o.display);
                } catch (e) {
                    o.display = 1;
                }

                //update for visibility change
                if (self.element.is(":hidden") && self.element.wijAddVisibilityObserver) {
                    self.element.wijAddVisibilityObserver(function () {
                        self.refresh();
                        if (self.element.wijRemoveVisibilityObserver) {
                            self.element.wijRemoveVisibilityObserver();
                        }
                    }, "wijcarousel");
                }
                _super.prototype._create.call(this);
            };

            wijcarousel.prototype._innerDisable = function () {
                _super.prototype._innerDisable.call(this);
                if (this.isPlaying) {
                    this.pause();
                }
                this._handleDisabledOption(true, this.element);
            };

            wijcarousel.prototype._innerEnable = function () {
                _super.prototype._innerEnable.call(this);
                this._handleDisabledOption(false, this.element);
            };

            wijcarousel.prototype._showControls = function () {
                this.container.find(ctrlSelector).stop(true, true).fadeIn(600, function () {
                    $(this).css("opacity", "");
                });
            };

            wijcarousel.prototype._hideControls = function () {
                this.container.find(ctrlSelector).stop(true, true).fadeOut(600);
            };

            wijcarousel.prototype._applyContainerStyle = function (isHorizontal, isPreviewCreated) {
                /// <summary>
                /// Apply special styles. after create dom element.
                /// </summary>
                var self = this, o = self.options, style = {}, list = self.list, listSize = 0, size, left = 0, dir = isHorizontal ? "left" : "top", i = 0, citem, sizeKey = isHorizontal ? "width" : "height";

                size = self.itemBound[isHorizontal ? "w" : "h"];
                self.count = self.list.children("li").length;
                listSize = self.count * size;
                self.list[sizeKey](listSize);
                self.clip[sizeKey](o.display * size);

                //self.container[sizeKey](o.display * size);
                self.clip[isHorizontal ? "height" : "width"](self.itemBound[isHorizontal ? "h" : "w"]);

                if (!o.loop) {
                    style[dir] = -size * self.currentIdx;
                    list.css(style);
                } else {
                    citem = list.find(">li:first");

                    // if preview mode the cuurent item is the second item of ul
                    if (o.preview && !!isPreviewCreated) {
                        citem = citem.next(); //previewNum
                    }
                    i = citem.data("itemIndex");

                    for (i; i < self.currentIdx; i++) {
                        list.children("li:first").appendTo(list);
                    }

                    if (o.preview) {
                        if (!isPreviewCreated) {
                            for (i = 0; i < previewNum; i++) {
                                list.children("li:last").prependTo(list);
                            }
                        }
                        left = -size * previewNum;
                    }
                    style[dir] = left;
                    list.css(style);
                }
            };

            wijcarousel.prototype._applyListStyle = function () {
                var self = this, o = self.options, isHorizontal = o.orientation === "horizontal", listSize = 0, size, sizeKey = isHorizontal ? "width" : "height";

                self.itemBound = self._getItemBound();
                size = self.itemBound[isHorizontal ? "w" : "h"];
                listSize = self.count * size;
                self.list[sizeKey](listSize);
            };

            wijcarousel.prototype._createButtons = function (prevIconCss, nextIconCss) {
                var self = this, o = self.options, hover, disableClass = o.wijCSS.stateDisabled;

                $.each(["prevBtn", "nextBtn"], function (i, n) {
                    var css = o[n + "Class"], is = n === "nextBtn", func = is ? "next" : "previous", btnCss = is ? nextBtnCss : prevBtnCss, iconCss = is ? nextIconCss : prevIconCss;
                    if (css && css.defaultClass) {
                        disableClass = css.disableClass || disableClass;
                        hover = css.hoverClass; //|| hover;

                        self[n] = $("<a class=\"" + o.wijCSS.stateDefault + "\"></a>").addClass(css.defaultClass).mouseover(function () {
                            if (!$(this).hasAllClasses(disableClass)) {
                                $(this).addClass(hover);
                            }
                        }).mouseout(function () {
                            if (!$(this).hasAllClasses(disableClass)) {
                                $(this).removeClass(hover);
                            }
                        });
                    } else {
                        self[n] = $(self._createBtn(btnCss, iconCss));
                    }

                    //self[n].bind("click." + self.widgetName, $.proxy(self[func], self))
                    self[n].bind("click." + self.widgetName, function (event) {
                        //handle the disabled state.
                        if (self._isDisabled()) {
                            return;
                        }

                        var btn = $(this);
                        if (btn.hasAllClasses(o.wijCSS.stateDisabled)) {
                            return;
                        }
                        self[func].call(self);
                    }).appendTo(self.container);

                    // add iframe for preventing prevBtn/nextBtn display behind the iframe
                    if ($.browser.msie && self.clip.find("iframe").length > 0) {
                        var frame = self.element.children('iframe.bgiframe.' + n + 'Frame');
                        if (frame.length === 0) {
                            frame = $('<iframe class="bgiframe ' + n + 'Frame" frameborder="0" tabindex="-1" src="javascript: false;" style="position:absolute;top:0px;left:0px;opacity:0;" />');
                            frame.width(self[n].outerWidth());
                            frame.height(self[n].outerHeight());
                            self.container.append(frame);
                        }
                    }
                });
            };

            wijcarousel.prototype._applyBtnClass = function () {
                var self = this, o = self.options, disable = o.wijCSS.stateDisabled, hover = o.wijCSS.stateHover;
                $.each(["prevBtn", "nextBtn"], function (i, n) {
                    var css = o[n + "Class"], con, btn = self[n];
                    if (css) {
                        disable = css.disableClass || disable;
                        hover = css.hoverClass || hover;
                    }
                    con = n === "prevBtn" ? (self.currentIdx <= 0) : ((self.currentIdx + o.display) >= self.count);

                    if ((con && !o.loop) || self._isDisabled()) {
                        btn.removeClass(hover).addClass(disable);
                    } else if (btn.hasAllClasses(disable)) {
                        btn.removeClass(disable);
                    }
                });
            };

            wijcarousel.prototype._applyBtnStyle = function (isHorizontal) {
                var self = this, buttonSize = 0, buttonOffset, css = self.options.wijCSS, nextPosition = {
                    collision: "none",
                    of: self.container,
                    my: isHorizontal ? "right{offset} center" : "center bottom{offset}",
                    at: isHorizontal ? "right center" : "center bottom"
                }, prevPosition = {
                    collision: "none",
                    of: self.container,
                    my: isHorizontal ? "left{offset} center" : "center top{offset}",
                    at: isHorizontal ? "left center" : "center top"
                }, inside = self.options.buttonPosition === "inside", nextCorner, prevCorner, dirs = ["cornerBottom", "cornerTop", "cornerRight", "cornerLeft"], ndir = (isHorizontal ? 1 : 0) * 2 + (inside ? 1 : 0), pdir = (isHorizontal ? 1 : 0) * 2 + (!inside ? 1 : 0), appltStyle = function (btn, c1, c2, offset, position) {
                    var off = "";
                    btn.removeClass(c1).addClass(c2);
                    if (!isNaN(offset) && offset !== 0) {
                        if (offset > 0) {
                            off = "+" + offset;
                        } else {
                            off = "-" + (-offset);
                        }
                    }
                    position.my = position.my.replace(/\{offset\}/, off);
                    btn.position(position);

                    // add iframe for preventing prevBtn/nextBtn display behind the iframe
                    if ($.browser.msie) {
                        var frame = btn.next("iframe.bgiframe");
                        if (frame.length) {
                            frame.css("left", btn.css("left"));
                            frame.css("top", btn.css("top"));
                        }
                    }
                };

                buttonSize = isHorizontal ? self.prevBtn.width() : self.prevBtn.height();
                buttonOffset = inside ? 0 : buttonSize;

                nextCorner = css[dirs[ndir]];
                prevCorner = css[dirs[pdir]];

                appltStyle(self.nextBtn, prevCorner, nextCorner, buttonOffset, nextPosition);
                appltStyle(self.prevBtn, nextCorner, prevCorner, -buttonOffset, prevPosition);

                self._applyBtnClass();
            };

            wijcarousel.prototype._createDom = function (isHorizontal) {
                /// <summary>
                /// Create base dom , apply styles , bind event
                /// </summary>
                var self = this, o = self.options, el = self.element, containerCss, nextIconCss, prevIconCss, allCss;
                if (el.is("div")) {
                    self.list = el.children("ul:eq(0)");
                    self.container = self.element;
                    if (!self.list.length) {
                        self.list = $("<ul></ul>").appendTo(self.container);
                    }
                } else if (el.is("ul")) {
                    self.list = el;
                    self.container = el.parent();
                } else {
                    return;
                }

                self.itemBound = self._getItemBound();

                if (isHorizontal) {
                    containerCss = (o.display > 1 && !o.preview) ? horizontalMultiCss : horizontalCss;
                    nextIconCss = o.wijCSS.iconArrowRight;
                    prevIconCss = o.wijCSS.iconArrowLeft;
                } else {
                    containerCss = (o.display > 1 && !o.preview) ? verticalMultiCss : verticalCss;
                    nextIconCss = o.wijCSS.iconArrowDown;
                    prevIconCss = o.wijCSS.iconArrowUp;
                }

                self.list.addClass(listCss).addClass(o.wijCSS.helperClearFix);

                allCss = baseCss + o.wijCSS.widget + " " + containerCss + " " + (o.preview ? (previewCss + " ") : "") + (o.display > 1 ? o.wijCSS.content + " " + o.wijCSS.cornerAll : "");

                self.container.addClass(allCss);

                //set dir to default value:ltr
                self.container.attr("dir", "ltr");
                self._createItems(isHorizontal);
                self._createClip(isHorizontal);
                self._applyContainerStyle(isHorizontal);
                self._createButtons(prevIconCss, nextIconCss);
                self._applyBtnStyle(isHorizontal);

                if (o.preview) {
                    self._createPreview();
                }
                if (o.showTimer) {
                    self._createTimer();
                }
                if (o.showPager) {
                    self._createPager();
                }
                if (o.showControls) {
                    self._createControls();
                }
            };

            // add new feature
            wijcarousel.prototype._createPreview = function () {
                var self = this, o = self.options, offset, size, isH = o.orientation === "horizontal", dir = isH ? "left" : "top", antiDir = isH ? "right" : "bottom", bound, idx;

                size = self.itemBound[isH ? "w" : "h"];
                offset = self.offset = Math.round(size / 4);
                bound = o.display * size + offset * 2;

                self.clip[isH ? "width" : "height"](bound);

                self.list.css(dir, function (i, v) {
                    return parseFloat(v) + offset;
                });
                self.clip.css(dir, function (i, v) {
                    return -offset;
                });

                self.container.css("margin-" + dir, offset + "px").css("margin-" + antiDir, offset + "px");

                self.list.find(captionSel).hide();

                for (idx = 0; idx < o.display; idx++) {
                    self._getItemByIndex(self.currentIdx + idx).find(captionSel).show();
                }
            };

            wijcarousel.prototype._createItemsFromData = function (data) {
                var self = this;
                if (!$.isArray(data) || !data.length || !$.isPlainObject(data[0]) || $.isEmptyObject(data[0])) {
                    return;
                }
                self.list.empty();
                $.each(data, function (idx, item) {
                    var li;
                    if (!$.isPlainObject(item)) {
                        return true;
                    }
                    li = self._generateMarkup(item);
                    self.list.append(li);
                });
            };

            wijcarousel.prototype._generateMarkup = function (item) {
                var li, a;
                if (!$.isPlainObject(item)) {
                    return;
                }
                li = $("<li></li>");
                if (typeof item.linkUrl === "string" && item.linkUrl) {
                    a = $("<a>").attr("href", item.linkUrl);
                    a.appendTo(li);
                }
                if (typeof item.imageUrl === "string" && item.imageUrl) {
                    $("<img>").attr("src", item.imageUrl).appendTo(a || li);
                }
                if (typeof item.caption === "string" && item.caption) {
                    $("<span>").html(item.caption).appendTo(li);
                }
                return li;
            };

            wijcarousel.prototype._createItems = function (isHorizontal) {
                var self = this, displays, i, o = self.options, currentItem, item;
                if (self.list) {
                    self._createItemsFromData(o.data);
                    self.list.children("li").each(function (idx, data) {
                        var item = $(data);
                        self._createItem(item, idx);
                    });

                    currentItem = self.list.children("li").eq(self.currentIdx).addClass(currentCss);

                    if (o.preview && o.display > 1) {
                        displays = item = currentItem;
                        for (i = 0; i < o.display - 1; i++) {
                            item = item.next();
                            displays = displays.add(item);
                        }
                        displays.find("div.wijmo-wijcarousel-mask").css({ opacity: 0 });
                    }
                }
            };

            wijcarousel.prototype._createItem = function (item, idx) {
                var self = this, o = self.options, img, span;

                img = item.addClass(itemCss).addClass(o.wijCSS.helperClearFix).find("img:eq(0)").attr("role", "img").addClass("wijmo-wijcarousel-image");

                self._applyItemBound(item);
                span = item.children("span:eq(0)").hide();
                self._createCaption(item, img, span);

                if (o.preview) {
                    if (item.children("div.wijmo-wijcarousel-mask").length === 0) {
                        $("<div class=\"wijmo-wijcarousel-mask\">").appendTo(item);
                    }
                } else {
                    item.children("div.wijmo-wijcarousel-mask").remove();
                }

                item.data("itemIndex", idx);
                return item;
            };

            wijcarousel.prototype._applyItemBound = function (item) {
                var self = this, w = self.itemBound.w, h = self.itemBound.h;

                if (!self.itemWidth || !self.itemHeight) {
                    item.width(w).height(h);
                    self.itemWidth = w - (item.outerWidth(true) - w);
                    self.itemHeight = h - (item.outerHeight(true) - h);
                }
                item.width(self.itemWidth).height(self.itemHeight);
            };

            wijcarousel.prototype._createCaption = function (item, img, span) {
                var self = this, o = self.options, caption, text, content, overlay, height;
                if (o.showCaption) {
                    caption = span.html() || img.attr("title");
                    if (caption && caption.length) {
                        content = $("<span></span>").html(caption);

                        overlay = $(captionHtml).addClass([o.wijCSS.helperClearFix, "wijmo-wijcarousel-caption"].join(' ')).appendTo(item);

                        text = $(captionHtml).addClass([o.wijCSS.helperClearFix, o.wijCSS.content, "wijmo-wijcarousel-text"].join(' ')).append(content).appendTo(item);

                        self._applyCaptionStyle(overlay, text);
                    }
                }
            };

            wijcarousel.prototype._applyCaptionStyle = function (overlay, text) {
                var caption = overlay.add(text), height;
                caption.width(this.itemWidth);

                if ($.browser.webkit) {
                    height = text.children("span").css("display", "inline-block").height();
                    text.children("span").css("display", "");
                } else {
                    height = text.children("span").height();
                }
                caption.height(height);
            };

            wijcarousel.prototype._showCaption = function (idx, lastIndex) {
                var self = this, item = self._getItemByIndex(idx), text = item.find(".wijmo-wijcarousel-text"), caption = item.find(".wijmo-wijcarousel-caption");
                if (text.length) {
                    text.fadeIn(300, function () {
                        if (idx < lastIndex) {
                            self._showCaption(idx + 1, lastIndex);
                        }
                    });
                }
                if (caption.length) {
                    caption.show();
                    caption.animate({ opacity: 0.5 }, 300);
                }
            };

            wijcarousel.prototype._hideCaption = function () {
                this.element.find(captionSel).hide();
            };

            wijcarousel.prototype._createClip = function (isHorizontal) {
                this.clip = this.list.wrap("<div></div>").parent().addClass(clipCss);
            };

            wijcarousel.prototype._createBtn = function (btnClass, itemClass) {
                var btn = $(btnHtml), o = this.options;
                btn.addClass(o.wijCSS.stateDefault + ' ' + btnClass).attr("role", "button").mouseover(function () {
                    if (!$(this).hasAllClasses(o.wijCSS.stateDisabled)) {
                        $(this).addClass(o.wijCSS.stateHover);
                    }
                }).mouseout(function () {
                    if (!$(this).hasAllClasses(o.wijCSS.stateDisabled)) {
                        $(this).removeClass(o.wijCSS.stateHover);
                    }
                }).children("span:eq(0)").addClass(o.wijCSS.icon + ' ' + itemClass);
                return btn;
            };

            wijcarousel.prototype._createControls = function () {
                var self = this, o = self.options, position = {
                    collision: "none",
                    of: self.container,
                    my: "center bottom",
                    at: "center bottom"
                };
                if (o.control) {
                    self.controls = $(o.control).css({ position: "absolute" }).appendTo(self.container);
                    $.extend(position, o.controlPosition);
                    self.controls.position(position);
                }
            };

            wijcarousel.prototype._createTimer = function () {
                var self = this, o = self.options;
                self._createPausePlay();

                self.progressBar = $("<div></div>").addClass("wijmo-wijcarousel-timerbar-inner " + o.wijCSS.cornerAll).css({ width: "0%" }).attr("role", "progressbar");

                self.timer = $("<div></div>").addClass("wijmo-wijcarousel-timerbar " + o.wijCSS.cornerAll).appendTo(self.container).append(self.progressBar).append(self.playPauseBtn);
            };

            wijcarousel.prototype._createPausePlay = function () {
                var self = this, o = self.options;
                self.playPauseBtn = $(self._createBtn(btnCss, o.auto ? o.wijCSS.iconPause : o.wijCSS.iconPlay)).bind("click." + self.widgetName, function () {
                    if (self._isDisabled()) {
                        return;
                    }
                    var icon = $(this).children("span:eq(0)");
                    self[icon.hasAllClasses(o.wijCSS.iconPlay) ? "play" : "pause"]();
                });
            };

            wijcarousel.prototype._createPagingItem = function (isDot, thumbOpt, ul, idx) {
                var item = $(pagerHtml).attribute({
                    "role": "tab",
                    "aria-label": idx + 1,
                    "title": idx + 1
                }).addClass(this.options.wijCSS.stateDefault), width, height;
                if (isDot) {
                    item.addClass("wijmo-wijcarousel-dot");
                } else {
                    if (thumbOpt && thumbOpt.images && thumbOpt.images[idx]) {
                        width = thumbOpt.imageWidth;
                        height = thumbOpt.imageHeight;
                        if (width && height) {
                            item.width(width).height(height);
                        }
                        item.children("a").append($("<img>").attr("src", thumbOpt.images[idx]));
                    } else {
                        return;
                    }
                }
                ul.append(item);
            };

            wijcarousel.prototype._createPaging = function (type) {
                var self = this, o = self.options, i, ul, li, thumbOpt = o.thumbnails, isDot = type === "dots";

                self.container.append(self.pager = $("<div><ul class=\"wijmo-list " + o.wijCSS.cornerAll + " " + o.wijCSS.helperClearFix + "\" role=\"tablist\"></ul></div>"));
                if (!isDot) {
                    self.pager.addClass("wijmo-wijcarousel-thumbnails");
                }
                ul = self.pager.children("ul.wijmo-list");

                for (i = 0; i < self.count; i++) {
                    self._createPagingItem(isDot, thumbOpt, ul, i);
                }
                li = self.pager.find("li").eq(self.currentIdx);
                if (li.length) {
                    self._activePagerItem(li);
                }

                //Add support for jUICE!
                if (thumbOpt) {
                    $.each(["mousedown", "mouseup", "mouseover", "mouseout", "click"], function (i, n) {
                        var c = thumbOpt[n];
                        if (c && (typeof c === "string") && window[c]) {
                            thumbOpt[n] = window[c];
                        }
                    });
                }

                //end
                self.pager.bind("mouseover." + self.widgetName, function (event) {
                    if (self._isDisabled()) {
                        return;
                    }
                    self._pageingEvents(event, "mouseover", thumbOpt, isDot, function (li) {
                        li.addClass(o.wijCSS.stateHover);
                    });
                }).bind("mouseout." + self.widgetName, function (event) {
                    if (self._isDisabled()) {
                        return;
                    }
                    self._pageingEvents(event, "mouseout", thumbOpt, isDot, function (li) {
                        li.removeClass(o.wijCSS.stateHover);
                    });
                }).bind("click." + self.widgetName, function (event) {
                    if (self._isDisabled()) {
                        return;
                    }
                    self._pageingEvents(event, "click", thumbOpt, isDot, function (li) {
                        self.scrollTo(li.index());
                        self._activePagerItem(li);
                    });
                });

                if (!isDot) {
                    $.each(["mousedown", "mouseup"], function (i, n) {
                        if ($.isFunction(thumbOpt[n])) {
                            self.pager.bind(n, function (event) {
                                if (self._isDisabled()) {
                                    return;
                                }
                                var li = $(event.target).closest(liSel);
                                if (li.length) {
                                    thumbOpt[n].call(li, event);
                                }
                            });
                        }
                    });
                }
            };

            wijcarousel.prototype._pageingEvents = function (event, type, thumbOpt, isDot, func) {
                var li = $(event.target).closest(liSel);
                if (li.length) {
                    if ($.isFunction(func)) {
                        func.call(event, li);
                    }
                    if (!isDot && $.isFunction(thumbOpt[type])) {
                        thumbOpt[type].call(li, event);
                    }
                }
            };

            wijcarousel.prototype._activePagerItem = function (li) {
                var activeCSS = this.options.wijCSS.stateActive;
                li.addClass(activeCSS).attribute("aria-selected", "true").siblings("li").removeClass(activeCSS).removeAttribute("aria-selected");
            };

            wijcarousel.prototype._createWijSlider = function () {
                var self = this, sOri = self.options.sliderOrientation, options = {
                    orientation: sOri,
                    range: false,
                    min: 0,
                    max: self.count - 1,
                    step: 1,
                    value: self.currentIdx,
                    buttonClick: function (event, ui) {
                        var idx = ui.value;
                        self.scrollTo(idx);
                    },
                    slide: function (event, ui) {
                        var idx = ui.value;
                        self.scrollTo(idx);
                    }
                }, slider = $("<div></div>").css("margin-bottom", "10px").css(sOri === "horizontal" ? "width" : "height", "200px").appendTo(self.container);

                self.pager = slider.wijslider(options).parent().wrap("<div>").parent().addClass("wijmo-wijcarousel-slider-wrapper");
            };

            wijcarousel.prototype._createWijPager = function () {
                var self = this, options = {
                    pageCount: self.count,
                    pageIndex: self.currentIdx,
                    pageButtonCount: self.count,
                    mode: "numeric",
                    pageIndexChanged: function (event, ui) {
                        var idx = ui.newPageIndex;
                        self.scrollTo(idx);
                    }
                }, pager = $("<div></div>").appendTo(self.container);

                self.pager = pager.wijpager(options).css({ position: "absolute" });
            };

            wijcarousel.prototype._createPager = function () {
                var self = this, o = self.options, position = {
                    collision: "none",
                    of: self.container,
                    my: "right top",
                    at: "right bottom"
                };

                if (o.pagerType === "numbers") {
                    self._createWijPager();
                } else if (o.pagerType === "dots" || o.pagerType === "thumbnails") {
                    self._createPaging(o.pagerType);
                    self.pager.css({
                        position: "absolute"
                    });
                } else if ($.wijmo.wijslider && o.pagerType === "slider") {
                    self._createWijSlider();
                    if (o.sliderOrientation !== "horizontal") {
                        position.my = "left center";
                        position.at = "right center";
                    }
                } else {
                    return;
                }
                self.pager.width(self.pager.width() + 1);
                $.extend(position, o.pagerPosition);
                o.pagerPosition = position;
                self.pager.addClass("wijmo-wijcarousel-pager").position(position);
            };

            wijcarousel.prototype._setOption = function (key, value) {
                var self = this, o = self.options, el, create, old, isHorizontal = o.orientation === "horizontal", currentIdx;
                if (key === "pagerPosition" || key === "animation" || key === "controlPosition") {
                    $.extend(true, o[key], value);
                } else {
                    old = o[key];
                    _super.prototype._setOption.call(this, key, value);
                    switch (key) {
                        case "showControls":
                        case "showPager":
                        case "showTimer":
                            if (value === old) {
                                break;
                            }
                            el = key.replace(/show/i, "").toLowerCase();
                            create = key.replace(/show/i, "_create");
                            if (value === true) {
                                if (!self[el]) {
                                    self[create]();
                                } else if (self[el].jquery) {
                                    self[el].show();
                                }
                            } else {
                                self[el].hide();
                            }
                            self._reCreatePager();
                            break;
                        case "loop":
                        case "orientation":
                        case "display":
                        case "preview":
                            if (value !== old) {
                                currentIdx = self.currentIdx;
                                self._wijdestroy();
                                self._create();
                                self.scrollTo(currentIdx);
                            }
                            break;
                        case "data":
                            self._createItems(isHorizontal);
                            self._applyContainerStyle(isHorizontal);
                            self._applyBtnClass();
                            if (o.showPager) {
                                self._createPager();
                            }
                            break;
                        case "showCaption":
                            if (value) {
                                self._createItems(isHorizontal); //re-create item with captions.
                            } else {
                                self.element.find(captionSel).remove();
                            }
                            break;
                        case "buttonPosition":
                            self._applyBtnStyle(isHorizontal);
                            break;
                        case "pagerType":
                            if (value !== old) {
                                self._reCreatePager();
                            }
                            break;
                        case "showControlsOnHover":
                            self._set_showControlsOnHover(value);
                            break;
                        case "thumbnails":
                            self._reCreatePager();
                            break;
                        case "auto":
                            self[value ? "play" : "pause"]();
                            break;
                        default:
                            break;
                    }
                }
            };

            wijcarousel.prototype._reCreatePager = function () {
                var self = this, o = self.options, disabled = self._isDisabled();
                if (self.pager && self.pager.jquery) {
                    self.pager.remove();
                    self.pager = null;
                }
                if (o.showPager) {
                    self._createPager();

                    //only disabled option is true need to disabled the pager.
                    if (disabled) {
                        self._handlePagerState(disabled);
                    }
                }
            };

            wijcarousel.prototype._getItemBound = function () {
                var bound = {}, self = this, o = self.options;
                if (o.orientation === "horizontal") {
                    bound = {
                        w: Math.round(self.width / o.display),
                        h: self.height
                    };
                } else {
                    bound = {
                        w: self.width,
                        h: Math.round(self.height / o.display)
                    };
                }
                return bound;
            };

            wijcarousel.prototype._stopAnimation = function () {
                var self = this;
                if (self.isPlaying && self.progressBar) {
                    self.progressBar.stop().css({ width: "0%" });
                }
                self.list.stop(true, true);
            };

            wijcarousel.prototype._itemClick = function (event) {
                var el = $(event.target), self = this, o = self.options, cIdx = self.currentIdx, item = el.closest("li." + itemCss), itemIdx = item.data("itemIndex"), idx, forward;

                if (self._isDisabled()) {
                    event.preventDefault();
                    return;
                }

                if (item.length > 0) {
                    if (o.preview && itemIdx < cIdx || itemIdx > cIdx + o.display - 1) {
                        idx = self._getItemByIndex(cIdx).index();
                        forward = (item.index() > idx) ? "next" : "previous";
                        self[forward]();
                    }
                    self._trigger("itemClick", event, {
                        index: itemIdx,
                        el: item
                    });
                }
            };

            wijcarousel.prototype._wijdestroy = function () {
                var self = this, wijCSS = self.options.wijCSS;
                self.container.removeClass(["wijmo-wijcarousel", wijCSS.widget, "wijmo-wijcarousel-horizontal", "wijmo-wijcarousel-vertical"].join(" "));

                if (self.timeout) {
                    self.list.stop(true);
                    window.clearTimeout(self.timeout);
                    self.timeout = null;
                }

                if (self.options.showTimer && self.progressBar) {
                    self.progressBar.stop(true);
                }

                self.list.unwrap().removeClass("wijmo-wijcarousel-list").removeClass(wijCSS.helperClearFix).unbind("." + self.widgetName).removeAttr("style").children("li").each(function (idx, data) {
                    var item = $(data);
                    item.removeClass(["wijmo-wijcarousel-item", wijCSS.helperClearFix, currentCss].join(" "));
                    item.find("img").removeClass("wijmo-wijcarousel-image");
                    item.children(captionSel).remove();
                    item.css({ width: "", height: "" });
                    item.removeData("itemIndex");
                });

                self.itemWidth = self.itemHeight = undefined;

                self.element.find(ctrlSelector + ",.wijmo-wijcarousel-timerbar").remove();
                if (self.pager) {
                    self.pager.remove();
                    self.pager = null;
                }
                if (self.timer) {
                    self.timer.remove();
                    self.timer = null;
                }
                self.element.find("li>span").css("display", "");
            };

            /**
            * Removes the wijcarousel functionality completely. This returns the element to its pre-init state.
            */
            wijcarousel.prototype.destroy = function () {
                this._wijdestroy();
                $.Widget.prototype.destroy.apply(this);
            };

            wijcarousel.prototype._resetDom = function () {
                var self = this;

                //reset list item container
                self._applyListStyle();
                self.list.children("li").each(function (idx, data) {
                    var li = $(data), caption = li.children("div.wijmo-wijcarousel-caption"), text = li.children("div.wijmo-wijcarousel-text");
                    self._applyItemBound(li);
                    self._setStyle(caption.add(text), function () {
                        self._applyCaptionStyle(caption, text);
                    });
                });
                self._applyContainerStyle(self.isHorizontal, true);

                //reset preview
                if (self.options.preview) {
                    self._createPreview();
                }

                //reset controls(button, pager, controls)
                self._setStyle(self.prevBtn.add(self.nextBtn), function () {
                    self._applyBtnStyle(self.isHorizontal);
                });

                self._setStyle(self.pager, function () {
                    self.pager.position(self.options.pagerPosition);
                });

                self._setStyle(self.controls, function () {
                    self.controls.position(self.options.controlPosition);
                });
            };

            wijcarousel.prototype._setStyle = function (control, func) {
                var isShow = true;
                if (!control || control.length === 0) {
                    return;
                }

                if (control.css("display") == "none") {
                    isShow = false;
                    control.css("display", "");
                }
                func.call(this);
                if (!isShow) {
                    control.css("display", "none");
                }
            };

            /**
            * Refresh the carousel layout.Reset the layout, scrolled.
            */
            wijcarousel.prototype.refresh = function () {
                var self = this, o = self.options, el = self.element;

                //reset variable
                self.width = el.width() || 640;
                self.height = el.height() || 480;
                self.itemWidth = self.itemHeight = 0;
                this.currentIdx = o.start;

                self._resetDom();
                self._setCurrentPagerIndex();
                self.pause();
            };

            /**
            * Starts automatically displaying each of the images in order.
            */
            wijcarousel.prototype.play = function () {
                var self = this, o = self.options;
                if (self.isPlaying || self._isDisabled()) {
                    return;
                }
                if (o.interval === 0) {
                    return self.pause();
                }

                if (o.showTimer && self.progressBar) {
                    self.progressBar.css({ width: "0%" });
                    self.playPauseBtn.children("span:eq(0)").removeClass(o.wijCSS.iconPlay).addClass(o.wijCSS.iconPause);
                    self.progressBar.animate({
                        width: "100%"
                    }, o.interval, null, function () {
                        self._scroll("next", o.step);
                    });
                } else {
                    if (self.timeout) {
                        return;
                    }
                    self.timeout = window.setTimeout(function () {
                        self.next();
                    }, o.interval);
                }
                self.isPlaying = true;
            };

            /**
            * Stops automatically displaying the images in order.
            */
            wijcarousel.prototype.pause = function () {
                var self = this, o = self.options;
                if (o.showTimer && self.progressBar) {
                    self.progressBar.stop(true).css({ width: "0%" });

                    self.playPauseBtn.children("span:eq(0)").removeClass(o.wijCSS.iconPause).addClass(o.wijCSS.iconPlay);
                } else {
                    if (self.timeout === null) {
                        return;
                    }
                    window.clearTimeout(self.timeout);
                    self.timeout = null;
                }
                self.isPlaying = false;
            };

            /**
            * Shows the next picture.
            */
            wijcarousel.prototype.next = function () {
                var self = this, step = self.options.step;
                if (typeof step !== "number" || step < 1) {
                    return;
                }
                self._stopAnimation();
                self._scroll("next", step);
            };

            /**
            * Shows the previous picture.
            */
            wijcarousel.prototype.previous = function () {
                var self = this, step = self.options.step;
                if (typeof step !== "number" || step < 1) {
                    return;
                }
                self._stopAnimation();
                self._scroll("previous", step);
            };

            /**
            * Scrolls to the picture at the specified index.
            * @param {number} index The zero-based index of the picture to which to scroll.
            * @example $("#element").wijcarousel("scrollTo", 2);
            */
            wijcarousel.prototype.scrollTo = function (idx) {
                var self = this, forward, step;
                self._stopAnimation();
                forward = idx > self.currentIdx ? "next" : "previous";
                step = Math.abs(idx - self.currentIdx);
                if (idx !== self.currentIdx) {
                    self._scroll(forward, step);
                }
            };

            wijcarousel.prototype._scroll = function (forward, step) {
                var self = this, o = self.options, list = self.list, offset = 0, mask, i, isHorizontal = o.orientation === "horizontal", option = {}, size = self.itemBound[isHorizontal ? "w" : "h"], dir = isHorizontal ? "left" : "top", scrolled = step, css = {}, previewOffset = 0, currentLeft = self.currentIdx * size;

                if (!o.loop) {
                    if (forward === "next") {
                        if (self.currentIdx + o.display + step <= self.count) {
                            offset = -currentLeft - size * scrolled;
                        } else if (self.currentIdx + o.display < self.count) {
                            scrolled = self.count - self.currentIdx - o.display;
                            offset = -currentLeft - size * scrolled;
                        } else {
                            return;
                        }
                    } else {
                        if (self.currentIdx - step >= 0) {
                            offset = -currentLeft + size * scrolled;
                        } else if (self.currentIdx > 0) {
                            scrolled = self.currentIdx;
                            offset = 0;
                        }
                    }

                    if (offset !== undefined) {
                        //self.offset for preview mode.
                        option[dir] = offset + self.offset;

                        //if ($.browser.webkit) {
                        //	self.list.css(dir, -currentLeft);
                        //}
                        self._doAnimation(forward, option, scrolled);
                    }
                } else {
                    if (o.preview) {
                        offset = previewOffset = -size * previewNum + self.offset;
                    }
                    if (forward === "next") {
                        offset += -size * scrolled;
                        option[dir] = offset;
                    } else {
                        for (i = 0; i < step; i++) {
                            offset -= size;
                            list.children("li:last").prependTo(list);
                        }
                        css[dir] = offset;
                        option[dir] = previewOffset;
                        list.css(css);
                    }
                    self._doAnimation(forward, option, step, dir, size);
                }
                if (o.preview) {
                    mask = $();
                    for (i = 0; i < o.display; i++) {
                        mask = mask.add(self._getItemByIndex(self.currentIdx + i).find("div.wijmo-wijcarousel-mask:eq(0)"));
                    }
                    mask.stop(true).animate({ opacity: 0.6 }, o.animation.duration / 2, function () {
                        //mask.css({ opacity: "" });
                        self._getItemByIndex(self.currentIdx).removeClass(currentCss);
                    });
                }
            };

            wijcarousel.prototype._doAnimation = function (action, option, scrolled, dir, size) {
                var self = this, list = self.list, o = self.options, data, i, animation = { complete: null }, completeCallback, css = {}, to;

                if (!self.list.children().length) {
                    return;
                }

                if (action === "next") {
                    to = self.currentIdx + scrolled;
                } else {
                    to = self.currentIdx - scrolled;
                }
                if (!o.loop) {
                    completeCallback = function () {
                        self.currentIdx = to;
                        self._setCurrentState(self.currentIdx);
                    };
                } else {
                    to = to % self.count + (to < 0 ? self.count : 0);
                    completeCallback = function () {
                        //self.isAnimating = false;
                        var left = 0;
                        if (o.preview) {
                            left = self.offset - previewNum * size;
                        }
                        if (action === "next") {
                            for (i = 0; i < scrolled; i++) {
                                list.children("li:first").appendTo(list);
                            }
                            if (dir) {
                                css[dir] = left;
                                list.css(css);
                            }
                        }
                        self.currentIdx = to;
                        self._setCurrentState(self.currentIdx);
                    };
                }
                animation.complete = completeCallback;
                data = {
                    index: self.currentIdx,
                    to: to,
                    el: self._getItemByIndex(self.currentIdx)
                };
                if (!self._trigger("beforeScroll", null, data)) {
                    return;
                }

                if (o.animation && o.animation.complete) {
                    o.animation.complete = undefined;
                }

                $.extend(animation, o.animation);
                self._hideCaption();
                list.animate(option, animation);
            };

            wijcarousel.prototype._setCurrentState = function (idx) {
                var self = this, o = self.options, li, data, shouldPlay, lastIdx = idx + o.display - 1, currentItem, mask, i;
                if (!o.loop) {
                    shouldPlay = (idx + o.display) < self.count;
                    if (self.isPlaying && shouldPlay) {
                        window.clearTimeout(self.timeout);
                        self.timeout = null;
                        self.isPlaying = false;
                        self.play();
                    } else if (self.progressBar) {
                        self.pause();
                    }
                    self._applyBtnClass();
                } else if (self.isPlaying) {
                    window.clearTimeout(self.timeout);
                    self.timeout = null;
                    self.isPlaying = false;
                    self.play();
                }
                if (o.preview) {
                    mask = $();
                    currentItem = self._getItemByIndex(idx);
                    for (i = 0; i < o.display; i++) {
                        mask = mask.add(self._getItemByIndex(idx + i).find("div.wijmo-wijcarousel-mask:eq(0)"));
                    }
                    mask.animate({ opacity: 0 }, o.animation.duration / 2, function () {
                        currentItem.addClass(currentCss);
                        self._showCaption(idx, lastIdx);
                    });
                } else {
                    self._showCaption(idx, lastIdx);
                }

                self._setCurrentPagerIndex();

                data = {
                    firstIndex: idx,
                    lastIndex: lastIdx
                };
                self._trigger("afterScroll", null, data);
            };

            wijcarousel.prototype._setCurrentPagerIndex = function () {
                var self = this, idx = self.currentIdx, li;
                if (self.pager) {
                    if ($.wijmo.wijslider && self.pager.find(":wijmo-wijslider").length) {
                        self.pager.find(":wijmo-wijslider:eq(0)").wijslider("value", idx);
                    } else if ($.wijmo.wijpager && self.pager.is(":wijmo-wijpager")) {
                        self.pager.wijpager("option", "pageIndex", idx);
                    } else if (self.pager.jquery) {
                        li = self.pager.find(">ul:eq(0)>li").eq(idx);
                        if (li.length) {
                            self._activePagerItem(li);
                        }
                    }
                }
            };

            wijcarousel.prototype._getItemByIndex = function (idx) {
                var self = this, list = self.list, item, index = idx % self.count;

                if (!self.options.loop) {
                    return list.children("li").eq(index);
                }
                list.children("li").each(function (i) {
                    var li = $(this);
                    if (li.data("itemIndex") === index) {
                        item = li;
                        return false;
                    }
                });
                return item;
            };

            wijcarousel.prototype._collectionChanged = function (action) {
                var self = this;

                self.count = self.count + (action === "add" ? 1 : -1);
                self._applyListStyle();
                if (self.pager && self.pager.jquery) {
                    self.pager.remove();
                    self.pager = null;
                    self._createPager();
                }
                self._applyBtnClass();
            };

            /**
            * Add a custom item with specified index.
            * @param {string|jQuery} ui The node content or innerHTML.
            * @param {number} index Specified the postion to insert at.
            */
            wijcarousel.prototype.add = function (ui, index) {
                var self = this, item, li;
                if (typeof ui === "string") {
                    item = $(ui);
                } else if (ui.jquery) {
                    item = ui;
                } else if ($.isPlainObject(ui)) {
                    item = self._generateMarkup(ui);
                } else {
                    return;
                }

                if (!item.is("li")) {
                    item = item.wrap("<li></li>").parent();
                }
                li = item;
                if (typeof index === "number" && index >= 0 && index < self.count) {
                    li.insertBefore(self._getItemByIndex(index));
                    self.list.children("li").each(function (i, data) {
                        var item = $(data);
                        if (item.data("itemIndex") >= index) {
                            item.data("itemIndex", item.data("itemIndex") + 1);
                        }
                    });
                } else {
                    if (index == 0) {
                        li.appendTo(self.list);
                    }
                    li.insertAfter(self._getItemByIndex(self.count - 1));
                }
                self._createItem(item, index !== undefined ? index : self.count);

                self._collectionChanged("add");
            };

            /**
            * Remove the item at specified index.
            * @param {number} index Specified which item should be removed.
            */
            wijcarousel.prototype.remove = function (index) {
                var self = this, item;

                if (typeof index === "number" && index >= 0 && index < self.count) {
                    item = self._getItemByIndex(index);
                    self.list.children("li").each(function (i, data) {
                        var li = $(data);
                        if (li.data("itemIndex") > index) {
                            li.data("itemIndex", li.data("itemIndex") - 1);
                        }
                    });
                } else {
                    item = self._getItemByIndex(self.count - 1);
                }
                if (item) {
                    item.remove();
                }
                self._collectionChanged("remove");
            };
            return wijcarousel;
        })(wijmo.wijmoWidget);
        carousel.wijcarousel = wijcarousel;

        var wijcarousel_options = (function () {
            function wijcarousel_options() {
                /**
                * Mobile CSS.
                * @ignore
                */
                this.wijMobileCSS = {
                    header: "ui-header ui-bar-a",
                    content: "ui-body-a",
                    stateDefault: "ui-btn ui-btn-a",
                    stateHover: "ui-btn-down-a",
                    stateActive: "ui-btn-down-b",
                    iconPlay: "ui-icon-arrow-r",
                    iconPause: "ui-icon-grid"
                };
                /** Selector option for auto self initialization.
                * This option is internal.
                * @ignore
                */
                this.initSelector = ":jqmData(role='wijcarousel')";
                /** An object collection that contains the data of the carousel.
                * @example:
                * $("#element").wijcarousel( { data: [{
                *     imageUrl: "../thumb/image1.jpg",
                *     linkUrl: "../images/image1.jpg",
                *     content: "",
                *     caption: "<span>Word Caption 1</span>"
                * },{
                *     imageUrl: "../thumb/image2.jpg",
                *     linkUrl: "../images/image2.jpg",
                *     content: "",
                *     caption: "<span>Word Caption 2</span>"
                * }] } );
                */
                this.data = [];
                /** Allows pictures to be played automatically.
                * @example $("#element").wijcarousel( { auto: true } );
                */
                this.auto = false;
                /** Determines the time span between two pictures showing in autoplay mode.
                * @example $("#element").wijcarousel( { interval: 3000 } );
                */
                this.interval = 5000;
                /** Determines if the timer of the carousel should be shown.
                * If true, the timer appears by default at the top of the carousel with a play/pause button allowing carousel items to be automatically cycled through at run time.
                * @example $("#element").wijcarousel( { showTimer: true } );
                */
                this.showTimer = false;
                /** Determines the position value for next button and previous button.
                * Possible values are: "inside" and "outside".
                * @example $("#element").wijcarousel( { buttonPosition: "outside" } );
                */
                this.buttonPosition = "inside";
                /** Determines whether to show the pager element.
                * By default, if showPager is set to true, the pager will appear at the bottom right of the widget and allows run time carousel item navigation.
                * You can customize the location and appearance of the pager by using the pagerPosition and pagerType options.
                * @example $("#element").wijcarousel( { showPager: true } );
                */
                this.showPager = false;
                /** Determines the class of custom previous button.
                * Includes the following sub-options "defaultClass", "hoverClass", "disableClass".
                * @example $("#element").wijcarousel( { prevBtnClass: {
                * }});
                */
                this.prevBtnClass = {
                    defaultClass: "",
                    hoverClass: "",
                    disableClass: ""
                };
                /** Determines the class of custom previous button.
                * Includes the following sub-options "defaultClass", "hoverClass", "disableClass".
                * @example $("#element").wijcarousel( { nextBtnClass: {
                * }});
                */
                this.nextBtnClass = {
                    defaultClass: "",
                    hoverClass: "",
                    disableClass: ""
                };
                /** Determines the type of the pager in the carousel.
                * Possible values are: "slider", "numbers", "dots", "thumbnails".
                * For a live example, see the Carousel Paging page in the Explore sample.
                * @example $("#element").wijcarousel( { pagerType: "numbers" } );
                */
                this.pagerType = "numbers";
                /** Determines the thumbnails list for a pager when pagerType is "thumbnails".
                * @type {object}
                * @example $("#element").wijcarousel( { thumbnails: [] } );
                */
                this.thumbnails = {
                    mouseover: null,
                    mouseout: null,
                    mousedown: null,
                    mouseup: null,
                    click: null,
                    imageWidth: 58,
                    imageHeight: 74,
                    images: []
                };
                /** A value that indicates the position settings for the pager.
                * @type {object}
                * @example $("#element").wijcarousel( {
                *     pagerPosition: {
                *         my: 'left bottom',
                *         at: 'right top',
                *         offset: '0 0'}
                * });
                */
                this.pagerPosition = {};
                /** Determines the orientation of the pager.
                * Possible values are: "vertical" & "horizontal"
                * @example $("#element").wijcarousel( { orientation: "vertical" } );
                */
                this.orientation = "horizontal";
                /** Determines the orientation of the slider.
                * Possible values are: "vertical" & "horizontal"
                * @example $("#element").wijcarousel( { sliderOrientation: "vertical" } );
                */
                this.sliderOrientation = "horizontal";
                /** Allows the carousel to loop back to the beginning.
                * @example $("#element").wijcarousel( { loop: true } );
                */
                this.loop = true;
                /** The animation option determines whether and how images are scroll in the carousel.
                * It defines the animation effect and controls other aspects of the widget's animation, such as duration and easing.
                * Set the disable attribute to true in order to disable the animation effect.
                * For a live example, see the Carousel Animation page in the Explore sample.
                * @type {object}
                * @example $("#element").wijcarousel( {
                *     animation {
                *         queue: true,
                *         disable: false,
                *         duration: true,
                *         easing: "easeOutCubic"
                *     }
                * } );
                */
                this.animation = {
                    /** This value determines whether to queue animation operations.
                    * @type {boolean}
                    */
                    queue: true,
                    /** A value that determines whether to show animation. Set this option to true in order to disable easing.
                    * @type {boolean}
                    */
                    disable: false,
                    /** The duration option defines the length of the scrolling animation effect in milliseconds.
                    * @type {number}
                    */
                    duration: 1000,
                    /** Sets the type of animation easing effect that users experience when the wijcarousel is scrolled to another image. For example, the wijcarousel can bounce several times as it loads.
                    * @type {string}
                    * Valid Values:
                    * easeInCubic - Cubic easing in.Begins at zero velocity and then accelerates.
                    * easeOutCubic - Cubic easing in and out.Begins at full velocity and then decelerates to zero.
                    * easeInOutCubic - Begins at zero velocity, accelerates until halfway, and then decelerates to zero velocity again.
                    * easeInBack - Begins slowly and then accelerates.
                    * easeOutBack - Begins quickly and then decelerates.
                    * easeOutElastic - Begins at full velocity and then decelerates to zero.
                    * easeOutBounce - Begins quickly and then decelerates.The number of bounces is related to the duration, longer durations produce more bounces.
                    * Default: "linear".
                    * Type: string.
                    */
                    easing: "linear"
                };
                /** Determines the custom start position of the image list in wijcarousel.
                * @example $("#element").wijcarousel( { start: 2 } );
                */
                this.start = 0;
                /** Determines how many images should be shown in the view area.
                * @example $("#element").wijcarousel( { display: 2 } );
                */
                this.display = 1;
                /** Determines if we should preview the last and next images.
                * loop == false , orintation == "horizontal",display == 1.
                * @example $("#element").wijcarousel( { preview: false } );
                */
                this.preview = false;
                /** Determines how many images will be scrolled
                * when you click the Next/Previous button.
                * @example $("#element").wijcarousel( { step: 2 } );
                */
                this.step = 1;
                /** Determines whether the custom control should be shown.
                * @example $("#element").wijcarousel( { showControls: true } );
                */
                this.showControls = false;
                /** Determines the innerHtml of the custom control.
                * @example $("#element").wijcarousel( { control: "<div>Blah</div>" } );
                */
                this.control = "";
                /** A value that indicates the position settings for the custom control.
                * @type {object}
                * @example $("#element").wijcarousel( {
                *     controlPosition: {
                *         my: 'left bottom',
                *         at: 'right top  ',
                *         offset: '0 0'
                *     }
                * });
                */
                this.controlPosition = {};
                /** Determines whether the caption of items should be shown.
                * @example $("#element").wijcarousel( { showCaption: true } );
                */
                this.showCaption = true;
                /** Determines whether the controls should be shown after created
                * or when hovering on the dom element.
                * @example $("#element").wijcarousel( { showControlsOnHover: true } );
                */
                this.showControlsOnHover = false;
                /** This is the itemClick event handler.
                * It is a function called when the image is clicked.
                * @event
                * @dataKey {number} index This is the index of the clicked image.
                * @dataKey {DOMElement} el This is the dom element of this item.
                */
                this.itemClick = null;
                /** This is the beforeScroll event handler.
                * It is a function called before scrolling to another image.
                * @event
                * @dataKey {number} index This is the index of the clicked image.
                * @dataKey {DOMElement} to The index of the image that will scrolled to.
                */
                this.beforeScroll = null;
                /** This is the afterScroll event handler.
                * It is a function called after scrolling to another image.
                * @event
                * @dataKey {number} index The index of the last image.
                * @dataKey {DOMElement} to The index of the current image.
                */
                this.afterScroll = null;
                /** This is the loadCallback event handler.
                * It is a function called after creating the dom element.
                * @event
                * @param {jQuery.Event} e jQuery Event object
                * @param {object} data The node widget that relates to this event.
                */
                this.loadCallback = null;
            }
            return wijcarousel_options;
        })();

        wijcarousel.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijcarousel_options());

        $.wijmo.registerWidget("wijcarousel", wijcarousel.prototype);
    })(wijmo.carousel || (wijmo.carousel = {}));
    var carousel = wijmo.carousel;
})(wijmo || (wijmo = {}));
;
/// <reference path="../Base/jquery.wijmo.widget.ts" />
/// <reference path="../wijslider/jquery.wijmo.wijslider.ts" />
/// <reference path="../wijpager/jquery.wijmo.wijpager.ts" />
/// <reference path="../wijcarousel/jquery.wijmo.wijcarousel.ts" />
/// <reference path="../External/declarations/swfobject.d.ts" />
/*globals jQuery, window, XMLHttpRequest*/
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};

var wijmo;
(function (wijmo) {
    (function (gallery) {
        var $ = jQuery, widgetName = "wijgallery", baseCss = "wijmo-wijgallery", cssPrefix = "wijmo-wijgallery-", selectedCss = cssPrefix + "selected", btnCssPrefix = cssPrefix + "button-", btnCss = cssPrefix + "button", pointerCss = "wijmo-wijgallery-thumbs-pointer-{0}", flashCss = "wijmo-wijgallery-flashwrapper", frameHtml = "<div class=\"wijmo-wijgallery-frame\">" + "<div class=\"wijmo-wijgallery-content\"></div></div>", thumbsHtml = "<div class=\"wijmo-wijgallery-thumbs\"></div>", btnHtml = "<a><span></span></a>", navHtml = "<div class=\"wijmo-wijgallery-frame-{0}\">" + "<a href=\"#\" class=\"wijmo-wijgallery-frame-link\"></a></div>", captionHtml = "<div></div>", carouselItem = "li.wijmo-wijcarousel-item";

        if (!window["S"] && window["swfobject"]) {
            window["S"] = {
                flash: window["swfobject"]
            };
        }

        /** @widget */
        var wijgallery = (function (_super) {
            __extends(wijgallery, _super);
            function wijgallery() {
                _super.apply(this, arguments);
            }
            wijgallery.prototype._setOption = function (key, value) {
                var self = this, o = self.options, el, create, old, text;
                if (key === "framePosition" || key === "thumbnailPosition" || key === "transitions" || key === "pagingPosition") {
                    $.extend(true, o[key], value);
                } else {
                    old = o[key];
                    _super.prototype._setOption.call(this, key, value);
                    switch (key) {
                        case "showThumbnailCaptions":
                            self.thumbs[self.thumbWidgetName]({
                                showCaption: value
                            });
                            break;
                        case "thumbnailOrientation":
                            self.thumbs[self.thumbWidgetName]({
                                orientation: value
                            });
                            self._wijdestroy();
                            self._create();
                            break;
                        case "thumbsDisplay":
                            self.thumbs[self.thumbWidgetName]({
                                display: value
                            });
                            break;
                        case "autoPlay":
                            self[value ? "play" : "pause"]();
                            break;
                        case "showCounter":
                        case "showTimer":
                        case "showControls":
                            el = key.replace(/show/i, "").toLowerCase();
                            create = key.replace(/show/i, "_create");
                            if (value !== old) {
                                if (value === true) {
                                    if (!self[el]) {
                                        self[create]();
                                    } else if (self[el].jquery) {
                                        self[el].show();
                                    }
                                } else {
                                    self[el].hide();
                                }
                            }
                            break;
                        case "showCaption":
                            if (value) {
                                self._createCaption(self.size);
                                text = self._loadCaption(self.images[self.currentIdx]);
                                text.show();
                            } else {
                                self.element.find(".wijmo-wijgallery-caption,.wijmo-wijgallery-text").remove();
                            }
                            break;
                        case "showPager":
                        case "thumbsLength":
                        case "thumbnailDirection":
                        case "showControlsOnHover":
                        case "mode":
                        case "data":
                            self._wijdestroy();
                            self._create();
                            break;
                        default:
                            break;
                    }
                }
            };

            wijgallery.prototype._innerDisable = function () {
                _super.prototype._innerDisable.call(this);
                if (this.isPlaying) {
                    this.pause();
                }
                this._handleDisabledOption(true, this.element);
            };

            wijgallery.prototype._innerEnable = function () {
                _super.prototype._innerEnable.call(this);
                this._handleDisabledOption(false, this.element);
            };

            wijgallery.prototype._handleDisabledOption = function (disabled, ele) {
                var self = this;

                if (self.pager && !self.pager.is(":hidden")) {
                    self.pager.wijpager("option", "disabled", disabled);
                } else if (self.thumbs && !self.thumbs.is(":hidden")) {
                    self.thumbs[self.thumbWidgetName]({
                        disabled: disabled
                    });
                }
            };

            wijgallery.prototype._initLi = function (li) {
                var a = li.children("a:eq(0)"), img = li.find("img:eq(0)"), caption = li.find("span:eq(0)"), imgData = {
                    url: null,
                    thumbUrl: null,
                    title: img.attr("alt"),
                    caption: undefined
                };

                if (a.length && a.attr("href")) {
                    imgData.url = a.attr("href");
                    if (!imgData.title) {
                        imgData.title = a.attr("title");
                    }
                } else if (img.length) {
                    imgData.url = img.attr("src");
                }

                if (caption.length) {
                    imgData.caption = caption;
                } else if (img.attr("title")) {
                    imgData.caption = $("<span>").html(img.attr("title"));
                }
                imgData.thumbUrl = img.attr("src");
                return imgData;
            };

            wijgallery.prototype._initStatus = function () {
                var self = this, lis;
                self.images = [];
                self.ul = self.element.children("ul");
                lis = self.ul.children("li");
                self._count = lis.length;
                lis.each(function (i) {
                    var imgData = self._initLi($(this));
                    self.images.push(imgData);
                });
            };

            wijgallery.prototype._createMarkupFromData = function () {
                var self = this, o = self.options, items = o.data, el = self.element, ul = el.children("ul:eq(0)");
                self.images = items;

                if (ul.length) {
                    ul.empty();
                } else {
                    ul = $("<ul>").appendTo(el);
                }
                self.ul = ul;
                $.each(items, function (idx, item) {
                    var link = $("<a>"), li = $("<li>"), img = $("<img>");
                    if (item.url) {
                        link.attr("href", item.url);
                    }
                    if (item.thumbUrl) {
                        img.attr("src", item.thumbUrl);
                    }
                    if (item.title) {
                        img.attr("alt");
                    }
                    link.append(img).appendTo(li);
                    li.appendTo(ul);
                });
                self._count = items.length;
            };

            wijgallery.prototype._create = function () {
                var self = this, o = self.options;
                self.container = self.element;
                self.container.addClass([baseCss, o.wijCSS.widget].join(' '));
                self.currentThumbIdx = 0;
                self.currentIdx = -1;

                //number of setTimeOut(ensure only 1 timer at same time)
                self.timerCount = 0;

                // enable touch support:
                if (window.wijmoApplyWijTouchUtilEvents) {
                    $ = window.wijmoApplyWijTouchUtilEvents($);
                }

                if (o.showPager) {
                    o.pagingPosition = true;
                    o.thumbnails = false;
                } else {
                    o.thumbnails = true;
                }
                if (o.data && o.data.length) {
                    self._createMarkupFromData();
                } else {
                    self._initStatus();
                }
                if (o.loadCallback && $.isFunction(o.loadCallback)) {
                    self._trigger("loadCallback", null, self);
                }

                self._createDom();
                if (o.autoPlay) {
                    self._play(true);
                }

                if (o.showControlsOnHover) {
                    self.frame.find(".wijmo-wijpager," + ".wijmo-wijgallery-button-next,.wijmo-wijgallery-counter," + ".wijmo-wijgallery-button-previous").hide();

                    if (!self.isPlaying && self.timer) {
                        self.timer.hide();
                    }
                }

                //update for visibility change
                if (self.element.is(":hidden") && self.element.wijAddVisibilityObserver) {
                    self.element.wijAddVisibilityObserver(function () {
                        //self.refresh();
                        if (self.element.wijRemoveVisibilityObserver) {
                            self.element.wijRemoveVisibilityObserver();
                        }
                    }, "wijgallery");
                }

                _super.prototype._create.call(this);
            };

            wijgallery.prototype._createDom = function () {
                var self = this, o = self.options;

                if (o.thumbnails) {
                    self._createThumbnails();
                } else {
                    self.ul.hide();
                }

                self._createFrame();

                if (o.control) {
                    self._createControls();
                }

                if (o.showCounter) {
                    self._createCounter();
                }

                if (o.showTimer) {
                    self._createTimer();
                }

                if (o.showPager) {
                    self._createPager();
                }
            };

            wijgallery.prototype._getFrameSize = function () {
                var self = this, or = self.options.thumbnailOrientation === "horizontal", height = self.element.height() - (or ? (self.thumbs ? self.thumbs.outerHeight(true) : 0) : 0), width = self.element.width() - (or ? 0 : (self.thumbs ? self.thumbs.outerWidth(true) : 0));
                return {
                    w: (width < 2 || !width) ? 750 : width,
                    h: (height < 2 || !height) ? 300 : height
                };
            };

            wijgallery.prototype._createFrame = function () {
                var self = this, o = self.options, w, h, size = self._getFrameSize(), d = o.thumbnailDirection === "after";

                self.frame = $(frameHtml).addClass(o.wijCSS.content + " " + o.wijCSS.helperClearFix)[d ? "prependTo" : "appendTo"](self.container).setOutWidth(size.w - 1).setOutHeight(size.h).wrap("<div class=\"wijmo-wijgallery-framewrapper\">");
                self.size = size;
                w = self.frame.width();
                h = self.frame.height();
                self.frameWrapper = self.frame.parent();

                if (o.thumbnailOrientation === "vertical") {
                    self.frameWrapper.addClass("wijmo-wijgallery-framewrapper-vertical");
                }

                if (o.showControlsOnHover) {
                    self.frame.bind("mouseenter." + self.widgetName, function () {
                        if (self._isDisabled()) {
                            return;
                        }
                        self._showControls("controls");
                    }).bind("mouseleave." + self.widgetName, function () {
                        if (self._isDisabled()) {
                            return;
                        }
                        self._hideControls("controls");
                    });
                }
                self.content = self.frame.children("div.wijmo-wijgallery-content");

                if (o.mode === "img") {
                    self._createFrameMask();
                }
                self._createPrevNextBtn();
                self._createCaption(size);
                self._createLoading();

                self.last = $("<div class=\"" + o.wijCSS.overlay + " wijmo-wijgallery-last\"></div>").appendTo(self.content).width(w).height(h).css({ "line-height": size.h + "px" });

                self.current = $("<div class=\"" + o.wijCSS.overlay + " wijmo-wijgallery-current\"></div>").appendTo(self.content).width(w).height(h).css({ "line-height": size.h + "px" });

                self._show(0);
            };

            wijgallery.prototype._createControls = function () {
                var self = this, o = self.options, position = {
                    collision: "none",
                    of: self.container,
                    my: "center bottom",
                    at: "center bottom"
                };
                if (o.control) {
                    self.controls = $(o.control).css({ position: "absolute" }).appendTo(self.container);
                    $.extend(position, o.controlPosition);
                    self.controls.position(position);
                }
            };

            wijgallery.prototype._createLoading = function () {
                var self = this;
                self.loading = $("<div></div>").addClass("wijmo-wijgallery-loading").appendTo(self.content);

                self.loading.css({
                    left: (self.content.width() - self.loading.width()) / 2,
                    top: (self.content.height() - self.loading.height()) / 2
                });

                self.loading.hide();
            };

            wijgallery.prototype._createFrameMask = function () {
                var self = this, o = self.options;

                $.each(["previous", "next"], function (i, n) {
                    var nav = $(navHtml.replace(/\{0\}/, n)).appendTo(self.frame), link = nav.children("a");

                    if ($.browser.msie && parseInt($.browser.version) <= 9) {
                        nav.css({
                            "background-color": "#fff"
                        });
                    }

                    if (o.showControlsOnHover) {
                        nav.bind("mouseenter." + self.widgetName, function () {
                            if (self._isDisabled()) {
                                return;
                            }
                            self._showControls(n);
                        }).bind("mouseleave." + self.widgetName, function () {
                            if (self._isDisabled()) {
                                return;
                            }
                            self._hideControls(n);
                        });
                    }

                    link.bind("click." + self.widgetName, function (event) {
                        if (self._isDisabled()) {
                            return;
                        }
                        self[n]();
                        event.preventDefault();
                    });
                });
            };

            wijgallery.prototype._createCounter = function () {
                var self = this, o = self.options;

                if (!o.showCounter) {
                    if (self.counter) {
                        self.counter.remove();
                        self.counter = undefined;
                    }
                    return;
                }

                if (!self.counter) {
                    self.counter = $("<div></div>").addClass("wijmo-wijgallery-counter " + o.wijCSS.stateDefault + " " + o.wijCSS.cornerTL).appendTo(self.frame);
                }
                self._refreshCounter();
            };

            wijgallery.prototype._refreshCounter = function () {
                var self = this, o = self.options, counter;
                if (!self.counter) {
                    return;
                }
                self.counter.empty();

                if (o.counter) {
                    counter = o.counter.replace(/\[i\]/, self.currentIdx + 1);
                    counter = counter.replace(/\[n\]/, self._count);

                    $("<span></span>").text(counter).appendTo(self.counter);
                }
            };

            wijgallery.prototype._createPrevNextBtn = function () {
                var self = this, wijCSS = self.options.wijCSS;

                $.each(["next", "previous"], function (i, n) {
                    var css = n === "next" ? wijCSS.iconArrowRight : wijCSS.iconArrowLeft, panel;
                    panel = self.frame.find(".wijmo-wijgallery-frame-" + n);
                    if (!panel.length || self.options.mode !== "img") {
                        panel = self.frame;
                    }
                    self[n + "Btn"] = $(self._createBtn(btnCssPrefix + n, css)).bind("click." + self.widgetName, $.proxy(self[n], self)).appendTo(panel);
                    self._applyBtnStyle(n);
                });
            };

            wijgallery.prototype._applyBtnStyle = function (dir) {
                var self = this, o = self.options, isNext = dir === "next", btn = self[dir + "Btn"], at = isNext ? "right center" : "left center", my = at, wijCSS = o.wijCSS, css = isNext ? wijCSS.cornerLeft : wijCSS.cornerRight, condition = dir === "next" ? (self.currentIdx >= self._count) : (self.currentIdx <= 0), nextPosition = {
                    collision: "none",
                    of: self.frame,
                    my: my,
                    at: at
                };
                btn.addClass(css).position(nextPosition);

                if (condition) {
                    btn.removeClass(wijCSS.stateHover).addClass(wijCSS.stateDisabled);
                } else if (btn.hasAllClasses(wijCSS.stateDisabled)) {
                    btn.removeClass(wijCSS.stateDisabled);
                }
            };

            wijgallery.prototype._createCaption = function (size) {
                var self = this, o = self.options, css = o.wijCSS;
                if (o.showCaption) {
                    self.overlay = $(captionHtml).addClass([css.content, css.helperClearFix, "wijmo-wijgallery-caption"].join(' ')).width(size.w).appendTo(self.content);

                    self.caption = $(captionHtml).addClass([css.content, css.helperClearFix, "wijmo-wijgallery-text"].join(' ')).width(size.w).appendTo(self.content);
                }
            };

            wijgallery.prototype._loadCaption = function (image) {
                var self = this, content = image.caption, height, caption = $("<span></span>"), text = self.element.find(".wijmo-wijgallery-text," + ".wijmo-wijgallery-caption");

                if (content) {
                    text.show();
                    if (content.jquery) {
                        content.show();
                    }
                    caption.html(content);
                    self.caption.empty().append(caption);
                    height = caption.outerHeight(true);
                    text.height(height);

                    //ie get wrong height at first time. the 2nd is right.
                    if ($.browser.msie) {
                        text.height(caption.css("display", "block").outerHeight(true));
                    }
                }
                text.hide();
                return text;
            };

            wijgallery.prototype._showCaption = function (img) {
                var self = this;

                if (img && img.caption) {
                    if (self.caption.length) {
                        self.caption.fadeIn(500);
                    }
                    if (self.overlay.length) {
                        self.overlay.show().animate({ opacity: 0.5 }, 500);
                    }
                }
            };

            wijgallery.prototype._createTooltip = function (dir) {
                var self = this, wijCSS = self.options.wijCSS, d = dir || "bottom";
                self.pointer = $("<div>").addClass([wijCSS.content, wijCSS.stateDefault, pointerCss.replace(/\{0\}/, d)].join(' '));
                self.pointer.appendTo(self.thumbsWrapper).hide();
            };

            wijgallery.prototype._createThumbnails = function () {
                var self = this, o = self.options, d = o.thumbnailDirection === "after", thumbClass = "wijmo-wijgallery-thumbs-{0}", or = o.thumbnailOrientation === "horizontal", postFix = d ? (or ? "bottom" : "right") : (or ? "top" : "left");

                self.thumbPosition = postFix;
                self.thumbs = $(thumbsHtml).appendTo(self.container).addClass(o.wijCSS.content).addClass(or ? "wijmo-wijcarousel-horizontal-multi" : "wijmo-wijcarousel-vertical-multi");

                if (or) {
                    self.thumbs.css({ height: o.thumbsLength + "px" }).setOutWidth(self.element.width());
                } else {
                    self.thumbs.css({ width: o.thumbsLength + "px" }).setOutHeight(self.element.height());
                }

                self.ul.appendTo(self.thumbs);

                self.ul.children("li").each(function (i, data) {
                    var link = $(data).children("a"), imgData = self.images[i], href = imgData.thumbUrl;
                    if (!link.length) {
                        link = $(data).wrapInner("<a>").children("a");
                        link.attr("href", href);
                    }
                });

                if ($[self.namespace][self.thumbWidgetName]) {
                    self.thumbs.addClass(thumbClass.replace(/\{0\}/, postFix)).find("li").addClass(o.wijCSS.stateDefault).hover(function () {
                        $(this).addClass(o.wijCSS.stateHover);
                    }, function () {
                        $(this).removeClass(o.wijCSS.stateHover);
                    });

                    self.thumbsWrapper = self.thumbs[self.thumbWidgetName]({
                        display: o.thumbsDisplay,
                        step: o.thumbsDisplay - 1,
                        itemPadding: "0 10px",
                        showCaption: o.showThumbnailCaptions,
                        orientation: o.thumbnailOrientation,
                        loop: false,
                        itemClick: function (event, ui) {
                            var idx = ui.index;
                            self.show(idx);
                            event.preventDefault();
                        },
                        afterScroll: function (event, ui) {
                            self.currentThumbIdx = ui.firstIndex;
                            if (self.activeLi && self.activeLi.is("li") && self.activeLi.index() >= ui.firstIndex && self.activeLi.index() <= ui.lastIndex) {
                                self._highlightThumb(self.activeLi);
                            }
                            self.isScrolling = false;
                        },
                        beforeScroll: function (event, ui) {
                            self.isScrolling = true;
                            if (o.mode === "swf" || o.mode === "flv") {
                                self.pointer.hide();
                            } else {
                                self.pointer.fadeOut(100);
                            }
                        }
                    }).wrap("<div class=\"wijmo-wijgallery-thumbswrapper\">").parent();

                    if (!or) {
                        self.thumbsWrapper.addClass("wijmo-wijgallery-thumbswrapper-vertical");
                    }
                    self._createTooltip(postFix);
                }
            };

            wijgallery.prototype._calculatePosition = function (offset, w, h, lw, lh, b) {
                var self = this;
                if (self.thumbPosition === "bottom") {
                    offset.left = offset.left + (lw - w) / 2 + b;
                    offset.top = offset.top - h;
                } else if (self.thumbPosition === "top") {
                    offset.left = offset.left + (lw - w) / 2 + b;
                    offset.top = offset.top + lh + 2 * b;
                } else if (self.thumbPosition === "left") {
                    offset.left = offset.left + lw + 2 * b;
                    offset.top = offset.top + (lh - h) / 2 + b;
                } else if (self.thumbPosition === "right") {
                    offset.left = offset.left - w;
                    offset.top = offset.top + (lh - h) / 2 + b;
                }
            };

            wijgallery.prototype._highlightThumb = function (li) {
                var self = this, w, h, lw, lh, offset, b, css = [selectedCss, self.options.wijCSS.stateActive].join(' ');
                if (li && li.length) {
                    li.siblings("li." + selectedCss).removeClass(css);
                    li.addClass(css);

                    w = self.pointer.outerWidth(true);
                    h = self.pointer.outerHeight(true);
                    lw = li.width();
                    lh = li.height();
                    offset = li.offset();

                    //b = li.outerWidth(true)- li.outerWidth();
                    // get border of li.
                    b = 5;
                    self._calculatePosition(offset, w, h, lw, lh, b);

                    self.pointer.fadeIn(100);
                    self.pointer.offset(offset);
                }
            };

            wijgallery.prototype._getSelector = function (content, includeTimer) {
                var selector, btnPrefix = ".wijmo-wijgallery-button-", controls = ".wijmo-wijpager,.wijmo-wijgallery-counter";

                if (includeTimer) {
                    controls += ",.wijmo-wijgallery-timerbar";
                }

                if (content === "next" || content === "previous") {
                    selector = btnPrefix + content;
                } else if (content === "controls") {
                    selector = controls;
                } else {
                    selector = controls + "," + btnPrefix + "next," + btnPrefix + "previous";
                }
                return selector;
            };

            wijgallery.prototype._showControls = function (content) {
                var self = this, selector;
                selector = self._getSelector(content, !!self.timer);
                self.frame.find(selector).stop(true, true).fadeIn(400, function () {
                    $(this).css('opacity', '');
                });
            };

            wijgallery.prototype._hideControls = function (content) {
                var self = this, selector;
                selector = self._getSelector(content, !!self.timer);
                this.frame.find(selector).stop(true, true).fadeOut(600);
            };

            wijgallery.prototype._createPager = function () {
                var self = this, o = self.options, pager, display = o.thumbsDisplay, pageCount = 1, pageIndex = self.currentIdx, currentIdx = self.currentIdx, position = {
                    collision: "none",
                    of: self.container,
                    my: "right top",
                    at: "right bottom"
                };
                if (o.thumbnails) {
                    pager = $("<div></div>").appendTo(self.thumbs);

                    if (display !== 0) {
                        pageCount = Math.ceil(self._count / display);
                        pageIndex = Math.ceil(self.currentIdx / display);
                    }

                    self.pager = pager.wijpager({
                        pageCount: pageCount,
                        pageIndex: pageIndex,
                        pageButtonCount: pageCount,
                        mode: "numeric",
                        pageIndexChanged: function (event, ui) {
                            var idx = ui.newPageIndex;
                            if (currentIdx < idx * display || currentIdx >= (idx + 1) * display) {
                                self.thumbs[self.thumbWidgetName]("scrollTo", (idx * display));
                            }
                            event.preventDefault();
                        }
                    }).css({
                        position: "absolute"
                    });
                } else {
                    pager = $("<div></div>").appendTo(self.container);
                    self.pager = pager.wijpager({
                        pageCount: self._count,
                        pageIndex: self.currentIdx,
                        pageButtonCount: self._count,
                        mode: "numeric",
                        pageIndexChanged: function (event, ui) {
                            var idx = ui.newPageIndex;
                            self._show(idx);
                        }
                    }).css({
                        position: "absolute"
                    });

                    $.extend(position, o.pagingPosition);
                    self.pager.addClass("wijmo-wijgallery-pager").position(position);
                    self._adjustPagerLeft();
                }
            };

            wijgallery.prototype._adjustPagerLeft = function () {
                var left = this.pager.css("left").replace(/px/, ""), numLeft = parseFloat(left);

                if (!isNaN(numLeft)) {
                    this.pager.css("left", numLeft - 1);
                }
            };

            wijgallery.prototype._createBtn = function (btnClass, itemClass) {
                var btn = $(btnHtml), o = this.options;
                btn.addClass(o.wijCSS.stateDefault + ' ' + btnClass).attr("role", "button").bind("mouseover" + this.widgetName, function () {
                    if ($(this).hasAllClasses(o.wijCSS.stateDisabled)) {
                        return;
                    }
                    $(this).addClass(o.wijCSS.stateHover);
                }).bind("mouseout" + this.widgetName, function () {
                    if ($(this).hasAllClasses(o.wijCSS.stateDisabled)) {
                        return;
                    }
                    $(this).removeClass(o.wijCSS.stateHover);
                });
                btn.children("span:eq(0)").addClass(o.wijCSS.icon + ' ' + itemClass);
                return btn;
            };

            wijgallery.prototype._createTimer = function () {
                var self = this, o = self.options;
                self._createPausePlay();

                self.progressBar = $("<div></div>").addClass("wijmo-wijgallery-timerbar-inner " + o.wijCSS.cornerAll).css({ width: "0%" }).attr("role", "progressbar");

                self.timer = $("<div></div>").addClass("wijmo-wijgallery-timerbar " + o.wijCSS.cornerAll).appendTo(self.frame).append(self.progressBar).append(self.playPauseBtn);
            };

            wijgallery.prototype._createPausePlay = function () {
                var self = this, o = self.options;
                self.playPauseBtn = $(self._createBtn(btnCss, o.autoPlay ? o.wijCSS.iconPause : o.wijCSS.iconPlay)).bind("wijclick." + self.widgetName, function () {
                    if (!$(this).hasAllClasses(o.wijCSS.stateDisabled)) {
                        var icon = $(this).children("span:eq(0)");
                        self[icon.hasAllClasses(o.wijCSS.iconPlay) ? "play" : "pause"]();
                    }
                });
            };

            wijgallery.prototype._show = function (index) {
                var self = this, img = self.images[index], iframeContent, lastContent, newImg, size = self._getFrameSize(), o = self.options, m = o.mode;
                if (self.currentIdx === index) {
                    return;
                }

                if (img && $.isPlainObject(img)) {
                    self.loading.delay(500).fadeIn(100);
                    newImg = self.last.children("img,div." + flashCss);
                    if (newImg.length) {
                        newImg.remove();
                    }

                    if (m === "swf" || m === "flv") {
                        self.last.hide();
                        self.current.empty();
                        self._wrapFlash(self.current, m, img.url);
                        self.picture = self.current.children("div." + flashCss);
                        self._setCurrentStates(index);

                        //self.picture.fadeIn(100);
                        self.loading.stop().hide();
                        self._thumbsScroll(index);
                    } else if (m === "img") {
                        if (self.picture && self.picture.length) {
                            self.last.append(self.picture);
                        }
                        self.current.addClass("ui-helper-hidden-accessible");
                        self.last.show();
                        self.picture = $("<img>");
                        self.picture.one("load", function () {
                            self.picture.data("itemIndex", index).appendTo(self.current);
                            self._imageLoaded(self, size);
                        }).attr({
                            src: img.url,
                            alt: img.title
                        });
                    } else if (m === "iframe") {
                        if (self.current.is(":hidden")) {
                            iframeContent = self.current;
                            lastContent = self.last;
                        } else {
                            iframeContent = self.last;
                            lastContent = self.current;
                        }

                        self.picture = $('<iframe></iframe>').addClass('wijmo-wijgallery-iframe').attr({
                            frameborder: '0',
                            marginwidth: '0',
                            marginheight: '0',
                            scrolling: 'auto',
                            allowtransparency: 'true',
                            src: img.url
                        }).hide().appendTo(iframeContent).data("itemIndex", index).bind('load', function () {
                            var pic = $(this), index = pic.data("itemIndex");
                            self.loading.stop().hide();
                            if (self.pointer) {
                                self.pointer.fadeOut(100);
                            }
                            self._setCurrentStates(index);
                            if (index !== undefined) {
                                if (o.showCaption) {
                                    //self._loadCaption(self.images[index]);
                                    //self._showCaption(self.images[index]);
                                }
                                pic.show();
                                lastContent.fadeOut(function () {
                                    lastContent.empty();
                                });
                                iframeContent.fadeIn();
                            }
                        });
                    }
                }
            };

            wijgallery.prototype._imageLoaded = function (self, size) {
                var pic = self.picture.attr("role", "img"), index = pic.data("itemIndex"), w = pic[0].naturalWidth || pic.width(), h = pic[0].naturalHeight || pic.height(), image = self.images[index];
                self.loading.stop().hide();
                self.current.removeClass("ui-helper-hidden-accessible");
                self.current.hide();
                if (self.pointer) {
                    self.pointer.fadeOut(100);
                }
                if (w >= size.w || h >= size.h) {
                    if (w / h > size.w / size.h) {
                        pic.css({ width: "100%" });
                    } else {
                        pic.css({ height: "100%" });
                    }
                } else if (w < size.w && h < size.h) {
                    pic.addClass(self.options.wijCSS.stateDefault).addClass("wijmo-wijgallery-small-image");
                }

                if (index !== undefined && image !== undefined) {
                    if (self.options.showCaption && self.caption) {
                        self._loadCaption(image);
                    }
                    self._animate(index);
                }
            };

            wijgallery.prototype._animate = function (index) {
                var self = this, o = self.options, animate = o.transitions, hori = o.thumbnailOrientation === "horizontal", width, height, wrapper, half, data, forward, effect = animate.animated, duration = animate.duration;

                //if (!self.last.find("img").attr("src") &&
                //!self.last.find("div."+flashCss)) {
                if (!self.last.children().length) {
                    self._setCurrentStates(index);
                    self.last.hide();
                    self.current.show();
                    return;
                }

                data = {
                    index: self.currentIdx,
                    to: index,
                    toImg: self.images[index]
                };
                if (!self._trigger("beforeTransition", null, data)) {
                    return;
                }

                if (effect) {
                    if (effect === "slide") {
                        width = self.size.w;
                        height = self.size.h;
                        self.current.show();
                        forward = self.currentIdx > index ? true : false;

                        wrapper = $.createWrapper(self.last).css({
                            overflow: 'hidden',
                            width: hori ? width * 2 : width,
                            height: hori ? height : height * 2,
                            left: hori ? (forward ? -width : 0) : 0,
                            top: hori ? 0 : (forward ? -height : 0)
                        });

                        wrapper[forward ? "prepend" : "append"](self.current);

                        wrapper.animate({
                            left: hori ? (forward ? 0 : -width) : 0,
                            top: hori ? 0 : (forward ? 0 : -height)
                        }, duration, function () {
                            if (self.last.parent().is(".ui-effects-wrapper")) {
                                self.last.unwrap();
                            }
                            self.last.hide();
                            self._setCurrentStates(index);
                        });
                    } else {
                        if ($.mobile) {
                            half = duration / 2;
                            self.last.fadeOut(half, function () {
                                self.current.stop(true, true).fadeIn(half, function () {
                                    self._setCurrentStates(index);
                                });
                            });
                        } else {
                            if (effect === "explode" || effect === "scale" || effect === "blind" || effect === "fold") {
                                self.current.css({ position: "absolute" });
                                self.current.stop(true, true).show(effect, duration, function () {
                                    self.last.hide();
                                    self._setCurrentStates(index);
                                });
                            } else if (effect === "size") {
                                self.last.hide();
                                self.current.stop(true, true).show(effect, duration, function () {
                                    self.last.hide();
                                    self._setCurrentStates(index);
                                });
                            } else {
                                half = duration / 2;
                                self.last.hide(effect, half, function () {
                                    self.last.hide();
                                    self.current.stop(true, true).show(effect, half, function () {
                                        self._setCurrentStates(index);
                                    });
                                });
                            }
                        }
                    }
                } else {
                    self.last.hide();
                    self.current.show();
                    self._setCurrentStates(index);
                }

                self._thumbsScroll(index);
            };

            wijgallery.prototype._thumbsScroll = function (index) {
                var scrollIdx, self = this, o = self.options;
                if (self.thumbs && self.thumbs[self.thumbWidgetName]) {
                    if (o.scrollWithSelection) {
                        scrollIdx = index - Math.ceil(o.thumbsDisplay / 2) + 1;
                        if (index > 0 && index < self._count - 1)
                            self.thumbs[self.thumbWidgetName]("scrollTo", scrollIdx);
                    } else {
                        if (index > (o.thumbsDisplay + self.currentThumbIdx - 1)) {
                            self.thumbs[self.thumbWidgetName]("scrollTo", index - o.thumbsDisplay + 1);
                        } else if (index < self.currentThumbIdx) {
                            self.thumbs[self.thumbWidgetName]("scrollTo", index);
                        }
                    }
                }
            };

            wijgallery.prototype._setCurrentStates = function (index) {
                var self = this, o = self.options, shouldPlay, data, last;

                last = self.currentIdx;
                self.currentIdx = index;
                shouldPlay = (index + 1) < self._count;

                if (self.isPlaying && shouldPlay) {
                    self.timeout = null;
                    self.isPlaying = false;
                    self._play();
                } else if (self.progressBar) {
                    self.pause();
                }

                // add disable to play btn.
                if ((index + 1) >= self._count) {
                    self.nextBtn.add(self.playPauseBtn).removeClass(o.wijCSS.stateHover).addClass(o.wijCSS.stateDisabled);
                } else {
                    self.nextBtn.add(self.playPauseBtn).removeClass(o.wijCSS.stateDisabled);
                }

                if (index <= 0) {
                    self.previousBtn.removeClass(o.wijCSS.stateHover).addClass(o.wijCSS.stateDisabled);
                } else {
                    self.previousBtn.removeClass(o.wijCSS.stateDisabled);
                }

                if (o.showCaption) {
                    self._showCaption(self.images[index]);
                }

                if (self.thumbs && self.thumbs[self.thumbWidgetName]) {
                    self.activeLi = self.thumbs.find(carouselItem).eq(index);
                    if (!self.isScrolling) {
                        self._highlightThumb(self.activeLi);
                    }
                } else if (self.pager) {
                    if (self.pager.is(":wijmo-wijpager")) {
                        self.pager.wijpager("option", "pageIndex", index);
                    }
                }

                self._refreshCounter();
                self._clearCss();
                data = {
                    last: last,
                    index: self.currentIdx,
                    toImg: self.images[self.currentIdx]
                };

                self._trigger("afterTransition", null, data);
            };

            wijgallery.prototype._clearCss = function () {
                this.current.css({ position: "", visibility: "" });
            };

            wijgallery.prototype._resetState = function () {
                var self = this;
                self._stopAnimation();
                if (self.isPlaying && self.progressBar) {
                    self.progressBar.stop();
                    self.progressBar.css({ width: "0%" });
                }
            };

            wijgallery.prototype._stopAnimation = function () {
                var self = this, wrapper;
                wrapper = self.content.find(".ui-effects-wrapper");
                if (wrapper.length) {
                    wrapper.stop(true, true);
                }
                self.current.stop(true, true);
                self.last.stop(true, true);
            };

            /**
            * Returns a count of the number of items in the gallery.
            * @returns {number} The number of items in the gallery
            */
            wijgallery.prototype.count = function () {
                return this._count;
            };

            wijgallery.prototype._wijdestroy = function () {
                var self = this, wijCSS = self.options.wijCSS;
                self.frame.unwrap().remove();
                self.frame = null;
                if (self.options.thumbnails) {
                    if ($[self.namespace][self.thumbWidgetName]) {
                        self.thumbs[self.thumbWidgetName]("destroy");
                        self.element.find("li").unbind().removeClass([wijCSS.stateDefault, wijCSS.stateActive].join(" ")).filter("." + selectedCss).removeClass(selectedCss);
                        self.thumbs.children("ul").unwrap().unwrap();
                        self.thumbs = null;
                    }
                } else {
                    if (self.pager && self.pager.length) {
                        self.pager.remove();
                        self.pager = null;
                    }
                    self.element.find("ul").css({ display: "" });
                }
                if (self.pointer) {
                    self.pointer.remove();
                    self.pointer = null;
                }
                self.element.removeClass([baseCss, wijCSS.widget, wijCSS.content, wijCSS.cornerAll].join(' '));
            };

            /**
            * Removes the wijgallery functionality completely. This returns the element to its pre-init state.
            */
            wijgallery.prototype.destroy = function () {
                this._wijdestroy();
                _super.prototype.destroy.call(this);
            };

            /**
            * Shows the picture at the specified index.
            * @example $("#element").wijgallery("show", 1);
            * @param {number} index The zero-based index of the picture to show.
            */
            wijgallery.prototype.show = function (index) {
                var self = this;
                self._resetState();
                self._show(index);
            };

            /**
            * Shows the next picture.
            */
            wijgallery.prototype.next = function () {
                var self = this, idx;
                if (self._isDisabled()) {
                    return;
                }
                self._resetState();
                idx = self.currentIdx + 1;
                if (idx < self._count) {
                    self._show(idx);
                }
            };

            /**
            * Shows the previous picture.
            */
            wijgallery.prototype.previous = function () {
                var self = this, idx;
                if (self._isDisabled()) {
                    return;
                }
                self._resetState();
                idx = self.currentIdx - 1;
                if (idx >= 0) {
                    self._show(idx);
                }
            };

            /**
            * Starts automatically displaying each of the images in order.
            */
            wijgallery.prototype.play = function () {
                this._play();
            };

            wijgallery.prototype._play = function (isFirst) {
                var self = this, o = self.options;
                if (self.isPlaying || self._isDisabled()) {
                    return;
                }

                if (o.interval === 0) {
                    return self.pause();
                }

                if (isFirst && o.mode !== "swf") {
                    //if called by autoplay, images will be played after first image loaded.
                    self.isPlaying = true;
                    return;
                }

                if (o.showTimer && self.progressBar) {
                    self.progressBar.css({
                        width: "0%"
                    });
                    self.playPauseBtn.children("span:eq(0)").removeClass(o.wijCSS.iconPlay).addClass(o.wijCSS.iconPause);
                    self.progressBar.animate({ width: "100%" }, o.interval, null, function () {
                        self._show(self.currentIdx + 1);
                    });
                } else {
                    if (self.timeout) {
                        return;
                    }
                    self.timeout = window.setTimeout(function () {
                        if (self.timerCount <= 1) {
                            //ensure only one timer call "next" at same time.
                            self.next();
                        }
                        self.timerCount--;
                    }, o.interval);
                    self.timerCount++;
                }
                self.isPlaying = true;
            };

            /**
            * Stops automatically displaying the images in order.
            */
            wijgallery.prototype.pause = function () {
                var self = this, o = self.options;
                if (o.showTimer && self.progressBar) {
                    self.progressBar.stop();
                    self.progressBar.css({
                        width: "0%"
                    });
                    self.playPauseBtn.children("span:eq(0)").removeClass(o.wijCSS.iconPause).addClass(o.wijCSS.iconPlay);
                } else {
                    if (self.timeout === null) {
                        return;
                    }
                    window.clearTimeout(self.timeout);
                    self.timeout = null;
                }
                self.isPlaying = false;
            };

            /**
            * Adds a custom item with specified index.
            * The first parameter is the new item to add,
            * it should be a jQuery Element or HTML string.
            * The second parameter is the index of item to add ,
            * If  no index specified the item will be added at the last of item collection.
            * @example
            * $("#element").wijgallery("add", "<li><img..></li>", index);
            * @param {string|jQuery} ui The node content or innerHTML.
            * @param {number} index Specified the postion to insert at.
            
            */
            wijgallery.prototype.add = function (ui, index) {
                var self = this, item, idx, data;
                if (typeof ui === "string") {
                    item = $(ui);
                    data = self._initLi(item);
                } else if (ui.jquery) {
                    item = ui;
                    data = self._initLi(item);
                } else if ($.isPlainObject(ui)) {
                    data = ui;
                } else {
                    return;
                }

                //image
                if (!index || index > self._count) {
                    idx = self._count;
                } else if (index < 0) {
                    idx = 0;
                } else {
                    idx = index;
                }

                self.images.splice(idx, 0, data);
                self._count++;
                if (self.thumbs && self.thumbs[self.thumbWidgetName]) {
                    if (self.pointer && self.pointer.is(":hidden")) {
                        self.pointer.show();
                    }
                    self.thumbs[self.thumbWidgetName]("add", item, idx);
                }

                if (self._count === 1) {
                    self.show(0);
                }

                self._refreshStateWithItemsChanged(idx);
            };

            /**
            * Removes the item at specified index.
            * The parameter is the index of item to add ,
            * If no index specified the last item will be removed.
            * @example
            * $("#element").wijgallery("remove", index);
            * @param {number} index Specified which item should be removed.
            */
            wijgallery.prototype.remove = function (index) {
                var self = this, idx;
                if (isNaN(index) || index >= self._count) {
                    idx = self._count - 1;
                } else if (index < 0) {
                    idx = 0;
                } else {
                    idx = index;
                }

                if (idx >= 0) {
                    self.images.splice(idx, 1);

                    self._count--;
                    if (self.thumbs && self.thumbs[self.thumbWidgetName]) {
                        self.thumbs[self.thumbWidgetName]("remove", idx);
                    }
                    if (self.currentIdx == idx) {
                        self.current.children("img").remove();
                        self.last.children("img").remove();
                        self.picture = null;
                        self.currentIdx = -1;
                        if (self._count > 0) {
                            if (idx === self._count) {
                                self.show(idx - 1);
                            } else {
                                self.show(idx);
                            }
                        }
                    } else if (self.currentIdx > idx) {
                        var ci = self.currentIdx;
                        self.currentIdx = -1;
                        self.show(ci);
                    }

                    self._refreshStateWithItemsChanged(idx);
                }
            };

            wijgallery.prototype._refreshStateWithItemsChanged = function (index) {
                var self = this, o = self.options;

                if (self._count === 0) {
                    self.nextBtn.removeClass(o.wijCSS.stateHover).addClass(o.wijCSS.stateDisabled);
                    self.previousBtn.removeClass(o.wijCSS.stateHover).addClass(o.wijCSS.stateDisabled);
                    if (self.playPauseBtn) {
                        self.playPauseBtn.removeClass(o.wijCSS.stateHover).addClass(o.wijCSS.stateDisabled);
                    }
                    if (self.pointer) {
                        self.pointer.hide();
                    }
                } else {
                    if (self.currentIdx <= 0) {
                        self.previousBtn.removeClass(o.wijCSS.stateHover).addClass(o.wijCSS.stateDisabled);
                    } else if (self.currentIdx >= self._count - 1) {
                        self.nextBtn.removeClass(o.wijCSS.stateHover).addClass(o.wijCSS.stateDisabled);
                        if (self.playPauseBtn) {
                            self.playPauseBtn.removeClass(o.wijCSS.stateHover).addClass(o.wijCSS.stateDisabled);
                        }
                    } else {
                        self.nextBtn.removeClass(o.wijCSS.stateDisabled);
                        self.previousBtn.removeClass(o.wijCSS.stateDisabled);
                        if (self.playPauseBtn) {
                            self.playPauseBtn.removeClass(o.wijCSS.stateDisabled);
                        }
                        if (self.pointer && self.pointer.is(":hidden")) {
                            self.pointer.show();
                        }
                    }
                }

                self._refreshCounter();
            };

            wijgallery.prototype._getExt = function (url) {
                var ext, m, regExt = /[0-9a-z]+$/i, q = url.indexOf("?");

                if (q > -1) {
                    url = url.substring(0, q);
                }

                m = url.match(regExt);
                if (m) {
                    ext = m[0].toLowerCase();
                }

                return ext;
            };

            wijgallery.prototype._getPlayerName = function (url) {
                if (url.indexOf("#") === 0 || (url.indexOf("#") > 0 && url.indexOf(document.location.href) === 0)) {
                    return "inline";
                }

                var imgExt = ["bmp", "gif", "jpg", "jpeg", "png"], swfExt = ["swf"], flvExt = ["flv", "m4v"], qtExt = ["dv", "mov", "moov", "movie", "mp4", "avi", "mpg", "mpeg"], wmpExt = ["asf", "avi", "mpg", "mpeg", "wm", "wmv"], ext = this._getExt(url);
                if (ext) {
                    if ($.inArray(ext, imgExt) >= 0) {
                        return "img";
                    }
                    if ($.inArray(ext, swfExt) >= 0) {
                        return "swf";
                    }
                    if ($.inArray(ext, flvExt) >= 0) {
                        return "flv";
                    }
                    if ($.inArray(ext, wmpExt) >= 0) {
                        return "wmp";
                    }
                    if ($.inArray(ext, qtExt) >= 0) {
                        return "qt";
                    }
                }
                return "unknown";
            };

            wijgallery.prototype._wrapFlash = function (container, type, url) {
                var self = this, lo = self.options, swf = url, wrapper, width = '100%', height = '100%', express = lo.flashInstall, version = lo.flashVersion, flashvars = lo.flashVars, params = lo.flashParams, id = self._newId();

                if (type === "flv") {
                    swf = lo.flvPlayer;
                    flashvars = $.extend({
                        file: url,
                        width: width,
                        height: height,
                        autostart: (lo.autoPlayMovies ? 'true' : 'false'),
                        controlbar: (lo.showMovieControls ? 'bottom' : "none"),
                        backcolor: "0x000000",
                        frontcolor: "0xCCCCCC",
                        lightcolor: "0x557722"
                    }, lo.flashVars);
                    params = $.extend({
                        autostart: (lo.autoPlayMovies ? 'true' : 'false'),
                        allowscriptaccess: 'always'
                    }, lo.flashParams);
                }

                wrapper = $('<div/>').addClass(flashCss).appendTo(container);
                $('<div/>').css({
                    width: '100%',
                    height: '100%',
                    overflow: 'hidden'
                }).attr('id', id).appendTo(wrapper);

                S.flash.embedSWF(swf, id, width, height, version, express, flashvars, params);
            };

            wijgallery.prototype._newId = function () {
                var chars = "a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z", charArray = [], id = "", i;
                charArray = chars.split("|");
                for (i = 0; i < 16; i++) {
                    id += charArray[Math.round(Math.random() * 25)];
                }
                return id;
            };
            return wijgallery;
        })(wijmo.wijmoWidget);
        gallery.wijgallery = wijgallery;

        wijgallery.prototype.thumbWidgetName = "wijcarousel";

        var wijgallery_options = (function () {
            function wijgallery_options() {
                /**
                * wijMobileCSS
                * @ignore
                */
                this.wijMobileCSS = {
                    header: "ui-header ui-bar-a",
                    content: "ui-body-a",
                    stateDefault: "ui-btn-up-a",
                    stateHover: "ui-btn-down-a",
                    stateActive: "ui-btn-down-b",
                    iconPlay: "ui-icon-arrow-r",
                    iconPause: "ui-icon-grid"
                };
                /** Selector option for auto self initialization.
                * This option is internal.
                * @ignore
                */
                this.initSelector = ":jqmData(role='wijgallery')";
                /** Allows pictures to be played automatically.
                * @example $("#element").wijgallery( { autoPlay: true } );
                */
                this.autoPlay = false;
                /** If set to true, the thumbnails will auto
                * scrolled after you select the image.
                * @example $("#element").wijgallery( { scrollWithSelection: true } );
                */
                this.scrollWithSelection = false;
                /** Determines if the timer bar should be shown.
                * @example $("#element").wijgallery( { showTimer: false } );
                */
                this.showTimer = true;
                /** Determines the time span between 2 pictures showing in autoplay mode.
                * @example $("#element").wijgallery( { interval: 3000 } );
                */
                this.interval = 5000;
                /** Determines whether the caption of items should be shown.
                * @example $("#element").wijgallery( { showCaption: true } );
                */
                this.showCaption = true;
                /** Determines whether to show captions for the thumbnails in the gallery.
                * @example $("#element").wijgallery( { showThumbnailCaptions: true } );
                */
                this.showThumbnailCaptions = false;
                /** An object collection that contains the data of the gallery.
                * @example
                * $("#element").wijgallery( { data: [{
                *     url: "../images/image1.jpg",
                *     thumbUrl: "../thumb/image1.jpg",
                *     caption: "<span>Word Caption 1</span>"
                * },{
                *     url: "../images/image2.jpg",
                *     thumbUrl: "../thumb/image2.jpg",
                *     caption: "<span>Word Caption 2</span>"
                * }] } );
                */
                this.data = [];
                /** Determines whether the custom control should be shown.
                * @example $("#element").wijgallery( { showControls: true } );
                */
                this.showControls = false;
                /** Determines the innerHTML of the custom control.
                * @example $("#element").wijgallery( { control: "<div>Blah</div>" } );
                */
                this.control = "";
                /** A value that indicates the position settings for the custom control.
                * @type {object}
                * @example $("#element").wijgallery( {
                *     controlPosition: {
                *         my: 'left bottom',
                *         at: 'right top',
                *         offset: '0 0'}
                * });
                */
                this.controlPosition = {};
                /** Determines whether the controls should be shown after the dom element is created or hovered on.
                * @example $("#element").wijgallery( {
                *     showCounter: false
                * });
                */
                this.showCounter = true;
                /** Determines the text format of counter.
                * @remarks
                * '[i]' and '[n]' are built-in parameters represents
                * the current page index and the number of pages.
                * @example
                * $("#id").wijgallery({
                *     counter: '[i]/[n]'
                * });
                */
                this.counter = "[i] of [n]";
                /** Determines if the pager should be shown.
                * @example $("#element").wijgallery( {
                *     showPager: false
                * } );
                */
                this.showPager = false;
                /** Determines the position of the pager.
                * @type {object}
                * @example $("#element").wijgallery( {
                *     pagingPosition: { my:{ },at:{ } } ;
                * } );
                */
                this.pagingPosition = {};
                /** Determines the orientation of the thumbnails. Possible values are: "vertical" and "horizontal".
                * @example $("#element").wijgallery( {
                *     thumbnailOrientation: "vertical"
                * } );
                */
                this.thumbnailOrientation = "horizontal";
                /** Determines the direction of the thumbnails. Possible values are: "before" and "after".
                * @example $("#element").wijgallery( {
                *     thumbnailOrientation: "before"
                * } );
                */
                this.thumbnailDirection = "after";
                /** A value that determines the settings of the animation effect to be used when the wijgallery is scrolling.
                * @type {object}
                * @example $("#element").wijgallery( {
                *     transitions: {
                *         animated: "slide",
                *         duration: 1000
                *     }
                * } );
                */
                this.transitions = {
                    animated: "slide",
                    duration: 1000,
                    easing: null
                };
                /** Determines whether the controls should be shown after the dom element is created or hovered on.
                * @example $("#element").wijgallery( { showControlsOnHover: true } );
                */
                this.showControlsOnHover = true;
                /** Determines how many thumbnails should be displayed.
                * @example $("#element").wijgallery( { thumbsDisplay: 6 } );
                */
                this.thumbsDisplay = 5;
                /** Determines the length of the thumbnails.
                * @example $("#element").wijgallery( { thumbsLength: 6 } );
                */
                this.thumbsLength = 100;
                /** This is the beforeTransition event handler. It is a function called before transitioning to another image.
                * @event
                * @dataKey {number} index The index of the current image.
                * @dataKey {number} to The index of the image that will scrolled to.
                */
                this.beforeTransition = null;
                /** The afterTransition event handler. A function called after the transition is over.
                * @event
                * @dataKey {number} index The index of the current image.
                * @dataKey {number} to The index of the image that will scrolled to.
                */
                this.afterTransition = null;
                /** The loadCallback event handler. A function called after the dom element is created.
                * @event
                * @param {object} data The node widget that relates to this event.
                */
                this.loadCallback = null;
                /** Determines whether to turn on the movie controls in movie player.
                * @example
                *  $("#id").wijgallery({
                *      showMovieControls: false
                *  });
                */
                this.showMovieControls = false;
                /** Determines whether to turn on the autoplay option in movie player.
                * @example
                *  $("#id").wijgallery({
                *      autoPlayMovies: false
                *  });
                */
                this.autoPlayMovies = true;
                /** A hash object that contains parameters for flash object.
                * @type{object}
                * @example
                *  $("#id").wijgallery({
                *      flashParams: { allowfullscreen: false }
                *  });
                */
                this.flashParams = {
                    bgcolor: "#000000",
                    allowfullscreen: true,
                    wmode: "transparent"
                };
                /** A hash object that contains variants for flash object.
                * @type {object}
                * @example
                * $("#id").wijgallery({  flashVars: { width:300,  height:400 } });
                */
                this.flashVars = {};
                /** Version of flash object.
                * @example
                * $("#id").wijgallery({  flashVersion: "8.0" })
                */
                this.flashVersion = "9.0.115";
                /** The relative path and name of the flash vedio player.
                * @example
                * $("#id").wijgallery({  flvPlayer: "player\\player2.swf " });
                */
                this.flvPlayer = 'player\\player.swf';
                /** The relative path and name of the flash installation guide.
                * @example
                * $("#id").wijgallery({  flashInstall: " player\expressInstall2.swf " });
                */
                this.flashInstall = 'player\\expressInstall.swf';
                /** Determines the display mode of the gallery.
                * Possible values: "img", "iframe", "swf", "flv"
                * @example
                * $("#id").wijgallery({  mode: "swf" });
                */
                this.mode = "img";
            }
            return wijgallery_options;
        })();

        wijgallery.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijgallery_options());

        $.wijmo.registerWidget("wijgallery", wijgallery.prototype);
    })(wijmo.gallery || (wijmo.gallery = {}));
    var gallery = wijmo.gallery;
})(wijmo || (wijmo = {}));

;
/// <reference path="../Base/jquery.wijmo.widget.ts" />
/// <reference path="../wijutil/jquery.wijmo.raphael.ts"/>
/// <reference path="../external/declarations/globalize.d.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*
    * Depends:
    *	raphael.js
    *	globalize.min.js
    *	jquery.ui.widget.js
    *	jquery.wijmo.raphael.js
    */
    (function (gauge) {
        var $ = jQuery, disabledCss = ".35";

        /** @ignore */
        (function (Compass) {
            Compass[Compass["east"] = 0] = "east";
            Compass[Compass["west"] = 1] = "west";
            Compass[Compass["south"] = 2] = "south";
            Compass[Compass["north"] = 3] = "north";
        })(gauge.Compass || (gauge.Compass = {}));
        var Compass = gauge.Compass;

        /** @ignore */
        var GaugeUtil = (function () {
            function GaugeUtil() {
            }
            GaugeUtil.mod360 = function (value) {
                var result = value % 360;
                if (value < 0) {
                    result += 360;
                }
                return result;
            };

            GaugeUtil.getAngle = function (p1, pivot, p2) {
                var self = this, a = self.distance(pivot, p2), b = self.distance(pivot, p1), c = self.distance(p2, p1), a2 = a * a, b2 = b * b, c2 = c * c, angleRadians = Math.acos((c2 - b2 - a2) / (-2 * b * a));
                return Math.round(180 / Math.PI * angleRadians);
            };

            GaugeUtil.distance = function (a, b) {
                return Math.sqrt(Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y, 2));
            };

            GaugeUtil.log = function (val, base) {
                if (val <= 0) {
                    return NaN;
                }
                if (base === 1 || base < 0) {
                    return NaN;
                }
                return Math.log(val) / Math.log(base);
            };

            GaugeUtil.generateValues = function (from, to, interval) {
                var list = [], qty, i;
                if (to > from && interval > 0) {
                    qty = parseInt(((to - from) / interval + 1).toString(), 10);
                    for (i = 0; i < qty; i++) {
                        list.push(from + i * interval);
                    }
                } else if (interval === 0) {
                    list.push(from);
                }
                return list;
            };

            GaugeUtil.isInRange = function (value, min, max) {
                return (value >= min && value <= max) || (value <= min && value >= max);
            };

            GaugeUtil.paintMarker = function (canvas, marker, x, y, length, width, isHorizontal) {
                var ele;
                if (marker === "rect") {
                    return canvas.rect(x - length / 2, y - width / 2, length, width);
                } else {
                    if (isHorizontal) {
                        ele = canvas.paintMarker(marker, x, y, width);
                    } else {
                        ele = canvas.paintMarker(marker, x, y, length);
                    }
                    return ele;
                }
            };

            GaugeUtil.formatString = function (str, format) {
                if ($.isFunction(format)) {
                    return format.call(this, str);
                } else if (format !== "") {
                    var reg = /\{0(?::((?:n|d|p|c)\d?))?\}/gi, match, formater;
                    if (reg.test(format)) {
                        match = format.match(reg);
                        formater = "$1";
                        return format.replace(/\{0(?::(?:(?:n|d|p|c)\d?))?\}/gi, Globalize.format(str, formater));
                    }
                }
                return str;
            };

            GaugeUtil.getPositionByAngle = function (cx, cy, r, angle) {
                var point = { x: 0, y: 0 }, rad = Raphael.rad(angle);

                point.x = cx - r * Math.cos(rad);
                point.y = cy - r * Math.sin(rad);
                return point;
            };

            GaugeUtil.donut = function (canvas, cx, cy, outerR, innerR, startAngle, endAngle) {
                var getPosByAngle = this.getPositionByAngle, outerS = getPosByAngle(cx, cy, outerR, startAngle), outerE = getPosByAngle(cx, cy, outerR, endAngle), innerS = getPosByAngle(cx, cy, innerR, startAngle), innerE = getPosByAngle(cx, cy, innerR, endAngle), largeAngle = endAngle - startAngle > 180, path;

                if ((endAngle - startAngle) % 360 !== 0) {
                    path = [
                        "M", outerS.x, outerS.y,
                        "A", outerR, outerR, 0, +largeAngle, 1, outerE.x, outerE.y,
                        "L", innerE.x, innerE.y,
                        "A", innerR, innerR, 0, +largeAngle, 1, innerS.x, innerS.y,
                        "L", outerS.x, outerS.y, "z"];
                    canvas.path(path.join(" "));
                } else {
                    canvas.circle(cx, cy, outerR);
                }
            };
            return GaugeUtil;
        })();
        gauge.GaugeUtil = GaugeUtil;

        Raphael.fn.isoTri = function (x, y, width, height, compass) {
            var x1 = x, y1 = y + height / 2, x2 = x + width, y2 = y, x3 = x + width, y3 = y + height, arrPath;

            if (compass == 3 /* north */) {
                x1 = x;
                y1 = y;
                x2 = x - width / 2;
                y2 = y + height;
                x3 = x + width / 2;
                y3 = y + height;
            } else if (compass === 0 /* east */) {
                x1 = x - width / 2;
                y1 = y - height / 2;
                x2 = x - width / 2;
                y2 = y + height / 2;
                x3 = x + width / 2;
                y3 = y;
            } else if (compass === 1 /* west */) {
                x1 = x - width / 2;
                y1 = y;
                x2 = x + width / 2;
                y2 = y - height / 2;
                x3 = x + width / 2;
                y3 = y + height / 2;
            }
            arrPath = ["M", x1, y1, "L", x2, y2, "L", x3, y3, "z"];
            return this.path(arrPath.join(" "));
        };

        /**
        * @widget
        */
        var wijgauge = (function (_super) {
            __extends(wijgauge, _super);
            function wijgauge() {
                _super.apply(this, arguments);
            }
            wijgauge.prototype._create = function () {
                var self = this, o = self.options, newEle;

                // enable touch support:
                if (window.wijmoApplyWijTouchUtilEvents) {
                    $ = window.wijmoApplyWijTouchUtilEvents($);
                }

                if (self.element.is(":hidden") && self.element.wijAddVisibilityObserver) {
                    self.element.wijAddVisibilityObserver(function () {
                        self.redraw();
                        if (self.element.wijRemoveVisibilityObserver) {
                            self.element.wijRemoveVisibilityObserver();
                        }
                    }, "wijgauge");
                }

                if (isNaN(o.width)) {
                    self._setDefaultWidth();
                }
                if (isNaN(o.height)) {
                    self._setDefaultHeight();
                }
                self._setDefaultWidthHeight();

                // handle the juice's function type
                if (o.face && o.face.template && typeof o.face.template === "string" && window[o.face.template]) {
                    o.face.template = window[o.face.template];
                }
                if (o.pointer && o.pointer.template && typeof o.pointer.template === "string" && window[o.pointer.template]) {
                    o.pointer.template = window[o.pointer.template];
                }
                if (o.cap && o.cap.template && typeof o.cap.template === "string" && window[o.cap.template]) {
                    o.cap.template = window[o.cap.template];
                }
                self.element.addClass(o.wijCSS.widget);

                try  {
                    self.canvas = Raphael(self.element[0], o.width, o.height);
                } catch (e) {
                    var displayCss = self.element.css("display");
                    newEle = $("<div></div>").insertBefore(self.element).append(self.element);
                    self.element.addClass("ui-helper-hidden-accessible").appendTo($('body'));
                    if (displayCss === "none") {
                        self.element.css("display", "block");
                    }
                    self.canvas = Raphael(self.element[0], o.width, o.height);
                    self.element.appendTo(newEle).unwrap().removeClass("ui-helper-hidden-accessible");
                    if (displayCss === "none") {
                        self.element.css("display", "none");
                    }
                }
                self._autoCalculate();
                self._draw();
                self._bindResizeEvent();
                _super.prototype._create.call(this);
            };

            wijgauge.prototype._setDefaultWidth = function () {
            };

            wijgauge.prototype._setDefaultHeight = function () {
            };

            wijgauge.prototype._setDefaultWidthHeight = function () {
                var self = this, ele = self.element, o = self.options, style = ele.get(0).style, width = style.width, height = style.height;

                if (width !== "") {
                    o.width = ele.width();
                }

                if (height !== "") {
                    o.height = ele.height();
                }
            };

            wijgauge.prototype._autoCalculate = function () {
            };

            wijgauge.prototype._setOption = function (key, value) {
                var self = this, o = self.options, oldValue = o[key];

                if (key === "value") {
                    if (self._trigger("beforeValueChanged", null, { newValue: value, oldValue: oldValue }) !== false) {
                        _super.prototype._setOption.call(this, key, value);
                        self._set_value(value, oldValue);
                        self._trigger("valueChanged", null, { newValue: value, oldValue: oldValue });
                    }
                } else {
                    _super.prototype._setOption.call(this, key, value);
                    if ($.isPlainObject(value)) {
                        o[key] = $.extend({}, oldValue, value);
                    }

                    if (o.radius === "auto") {
                        self._autoCalculate();
                        self.redraw();
                        return;
                    }

                    if (self["_set_" + key]) {
                        self["_set_" + key](value, oldValue);
                    }
                }
            };

            wijgauge.prototype._innerDisable = function () {
                _super.prototype._innerDisable.call(this);
                this._handleDisabledOption(true, this.element);
            };

            wijgauge.prototype._innerEnable = function () {
                _super.prototype._innerEnable.call(this);
                this._handleDisabledOption(false, this.element);
            };

            wijgauge.prototype._toggleDisable = function () {
                var self = this, e = self.element;
                if (self._isDisabled()) {
                    self._opacityHolder = e.css("opacity");
                    e.css("opacity", disabledCss);
                } else {
                    e.css("opacity", self._opacityHolder);
                }
            };

            wijgauge.prototype._set_value = function (value, oldValue) {
                this._setPointer();
            };

            wijgauge.prototype._set_autoResize = function () {
                this._unbindResizeEvent();
                this._bindResizeEvent();
            };

            wijgauge.prototype._set_max = function () {
                this._redrawMarksAndLabels();
                this._set_ranges();
                this._setPointer();
            };

            wijgauge.prototype._set_min = function () {
                this._redrawMarksAndLabels();
                this._set_ranges();
                this._setPointer();
            };

            wijgauge.prototype._set_width = function () {
                this.redraw();
            };

            wijgauge.prototype._set_height = function () {
                this.redraw();
            };

            wijgauge.prototype._set_isInverted = function () {
                this.redraw();
            };

            wijgauge.prototype._set_tickMajor = function () {
                this._redrawMarksAndLabels();
            };

            wijgauge.prototype._set_tickMinor = function () {
                this._redrawMarksAndLabels();
            };

            wijgauge.prototype._set_pointer = function () {
                var self = this;
                self._removePointer();
                self._paintPointer();
                self._setPointer();
            };

            wijgauge.prototype._removePointer = function () {
                var self = this;
                if (self.pointer) {
                    self._destroyRaphaelElement(self.pointer);
                    self.pointer = null;
                }
            };

            wijgauge.prototype._set_islogarithmic = function () {
                var self = this;
                self._redrawMarksAndLabels();
                self._setPointer();
            };

            wijgauge.prototype._set_logarithmicBase = function () {
                var self = this;
                self._redrawMarksAndLabels();
                self._setPointer();
            };

            wijgauge.prototype._set_labels = function () {
                this._redrawMarksAndLabels();
            };

            wijgauge.prototype._set_margin = function (value, oldValue) {
                if (value !== oldValue) {
                    this.redraw();
                }
            };

            wijgauge.prototype._set_marginTop = function (value, oldValue) {
                this._set_margin(value, oldValue);
            };

            wijgauge.prototype._set_marginBottom = function (value, oldValue) {
                this._set_margin(value, oldValue);
            };

            wijgauge.prototype._set_marginLeft = function (value, oldValue) {
                this._set_margin(value, oldValue);
            };

            wijgauge.prototype._set_marginRight = function (value, oldValue) {
                this._set_margin(value, oldValue);
            };

            wijgauge.prototype._set_ranges = function () {
                var self = this;
                self._removeRanges();
                self._paintRanges();
                self._resetElementPosition();
            };

            wijgauge.prototype._set_face = function () {
                var self = this;
                self._removeFace();
                self._paintFace();
                self._resetElementPosition(true);
            };

            wijgauge.prototype._removeFace = function () {
                var self = this;
                if (self.face) {
                    self._destroyRaphaelElement(self.face);
                    self.face = null;
                }
            };

            wijgauge.prototype._clearState = function () {
                var self = this;
                self.labels = [];
                self.majorMarks = [];
                self.minorMarks = [];
                self.face = null;
                self.pointer = null;
            };

            //when redraw the range or face or pointer, reset the z-index of the elements.
            wijgauge.prototype._resetElementPosition = function (resetRangePosition) {
                var self = this;
                if (resetRangePosition && self.ranges) {
                    $.each(self.ranges, function (i, n) {
                        n.toFront();
                    });
                }

                if (self.majorMarks) {
                    $.each(self.majorMarks, function (i, mark) {
                        mark.toFront();
                    });
                }
                if (self.minorMarks) {
                    $.each(self.minorMarks, function (i, mark) {
                        mark.toFront();
                    });
                }

                if (self.labels) {
                    $.each(self.labels, function (i, label) {
                        label.toFront();
                    });
                }

                if (self.pointer) {
                    self.pointer.toFront();
                }
                if (self.cap) {
                    self.cap.toFront();
                }
            };

            wijgauge.prototype._redrawMarksAndLabels = function () {
                var self = this;
                self._removeMarksAndLabels();
                self._drawMarksAndLabels();
            };

            wijgauge.prototype._removeMarksAndLabels = function () {
                var self = this;
                self._unbindEvents(self.labels);
                self._destroyRaphaelArray(self.labels);

                self._unbindEvents(self.majorMarks);
                self._destroyRaphaelArray(self.majorMarks);

                self._unbindEvents(self.minorMarks);
                self._destroyRaphaelArray(self.minorMarks);
            };

            wijgauge.prototype._destroyRaphaelArray = function (objs) {
                if (!objs) {
                    return;
                }
                var len = objs.length, i = 0, ele;

                for (; len && i < len; i++) {
                    ele = objs[i];
                    this._destroyRaphaelElement(ele);
                    objs[i] = null;
                }
                objs = null;
            };

            wijgauge.prototype._destroyRaphaelElement = function (ele) {
                var obj;
                if (ele && ele[0]) {
                    obj = $(ele.node);
                    obj.unbind().removeData();
                    ele.wijRemove();
                    obj.remove();
                    obj = null;
                    ele = null;
                }
            };

            wijgauge.prototype._drawMarksAndLabels = function () {
                var self = this;
                self.labels = [];
                self.majorMarks = [];
                self.minorMarks = [];
                self._paintMarks();
            };

            wijgauge.prototype._handleDisabledOption = function (disabled, ele) {
                var self = this;

                if (disabled) {
                    if (!self.disabledDiv) {
                        self.disabledDiv = self._createDisabledDiv(ele);
                    }
                    self.disabledDiv.appendTo("body");
                } else {
                    if (self.disabledDiv) {
                        self.disabledDiv.remove();
                        self.disabledDiv = null;
                    }
                }
            };

            wijgauge.prototype._createDisabledDiv = function (outerEle) {
                var self = this, o = self.options, ele = outerEle || self.element, eleOffset = ele.offset(), disabledWidth = o.width || ele.outerWidth(), disabledHeight = o.height || ele.outerHeight(), disabledDiv;

                disabledDiv = $("<div></div>").css({
                    "z-index": "99999",
                    position: "absolute",
                    width: disabledWidth,
                    height: disabledHeight,
                    left: eleOffset.left,
                    top: eleOffset.top
                });
                if (Raphael.vml) {
                    disabledDiv.addClass(o.stateDisabled).css("background-color", "#fff");
                }
                return disabledDiv;
            };

            wijgauge.prototype._triggerPainted = function () {
                return this._trigger("painted");
            };

            wijgauge.prototype._draw = function () {
                var self = this, o = self.options;

                self.pointer = null;

                self._innerBbox = {
                    width: o.width - o.marginLeft - o.marginRight,
                    height: o.height - o.marginTop - o.marginBottom,
                    left: o.marginLeft,
                    top: o.marginTop
                };

                self.face = self._paintFace();
                if (self.ranges) {
                    self._removeRanges();
                }
                self._paintRanges();
                self._drawMarksAndLabels();
                self._paintPointer();
                if (self.pointer) {
                    self._setOffPointerValue();
                    self._setPointer();
                }
                $.wijraphael.clearRaphaelCache();
                self._triggerPainted();
            };

            /**
            * Redraw the gauge.
            */
            wijgauge.prototype.redraw = function () {
                var self = this, o = self.options;
                self._clearElements();
                self._clearState();
                self.canvas.clear();
                self.canvas.setSize(o.width, o.height);
                self._draw();
            };

            /**
            * Remove the functionality completely. This will return the element back to its pre-init state.
            */
            wijgauge.prototype.destroy = function () {
                var self = this;

                self._unbindResizeEvent();

                self._clearElements();
                self.canvas.clear();
                self.canvas = null;
                self._clearVariables();

                self.element.removeClass("ui-widget").empty();

                //Add for fixing bug 16039
                if (self.disabledDiv) {
                    self.disabledDiv.remove();
                    self.disabledDiv = null;
                }

                //end for bug 16039
                _super.prototype.destroy.call(this);
            };

            wijgauge.prototype._clearVariables = function () {
                var self = this;
                self._innerBbox = null;
                self.resizeTimer = null;
            };

            wijgauge.prototype._clearElements = function () {
                var self = this;
                self._removeMarksAndLabels();
                self._removeRanges();
                self._removeFace();
                self._removePointer();
            };

            /**
            * Returns a reference to the Raphael canvas object.
            * @returns {Raphael Element} Reference to raphael canvas object.
            */
            wijgauge.prototype.getCanvas = function () {
                /// <summary>
                /// Returns a reference to the Raphael canvas object.
                /// Code example:
                /// $("gauge").wijgauge("getCanvas");
                /// </summary>
                /// <returns type="Raphael">
                /// Reference to raphael canvas object.
                /// </returns>
                return this.canvas;
            };

            wijgauge.prototype._percentage = function () {
                var self = this, o = self.options, max = o.max, min = o.min, value = o.value;

                if (isNaN(value)) {
                    return 0;
                }
                if (max === min) {
                    return 1;
                }
                return (value - min) / (max - min);
            };

            wijgauge.prototype._valueToLogical = function (value) {
                var self = this, o = self.options, min = o.min, max = o.max, logarithmicBase = o.logarithmicBase, linerValue, alpha;

                if (value < min) {
                    return 0;
                }
                if (max < value) {
                    return 1;
                }
                linerValue = (value - min) / (max - min);
                if (!o.islogarithmic) {
                    alpha = linerValue;
                } else {
                    alpha = GaugeUtil.log(1 + (logarithmicBase - 1) * linerValue, o.logarithmicBase);
                }

                return alpha;
            };

            wijgauge.prototype._logicalToValue = function (alpha) {
                var self = this, o = self.options, max = o.max, min = o.min, linearValue;

                if (alpha < 0) {
                    return min;
                }
                if (1 <= alpha) {
                    return max;
                }
                if (!o.islogarithmic) {
                    linearValue = alpha;
                } else {
                    if (o.logarithmicBase <= 1) {
                        return o.min;
                    }
                    linearValue = (Math.pow(o.logarithmicBase, alpha) - 1) / (o.logarithmicBase - 1);
                }
                return min + (max - min) * linearValue;
            };

            wijgauge.prototype._bindResizeEvent = function () {
                var self = this;
                if (self.options.autoResize) {
                    self.element.on("resize." + self.widgetName, function () {
                        clearTimeout(self.resizeTimer);
                        self.resizeTimer = setTimeout(function () {
                            self.redraw();
                        }, 250);
                    });
                }
            };

            wijgauge.prototype._unbindResizeEvent = function () {
                this.element.off("resize." + this.widgetName);
            };

            wijgauge.prototype._bindClickEvents = function (eles) {
                var self = this;
                $.each(eles, function (i, n) {
                    $(n.node).bind("click." + self.widgetName, function (e) {
                        self._trigger("click", e, { ele: n });
                    });
                });
            };

            wijgauge.prototype._unbindEvents = function (eles) {
                var self = this;
                $.each(eles, function (i, n) {
                    $(n.node).unbind("." + self.widgetName);
                });
            };

            wijgauge.prototype._setOffPointerValue = function () {
            };

            wijgauge.prototype._setPointer = function () {
            };

            wijgauge.prototype._paintPointer = function () {
            };

            wijgauge.prototype._paintFace = function () {
            };

            wijgauge.prototype._paintRanges = function () {
                var self = this, o = self.options, ranges = o.ranges || [];

                self.ranges = [];
                $.each(ranges, function (i, n) {
                    self._paintRange(n);
                });
            };

            wijgauge.prototype._paintRange = function (range) {
            };

            wijgauge.prototype._removeRanges = function () {
                var self = this;
                if (self.ranges) {
                    self._destroyRaphaelArray(self.ranges);
                }
            };

            wijgauge.prototype._paintMarks = function () {
                var self = this, o = self.options, generateValues = GaugeUtil.generateValues, majorMarks = generateValues(o.min, o.max, o.tickMajor.interval), minorMarks = generateValues(o.min, o.max, o.tickMinor.interval), labelInfo = o.labels, showLabels = labelInfo.visible;

                if (o.tickMajor.visible) {
                    $.each(majorMarks, function (i, n) {
                        self.majorMarks.push(self._paintMark(n, o.tickMajor, true));
                        if (showLabels) {
                            self.labels.push(self._paintLabel(n, labelInfo));
                        }
                    });
                }

                if (o.tickMinor.visible) {
                    $.each(minorMarks, function (i, n) {
                        var IsInMajor = false;
                        $.each(majorMarks, function (k, m) {
                            if (n === m) {
                                IsInMajor = true;
                                return false;
                            }
                        });
                        if (!IsInMajor) {
                            self.minorMarks.push(self._paintMark(n, o.tickMinor, false));
                        }
                    });
                }

                self._bindClickEvents(self.majorMarks);
                self._bindClickEvents(self.minorMarks);
                self._bindClickEvents(self.labels);
            };

            wijgauge.prototype._paintMark = function (n, tickMajor, tag) {
            };

            wijgauge.prototype._paintLabel = function (n, labelInfo) {
            };
            return wijgauge;
        })(wijmo.wijmoWidget);
        gauge.wijgauge = wijgauge;

        var wijgauge_options = (function () {
            function wijgauge_options() {
                /**
                * Sets the value of the gauge, indicated by the pointer.
                * @remarks
                * This value must fall between the min and max values that you set.
                */
                this.value = 0;
                /**
                * Sets the maximum value of the gauge.
                * @remarks
                * Use this option along with min to set the numeric scale of values that are shown on the gauge. This setting limits
                * your valid values for other options, such as value and ranges.
                */
                this.max = 100;
                /**
                * Sets the minimum value of the gauge.
                * @remarks
                * Use this option along with min to set the numeric scale of values that are shown on the gauge. This setting limits
                * your valid values for other options, such as value and ranges.
                */
                this.min = 0;
                /**
                * Sets the width of the gauge area in pixels.
                */
                this.width = 600;
                /**
                * Sets the height of the gauge area in pixels.
                */
                this.height = 400;
                /** A value that indicates whether to redraw the gauge automatically when resizing the gauge element.  */
                this.autoResize = true;
                /**
                * Sets appearance options for the major tick marks that appear next to the numeric labels around the face of the gauge.
                * @example
                *    $(document).ready(function () {
                *        $("#radialgauge1").wijradialgauge({
                * 		value: 90,
                * 		tickMajor: {
                * 		position: "inside",
                * 		style: { fill: "purple", stroke: "#1E395B"},
                * 		factor: 2.5,
                * 		marker: 'diamond',
                * 		visible: true,
                * 		offset: 27,
                * 		interval: 20
                * 		}
                * 	});
                * });
                */
                this.tickMajor = {
                    /**
                    * A value that indicates the position of the major tick marks in relation to the edge of the face
                    * @remarks
                    * Valid Values:
                    *		"inside" -- Draws the major tick marks inside the edge of the face.
                    *		"outside" -- Draws the major tick marks outside the edge of the face.
                    *		"cross" -- Draws the major tick marks centered on the edge of the face.
                    */
                    position: "inside",
                    /**
                    * A value that indicates the fill color and outline (stroke) of the major tick mark.
                    */
                    style: {
                        fill: "#1E395B",
                        stroke: "none"
                    },
                    /**
                    * A value that indicates how long to draw the major tick marks as a factor of the default length of the minor tick marks.
                    */
                    factor: 2,
                    /**
                    * A value that indicates whether to show the major tick mark.
                    */
                    visible: true,
                    /**
                    * A value that indicates the shape to use in drawing major tick marks.
                    * @remarks
                    * Options are 'rect', 'tri', 'circle', 'invertedTri', 'box', 'cross', 'diamond'.
                    */
                    marker: "rect",
                    /**
                    * A value that indicates the distance in pixels from the edge of the face to draw the major tick marks.
                    * The numeric labels are drawn a few pixels
                    */
                    offset: 0,
                    /**
                    * A value that indicates the frequency of the major tick marks and their numeric labels.
                    * @remarks
                    * A setting of 1 renders a major tick mark for every number between the min and max.This setting is useful when
                    * the spread between min and max is small. The default setting of 10 renders a major tick mark once every 10 numbers
                    * between the min and the max. A setting of 100 renders a major tick mark once every 100 numbers between the min
                    * and max. This setting is useful when the spread between min and max is very large.
                    */
                    interval: 10
                };
                /**
                * A value that provides information for the minor tick.
                * @example
                * //This example renders the minor tick marks as purple crosses, at an interval of once every 2 numbers
                *    $(document).ready(function () {
                *        $("#radialgauge1").wijradialgauge({
                *		value: 90,
                *		tickMinor: {
                *		position: "inside",
                *		style: { fill: "#1E395B", stroke: "purple"},
                *		factor: 2,
                *		marker: 'cross',
                *		visible: true,
                *		offset: 30,
                *		interval: 2
                *		}
                *		});
                *		});
                */
                this.tickMinor = {
                    /**
                    * A value that indicates the position of the minor tick marks in relation to the edge of the face.
                    * @remarks
                    * Valid Values:
                    *		"inside" -- Draws the minor tick marks inside the edge of the face.
                    *		"outside" -- Draws the minor tick marks outside the edge of the face.
                    *		"cross" -- Draws the minor tick marks centered on the edge of the face.
                    */
                    position: "inside",
                    /**
                    * A value that indicates the fill color and outline (stroke) of the minor tick mark.
                    */
                    style: { fill: "#1E395B", "stroke": "none" },
                    /**
                    * A value that indicates how long to draw the minor tick marks as a factor of the default length of the minor
                    * tick marks, which is half the default length of the major tick marks.
                    */
                    factor: 1,
                    /**
                    * A value that indicates whether to show the minor tick mark.
                    */
                    visible: false,
                    /**
                    * A value that indicates the shape to use in drawing minor tick marks.
                    * @remarks
                    * In order to use the 'cross' marker shape, you must specify a color for the stroke setting of the style option.
                    * The other shapes use the fill setting, but since the cross is not a closed shape, fill has no effect, and
                    * we must use the outline (stroke) color.
                    * Options are 'rect', 'tri', 'circle', 'invertedTri', 'box', 'cross', 'diamond'.
                    */
                    marker: "rect",
                    /**
                    * A value that indicates the distance in pixels from the edge of the face to draw the minor tick marks.
                    * @remarks
                    * By default, they are three pixels in from the major tick marks.
                    */
                    offset: 0,
                    /**
                    * A value that indicates the frequency of the minor tick marks.
                    */
                    interval: 5
                };
                /**
                * A value that includes all settings of the gauge pointer.
                * @example
                * // The example above renders the pointer as a purple-outlined blue rectangle of 125% the length of the radius
                * // by 10 pixels wide, offset back through the cap by 50% of the length of the radius
                *    $(document).ready(function () {
                *        $("#radialgauge1").wijradialgauge({
                *		value: 90,
                *		cap: {visible: true},
                *		pointer: {
                *		length: 1.25,
                *		offset: 0.5,
                *		shape: "rect",
                *		style: { fill: "blue", stroke: "purple"},
                *		width: 10
                *		}
                *		});
                *		});
                */
                this.pointer = {
                    /**
                    * Sets the length of the pointer as a percentage of the radius(or width/height in lineargauge) of the gauge.
                    * You can set the length to be greater than the radius(or width/height).
                    */
                    length: 1,
                    /**
                    * Sets the fill and outline (stroke) colors of the pointer.
                    */
                    style: {
                        fill: "#1E395B",
                        stroke: "#1E395B"
                    },
                    /**
                    * Sets the width of the pointer in pixels.
                    */
                    width: 8,
                    /**
                    * Sets the percentage of the pointer that is shoved backward through the cap.
                    */
                    offset: 0,
                    /**
                    * Sets the shape in which to render the pointer: triangular or rectangular.
                    * @remarks
                    * Options are 'rect', 'tri'.
                    */
                    shape: "tri",
                    /**
                    * A value that indicates whether to show the pointer.
                    */
                    visible: true,
                    /**
                    * A JavaScript callback value that returns a Raphael element that draws the pointer.
                    * @remarks
                    * Use this option to customize the pointer. In order to use the template, you must know how to draw Raphael
                    * graphics For more information,see the Raphael documentation.
                    * In radial gauge：
                    * The pointer template's callback contains two arguments:
                    *		startLocation -- The starting point from which to draw the pointer. This argument is defined by x and y coordinates.
                    *		pointerInfo -- A JSON object that extends the gauge's pointer options:
                    *			offset -- Sets the percentage of the pointer that is shoved backward through the origin.
                    *			length -- Sets the absolute value in pixels of the length of the pointer.
                    *			gaugeBBox -- An object that sets the bounding box of the gauge, as defined by x and y coordinates and width and height options.
                    */
                    template: null
                };
                /**
                * The islogarithmic option, inherited from the jquery.wijmo.wijgauge.js base class, indicates whether to use logarithmic
                * scaling for gauge label numeric values.
                * @remarks
                * This adds space between tick marks that corresponds to the percentage of change between those numbers rather than
                * absolute arithmetic values. You would want to use logarithmic scaling if you were displaying really high numbers,
                * because it goes higher much more quickly. A linear scale is more difficult to use if you are displaying really high
                * numbers. Note: By default, Wijmo uses a logarithmic base of 10, the common logarithm. See logarithmicBase for
                * information on changing this value.
                * @example
                * // The following code creates a gauge with the number labels and tick marks arranged as in the following image.
                *    $(document).ready(function () {
                *        $("#radialgauge1").wijradialgauge({
                *		value: 90,
                *		islogarithmic: true
                *		});
                *		});
                */
                this.islogarithmic = false;
                /**
                * The logarithmicBase option, inherited from the jquery.wijmo.wijgauge.js base class, indicates the logarithmic
                * base to use if the islogarithmic option is set to true. The logarithmic base is the number to raise to produce the exponent.
                * @remarks
                * For example, with the default base 10, a logarithm of 3 produces 1000, or 10 to the power of 3, or 10³ = 10 x 10 x 10 = 1000.
                * If you change the base to 2, a logarithm of 3 produces 8, or 2³ = 2 x 2 x 2 = 8. You can use the natural
                * logarithm (using a base of ≈ 2.718) by specifying the value Math.e.
                */
                this.logarithmicBase = 10;
                /**
                * Sets all of the appearance options of the numeric labels that appear around the edge of the gauge.
                * @example
                * // This example sets the color for the labels to purple, and the font to 14 point, bold, Times New Roman.
                * $(document).ready(function () {
                *    $("#radialgauge1").wijradialgauge({
                *		value: 90,
                *		labels: {
                *		style: {
                *			fill: "purple",
                *				"font-size": "14pt",
                *				"font-weight": "bold",
                *				"font-family": "Times New Roman"
                *			}
                *		}
                *	});
                *});
                */
                this.labels = {
                    /**
                    * A value that indicates the globalized format to use for the labels.
                    * @remarks
                    * For more information on using jQuery globalize with Wijmo
                    * Note: If the value is a function rather than a string, the function formats the value and returns it to the gauge.
                    */
                    format: "",
                    /**
                    * A value that indicates the color, weight, and size of the numeric labels.
                    */
                    style: {
                        fill: "#1E395B",
                        "font-size": 12,
                        "font-weight": "800"
                    },
                    /**
                    * A value that indicates whether to show the numeric labels.
                    */
                    visible: true,
                    /**
                    * A value in pixels that indicates the distance of the numeric labels from the outer reach of the pointer.
                    * @remarks
                    * A value of 50 pixels renders the labels outside the circular gauge area, cutting off the numbers along
                    * the top. A value of 0 pixels renders the labels just inside the tick marks.
                    */
                    offset: 0
                };
                /**
                * Defines the animation effect, controlling aspects such as duration and easing.
                */
                this.animation = {
                    /**
                    * A value that determines whether to show animation.
                    */
                    enabled: true,
                    /**
                    * The duration option defines the length of the animation effect in milliseconds.
                    */
                    duration: 2000,
                    /**
                    * The easing option uses Raphael easing formulas to add effects to the animation, such as allowing an item to
                    * bounce realistically.
                    * @remarks
                    * Valid Values (see http://raphaeljs.com/easing.html for easing demos):
                    */
                    easing: ">"
                };
                /**
                * Sets or draws the image or shape to use for the face of the gauge and the background area.
                * @remarks
                * The origin is the center of the gauge, but the image draws from the top left, so we first calculate the starting point
                * of the top left based on the origin, and we calculate the width and height based on the radius of the face. The radius
                * of the face is half of the min of the width and height.
                * Note: The fill property is defined using the Raphael framework. Please see the Raphael Element attr method for more
                * information. The face can be filled with a simple color, or a gradient. The default fill is a radial gradient,
                * indicated by the r in the fill property.
                * @example
                * // This example uses a custom image for the face of the gauge. The argument that we name ui in the example is a JSON
                * // object. This object has a canvas, which is a Raphael paper object, and we use the image method of the Raphael
                * // paper that takes five parameters: source, x, y, width, and height. See the Raphael documentation for more information.
                * // We also set the radius to 120 pixels to render it inside the white area of the image.
                *$(document).ready(function () {
                *	$("#radialgauge1").wijradialgauge({
                *		value: 90,
                *		radius: 120,
                *		face: {
                *			style: {},
                *			template: function (ui) {
                *				var url = "images/customGaugeFace.png";
                *				return ui.canvas.image(url, ui.origin.x -ui.r, ui.origin.y -ui.r, ui.r * 2, ui.r * 2);
                *			}
                *		}
                *	});
                *});
                */
                this.face = {
                    /**
                    * A value that indicates the fill color (or gradient), and the outline color and width of the gauge face.
                    */
                    style: {
                        fill: "270-#FFFFFF-#D9E3F0",
                        stroke: "#7BA0CC",
                        "stroke-width": 4
                    },
                    /**
                    * A JavaScript callback value that returns a Raphael element (or set) that draws the gauge face.
                    * @remarks
                    * If you are only using one shape, the function returns a Raphael element. If you define multiple shapes,
                    * have the function create a Raphael set object, push all of the Raphael elements to the set, and return the
                    * set to wijgauge. In order to use the template, you must know how to draw Raphael graphics.
                    * For more information, see the Raphael documentation.
                    * In radial gauge
                    * The face template's callback contains one argument with the following parameters:
                    *		origin -- The starting point from which to draw the center of the face.This argument is defined by x and y coordinates.
                    *		canvas -- A Raphael paper object that you can use to draw the custom graphic to use as the face.
                    */
                    template: null
                };
                /**
                * Sets a value in pixels that indicates where to render the top edge of the gauge face.
                * @remarks
                * Note: If the radius of the gauge is too large to fit within the rectangle defined by the width and height less the
                * specified margins, and the radius is set to the default value of "auto," Wijmo automatically resizes the gauge to fit.
                */
                this.marginTop = 0;
                /**
                * Sets a value in pixels that indicates where to render the right edge of the gauge face.
                * @remarks
                * Note: If the radius of the gauge is too large to fit within the rectangle defined by the width and height less
                * the specified margins, and the radius is set to the default value of "auto," Wijmo automatically resizes the gauge to fit.
                */
                this.marginRight = 0;
                /**
                * Sets a value in pixels that indicates where to render the bottom edge of the gauge face.
                * @remarks
                * Note: If the radius of the gauge is too large to fit within the rectangle defined by the width and height less the
                * specified margins, and the radius is set to the default value of "auto," Wijmo automatically resizes the gauge to fit.
                */
                this.marginBottom = 0;
                /**
                * Sets a value in pixels that indicates where to render the left edge of the gauge face.
                * @remarks
                * Note: If the radius of the gauge is too large to fit within the rectangle defined by the width and height less the
                * specified margins, and the radius is set to the default value of "auto," Wijmo automatically resizes the gauge to fit.
                */
                this.marginLeft = 0;
                /**
                * Allows you to create an array of ranges to highlight where values fall within the gauge.
                *@remarks
                * For example, a red range, a yellow range, and a green range. Each range is drawn in the form of a curved bar.
                * You can control every aspect of each range with the settings detailed below.
                * Options available for each range include:
                *		startWidth – Sets the thickness of the left side of the range bar in pixels.
                *		endWidth – Sets the thickness of the right side of the range bar in pixels.
                *		startValue – Sets the value at which to begin drawing the range bar.This value must fall between the max and min values you set for the gauge.
                *		endValue – Sets the value at which to end the range bar.This value must fall between the max and min values you set for the gauge.
                *		startDistance – Sets the distance from the center of the gauge to draw the left side of the range bar.
                *		endDistance – Sets the distance from the center of the gauge to draw the right side of the range bar.
                *		style – Sets the colors to use in drawing the range bar with the following options:
                */
                this.ranges = [];
                /**
                * Determines whether to render the gauge in reverse order, with the numbering going from highest to lowest.
                */
                this.isInverted = false;
                /**
                * Fires before the value changes, this event can be called.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {IGaugeEventArgs} data Information about an event
                */
                this.beforeValueChanged = null;
                /**
                * Fires before the value changes, this event can be called.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {IGaugeEventArgs} data Information about an event
                */
                this.valueChanged = null;
                /**
                * Fires before the canvas is painted. This event can be cancelled. "return false;" to cancel the event.
                * @event
                */
                this.painted = null;
            }
            return wijgauge_options;
        })();

        wijgauge.prototype.options = $.extend({}, wijmo.wijmoWidget.prototype.options, new wijgauge_options());
    })(wijmo.gauge || (wijmo.gauge = {}));
    var gauge = wijmo.gauge;
})(wijmo || (wijmo = {}));

;
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /// <reference path="../wijgauge/jquery.wijmo.wijgauge.ts"/>
    /*globals $, Raphael, jQuery, document, window*/
    /*
    * Depends:
    *  jQuery.1.5.1.js
    *  jQuery.ui.core.js
    *  jQuery.ui.widget.js
    *	raphael.js
    *  jQuery.wijmo.rahpael.js
    *  jquery.wijmo.wijgauge.js
    */
    (function (gauge) {
        /**
        * @widget
        */
        var wijlineargauge = (function (_super) {
            __extends(wijlineargauge, _super);
            function wijlineargauge() {
                _super.apply(this, arguments);
            }
            wijlineargauge.prototype._setDefaultWidth = function () {
                var o = this.options;
                o.width = o.orientation === "horizontal" ? 310 : 70;
            };

            wijlineargauge.prototype._setDefaultHeight = function () {
                var o = this.options;
                o.height = o.orientation === "horizontal" ? 70 : 310;
            };

            wijlineargauge.prototype._set_orientation = function () {
                var self = this;
                self._setDefaultWidth();
                self._setDefaultHeight();
                self.redraw();
            };

            wijlineargauge.prototype._set_xAxisLocation = function () {
                this.redraw();
            };

            wijlineargauge.prototype._set_xAxisLength = function () {
                this.redraw();
            };

            wijlineargauge.prototype._set_yAxisLocation = function () {
                this.redraw();
            };

            wijlineargauge.prototype._clearState = function () {
                _super.prototype._clearState.call(this);
                if (this.markBbox) {
                    this.markBbox = null;
                }
            };

            wijlineargauge.prototype._create = function () {
                _super.prototype._create.call(this);
                this.element.addClass(this.options.wijCSS.linearGauge);
            };

            wijlineargauge.prototype._paintLabel = function (value, labelInfo) {
                var self = this, o = self.options, format = labelInfo.format, style = labelInfo.style, offset = labelInfo.offset, text = value, markOption = self.options.tickMajor, position = markOption.position || "inside", point, textEle, markBbox, labelBBox;

                if (format !== "") {
                    text = gauge.GaugeUtil.formatString(value, format);
                }
                markBbox = self._getMarkerBbox();
                labelBBox = self._getLabelBBox(text);
                point = self._valueToPoint(value, 0);

                if (o.orientation === "horizontal") {
                    if (position === "inside") {
                        point.y = markBbox.y - labelBBox.height;
                    } else {
                        point.y = markBbox.y + markBbox.height + labelBBox.height / 2;
                    }

                    point.y += offset;
                } else {
                    if (position === "inside") {
                        point.x = markBbox.x - labelBBox.width / 2;
                    } else {
                        point.x = markBbox.x + markBbox.width + labelBBox.width / 2;
                    }

                    point.x += offset;
                }
                textEle = self.canvas.text(point.x, point.y, text);
                textEle.attr(style);
                $.wijraphael.addClass($(textEle.node), o.wijCSS.linearGaugeLabel);
                return textEle;
            };

            wijlineargauge.prototype._getLabelBBox = function (value) {
                var self = this, o = self.options, text, bbox;

                text = self.canvas.text(0, 0, value);
                text.attr(o.gaugeLableStyle);
                bbox = text.wijGetBBox();
                text.wijRemove();
                return bbox;
            };

            wijlineargauge.prototype._getMarkerBbox = function () {
                var self = this, o = self.options, markOption = o.tickMajor, markEle;

                if (!self.markBbox) {
                    markEle = self._paintMark(0, markOption);
                    self.markBbox = markEle.wijGetBBox();
                    markEle.wijRemove();
                }
                return self.markBbox;
            };

            wijlineargauge.prototype._paintMark = function (value, opt, isMajor) {
                var self = this, o = self.options, marker = opt.marker || "rect", baseLength = marker === "rect" ? 5 : 2, point = self._valueToPoint(value, 0), position = opt.position || "inside", offset = opt.offset || 0, width = isMajor ? 2 : 1, length, markEle, style = $.extend({}, opt.style);

                length = baseLength * opt.factor;
                if ($.isFunction(marker)) {
                    return marker.call(self, self.canvas, point, o);
                } else {
                    if (marker === "cross") {
                        style.stroke = style.fill;
                    }
                    if (o.orientation === "horizontal") {
                        markEle = gauge.GaugeUtil.paintMarker(self.canvas, marker, point.x, point.y, width, length, true);
                    } else {
                        markEle = gauge.GaugeUtil.paintMarker(self.canvas, marker, point.x, point.y, length, width);
                    }
                }
                markEle.attr(style);
                $.wijraphael.addClass($(markEle.node), o.wijCSS.linearGaugeMarker);
                self._applyPosition(markEle, position, offset, value);
                return markEle;
            };

            wijlineargauge.prototype._applyPosition = function (ele, position, offset, value) {
                var left = 0, top = 0, self = this, isHorizontal = self.options.orientation === "horizontal", bbox = ele.wijGetBBox();
                switch (position) {
                    case "inside":
                        if (isHorizontal) {
                            top -= bbox.width / 2 + offset;
                        } else {
                            left -= bbox.width / 2 + offset;
                        }
                        break;
                    case "outside":
                        if (isHorizontal) {
                            top += bbox.width / 2 + offset;
                        } else {
                            left += bbox.width / 2 + offset;
                        }
                        break;
                    case "center":
                        if (isHorizontal) {
                            top -= offset;
                        } else {
                            left -= offset;
                        }
                        break;
                    default:
                        break;
                }

                ele.attr("transform", "t" + left + "," + top);
            };

            wijlineargauge.prototype._paintFace = function () {
                var self = this, face, o = self.options, width = self._innerBbox.width, height = self._innerBbox.height, left = self._innerBbox.left, top = self._innerBbox.top, ui = {
                    width: width,
                    height: height,
                    x: left,
                    y: top,
                    canvas: self.canvas
                };
                if (o.face && o.face.template && $.isFunction(o.face.template)) {
                    return o.face.template.call(self, ui);
                }
                face = self.canvas.rect(left, top, width, height, 5);
                if (o.face && o.face.style) {
                    face.attr(o.face.style);
                }
                $.wijraphael.addClass($(face.node), o.wijCSS.linearGaugeFace);
                return face;
            };

            wijlineargauge.prototype._paintPointer = function () {
                var self = this, o = self.options, point = self._valueToPoint(o.min, 0), width = self._innerBbox.width, height = self._innerBbox.height, left = self._innerBbox.left, top = self._innerBbox.top, pointerInfo = o.pointer, pointer, length, offset, base;

                if (!pointerInfo.visible) {
                    return;
                }

                base = o.orientation === "horizontal" ? height : width;
                offset = base * pointerInfo.offset;
                length = base * pointerInfo.length;

                if (pointerInfo.template && $.isFunction(pointerInfo.template)) {
                    pointer = pointerInfo.template.call(self.canvas, point, $.extend({}, o.pointer, {
                        offset: offset,
                        length: length,
                        gaugeBBox: self._innerBbox
                    }));
                } else {
                    if (o.orientation === "horizontal") {
                        if (pointerInfo.shape === "rect") {
                            pointer = self.canvas.rect(point.x - pointerInfo.width / 2, height - length - offset + top, pointerInfo.width, length);
                        } else {
                            pointer = self.canvas.isoTri(point.x, height - length - offset + top, pointerInfo.width, length, 3 /* north */);
                        }
                    } else {
                        if (pointerInfo.shape === "rect") {
                            pointer = self.canvas.rect(width - length - offset + left, point.y - pointerInfo.width / 2, length, pointerInfo.width);
                        } else {
                            pointer = self.canvas.isoTri(width - length - offset + left, point.y - pointerInfo.width / 2, length, pointerInfo.width);
                        }
                    }
                    pointer.attr(pointerInfo.style);
                }
                $.wijraphael.addClass($(pointer.node), o.wijCSS.linearGaugePointer);
                self.pointer = pointer;
            };

            wijlineargauge.prototype._setPointer = function () {
                var self = this, o = self.options;

                if (!self.pointer) {
                    return;
                }
                _super.prototype._setPointer.call(this);
                self._setLinearPointer(o.value);
            };

            wijlineargauge.prototype._setLinearPointer = function (value) {
                var self = this, o = self.options, startPoint = self._valueToPoint(o.min, 0), endPoint = self._valueToPoint(value, 0), animation = o.animation, translation = { x: 0, y: 0 }, transform;

                // if use the transform("..."), the memeroy may leak.
                // Using the absolute path instead of it.
                if (o.orientation === "horizontal") {
                    translation.x = endPoint.x - startPoint.x;
                } else {
                    translation.y = endPoint.y - startPoint.y;
                }

                transform = "t" + translation.x + "," + translation.y;
                if (animation.enabled) {
                    self.pointer.stop().wijAnimate({
                        transform: transform
                    }, animation.duration, animation.easing);
                } else {
                    self.pointer.attr("transform", transform);
                }
            };

            wijlineargauge.prototype._minScreenPoint = function (yOffset) {
                var self = this, o = self.options, width = self._innerBbox.width, height = self._innerBbox.height, left = self._innerBbox.left, top = self._innerBbox.top, totalOffset = o.yAxisLocation + yOffset;
                if (o.orientation === "horizontal") {
                    return {
                        x: width * o.xAxisLocation + left,
                        y: height * totalOffset + top
                    };
                } else {
                    return {
                        x: width * totalOffset + left,
                        y: height * (1 - o.xAxisLocation) + top
                    };
                }
            };

            wijlineargauge.prototype._maxScreenPoint = function (yOffset) {
                var self = this, o = self.options, width = self._innerBbox.width, height = self._innerBbox.height, left = self._innerBbox.left, top = self._innerBbox.top, totalOffset = o.yAxisLocation + yOffset, end = o.xAxisLocation + o.xAxisLength;
                if (o.orientation === "horizontal") {
                    return { x: width * end + left, y: height * totalOffset + top };
                } else {
                    return { x: width * totalOffset + left, y: height * (1 - end) + top };
                }
            };

            wijlineargauge.prototype._paintRange = function (range) {
                var self = this, o = self.options, calculateFrom = isNaN(range.startValue) ? 0 : range.startValue, calculateTo = isNaN(range.endValue) ? 0 : range.endValue, calculateStartWidth = isNaN(range.startWidth) ? (isNaN(range.width) ? 0 : range.width) : range.startWidth, calculateEndWidth = isNaN(range.endWidth) ? (isNaN(range.width) ? 0 : range.width) : range.endWidth, startDistance = range.startDistance || 0, endDistance = range.endDistance || 0, coercedFrom, coercedTo;

                if (calculateFrom !== calculateTo) {
                    if (calculateTo > calculateFrom) {
                        coercedFrom = Math.max(calculateFrom, o.min);
                        coercedTo = Math.min(o.max, calculateTo);
                    } else {
                        coercedFrom = Math.max(o.min, calculateTo);
                        coercedTo = Math.min(o.max, calculateFrom);
                    }
                    self._drawRange(coercedFrom, coercedTo, startDistance, endDistance, calculateStartWidth, calculateEndWidth, range);
                }
            };

            wijlineargauge.prototype._drawRange = function (coercedFrom, coercedTo, startDistance, endDistance, calculateStartWidth, calculateEndWidth, range) {
                var self = this, o = self.options, orientation = o.orientation, width = self._innerBbox.width, height = self._innerBbox.height, left = self._innerBbox.left, top = self._innerBbox.top, p1 = self._valueToPoint(coercedFrom, 0), p2 = self._valueToPoint(coercedTo, 0), p3, p4, arrPath, rangeEl, startWidth, endWidth;

                if (orientation === "horizontal") {
                    startWidth = calculateStartWidth * height;
                    endWidth = calculateEndWidth * height;

                    if (startDistance !== 0) {
                        p1.y = startDistance * height + top;
                    }
                    if (endDistance !== 0) {
                        p2.y = endDistance * height + top;
                    }

                    p3 = { x: p1.x, y: p1.y - startWidth };
                    p4 = { x: p2.x, y: p2.y - endWidth };
                } else {
                    startWidth = calculateStartWidth * width;
                    endWidth = calculateEndWidth * width;
                    if (startDistance !== 0) {
                        p1.x = startDistance * width + left;
                    }
                    if (endDistance !== 0) {
                        p2.x = endDistance * width + left;
                    }
                    p3 = { x: p1.x - startWidth, y: p1.y };
                    p4 = { x: p2.x - endWidth, y: p2.y };
                }

                arrPath = [
                    "M", p1.x, p1.y, "L", p2.x, p2.y,
                    "L", p4.x, p4.y, "L", p3.x, p3.y, "Z"];
                rangeEl = self.canvas.path(arrPath.join(" "));
                rangeEl.attr(range.style);
                $.wijraphael.addClass($(rangeEl.node), o.wijCSS.linearGaugeRange);
                self.ranges.push(rangeEl);
            };

            wijlineargauge.prototype._valueToPoint = function (value, offset) {
                var self = this, o = self.options, isInverted = o.isInverted, alpha, minPoint, maxPoint;

                if (o.max === o.min) {
                    return { x: 0, y: 0 };
                }

                alpha = self._valueToLogical(value);
                minPoint = self._minScreenPoint(offset);
                maxPoint = self._maxScreenPoint(offset);

                if (isInverted) {
                    return {
                        x: minPoint.x * alpha + maxPoint.x * (1 - alpha),
                        y: minPoint.y * alpha + maxPoint.y * (1 - alpha)
                    };
                } else {
                    return {
                        x: minPoint.x * (1 - alpha) + maxPoint.x * alpha,
                        y: minPoint.y * (1 - alpha) + maxPoint.y * alpha
                    };
                }
            };

            /**
            * Remove the functionality completely. This will return the element back to its pre-init state.
            */
            wijlineargauge.prototype.destroy = function () {
                _super.prototype.destroy.call(this);
                this.element.removeClass(this.options.wijCSS.linearGauge);
            };
            return wijlineargauge;
        })(gauge.wijgauge);
        gauge.wijlineargauge = wijlineargauge;

        wijlineargauge.prototype.widgetEventPrefix = "wijlineargauge";

        var wijlineargauge_options = (function () {
            function wijlineargauge_options() {
                /**
                * @ignore
                */
                this.initSelector = ":jqmData(role='wijlineargauge')";
                /**
                * @ignore
                */
                this.wijCSS = {
                    linearGauge: "wijmo-wijlineargauge",
                    linearGaugeLabel: "wijmo-wijlineargauge-label",
                    linearGaugeMarker: "wijmo-wijlineargauge-mark",
                    linearGaugeFace: "wijmo-wijlineargauge-face",
                    linearGaugePointer: "wijmo-wijlineargauge-pointer",
                    linearGaugeRange: "wijmo-wijlineargauge-range"
                };
                /**
                * Sets the orientation of the gauge, with a setting of horizontal showing values across the gauge from left to right, and a
                * setting of vertical showing values along the gauge from top to bottom.
                * @example
                * // This sample shows how to create vertical linear gauge.
                *    $(document).ready(function () {
                *        $("#lineargauge1").wijlineargauge({
                *			value: 31,
                *			orientation: "vertical"
                *		});
                *	});
                */
                this.orientation = "horizontal";
                /**
                * Sets the starting location of the X axis as a percentage of the width of the gauge.
                * @remarks
                * Note: By default, the xAxisLength option is set to draw the X axis 80% of the width the gauge, so if you want to center
                * the axis within the gauge, you must also adjust that option.
                */
                this.xAxisLocation = 0.1;
                /**
                * Sets the length of the X axis as a percentage of the width of the gauge.
                * @remarks
                * Note: By default, the xAxisLocation option is set to begin the X axis 10% of the way across from the left edge of the
                * gauge, so if you want to use a higher ratio for the xAxisLength, you must also adjust that option.
                */
                this.xAxisLength = 0.8;
                /**
                * Sets the base vertical location of the pointer, tick marks and labels on the X axis as a percentage of the height of the gauge.
                * @remarks
                * Note that there is no actual Y axis in the LinearGauge. By default, it is centered in the gauge.A setting of 0.8 moves the
                * pointer, tick marks, and labels toward the bottom edge of the gauge.
                */
                this.yAxisLocation = 0.5;
                /**
                * Sets the width of the gauge area in pixels.
                * @type {number|string}
                */
                this.width = "auto";
                /**
                * Sets the height of the gauge area in pixels.
                * @type {number|string}
                */
                this.height = "auto";
                /**
                * Creates an object that includes all settings of the gauge pointer.
                */
                this.pointer = {
                    /**
                    * Sets the length of the pointer as a percentage of the height of the gauge (or the width, if the orientation is set
                    * to vertical).
                    * @remarks
                    * You can set the length to be greater than the height (or width).
                    */
                    length: 0.5,
                    /**
                    * Sets the width of the pointer in pixels.
                    */
                    width: 4,
                    /**
                    * Sets the percentage of the height of the gauge to move the pointer upward (or of the width if the orientation is
                    * vertical) from the bottom (or right) edge of the gauge.
                    */
                    offset: 0,
                    /**
                    * A value that indicates whether to show the pointer.
                    */
                    visible: true,
                    /**
                    * A JavaScript callback value that returns a Raphael element that draws the pointer. Use this option to customize
                    * the pointer.
                    * @remarks
                    * In order to use the template, you must know how to draw Raphael graphics. For more information, see the Raphael documentation.
                    * The pointer template's callback contains two arguments:
                    *		startLocation -- The starting point from which to draw the pointer. This argument is defined by x and y coordinates.
                    *		pointerInfo -- A JSON object that extends the gauge's pointer options:
                    *			offset -- Sets the percentage of the pointer that is shoved upward from the bottom edge.
                    *			length -- Sets the absolute value in pixels of the length of the pointer.
                    *			gaugeBBox -- An object that sets the bounding box of the gauge, as defined by x and y coordinates and width and height options.
                    */
                    template: null,
                    shape: "tri",
                    style: {
                        fill: "#1E395B",
                        stroke: "#1E395B"
                    }
                };
                /**
                * It is a value in pixels that indicates where to render the left edge of the gauge markers, it may help to also change
                * the width option.
                */
                this.marginLeft = 5;
                /**
                * It is a value in pixels that indicates where to render the top edge of the gauge face.
                * @remarks
                * In order to change the margin settings by more than a few pixels without clipping the gauge face edges, it may help
                * to also change the height property.
                */
                this.marginTop = 5;
                /**
                * It is a value in pixels that indicates where to render the right edge of the gauge face.
                * @remarks
                * In order to change the margin settings without compressing the gauge markers, it may help to also change the width option.
                */
                this.marginRight = 5;
                /**
                * It is a value in pixels that indicates where to render the bottom edge of the gauge face.
                * @remarks
                * In order to change the margin settings by more than a few pixels without clipping the gauge face edges, it may help to
                * also change the height property
                */
                this.marginBottom = 5;
            }
            return wijlineargauge_options;
        })();

        wijlineargauge.prototype.options = $.extend(true, {}, gauge.wijgauge.prototype.options, new wijlineargauge_options());

        $.wijmo.registerWidget("wijlineargauge", wijlineargauge.prototype);
    })(wijmo.gauge || (wijmo.gauge = {}));
    var gauge = wijmo.gauge;
})(wijmo || (wijmo = {}));

;
/// <reference path="../wijgauge/jquery.wijmo.wijgauge.ts"/>
/*globals $, Raphael, jQuery, document, window*/
/*
* Depends:
*  jQuery.1.5.1.js
*  jQuery.ui.core.js
*  jQuery.ui.widget.js
*	raphael.js
*	globalize.min.js
*	jquery.wijmo.raphael.js
*/
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    (function (gauge) {
        var _zeroOffset = 180, interpMinPoints = 9, interJump = 5;

        /**
        * @widget
        */
        var wijradialgauge = (function (_super) {
            __extends(wijradialgauge, _super);
            function wijradialgauge() {
                _super.apply(this, arguments);
            }
            wijradialgauge.prototype._create = function () {
                var self = this;
                _super.prototype._create.call(this);
                self.element.addClass(this.options.wijCSS.radialGauge);
            };

            wijradialgauge.prototype._set_radius = function () {
                var self = this;
                self._autoCalculate();
                self.redraw();
            };

            wijradialgauge.prototype._set_startAngle = function () {
                var self = this;
                self._redrawMarksAndLabels();
                self._setPointer();
            };

            wijradialgauge.prototype._set_sweepAngle = function (value) {
                var self = this;
                if (value > 360) {
                    self.options.endAngle = 360;
                }
                self._redrawMarksAndLabels();
                self._setPointer();
            };

            wijradialgauge.prototype._set_width = function () {
                var self = this;
                self._autoCalculate();
                _super.prototype._set_width.call(this);
            };

            wijradialgauge.prototype._set_height = function () {
                var self = this;
                self._autoCalculate();
                _super.prototype._set_height.call(this);
            };

            wijradialgauge.prototype._set_origin = function () {
                var self = this;
                self._autoCalculate();
            };

            wijradialgauge.prototype._set_cap = function () {
                var self = this;
                self._removeCap();
                self._paintCap();
                self._positionCapWithBehindPointer();
            };

            wijradialgauge.prototype._removeCap = function () {
                var self = this;
                if (self.cap) {
                    self._destroyRaphaelElement(self.cap);
                    self.cap = null;
                }
            };

            wijradialgauge.prototype._set_pointer = function () {
                var self = this;
                self._removePointer();
                self._paintPointerExcludeCap();
                self._setPointer();
                self._positionCapWithBehindPointer();
            };

            wijradialgauge.prototype._clearState = function () {
                _super.prototype._clearState.call(this);
                this.markBbox = null;
            };

            wijradialgauge.prototype._clearElements = function () {
                _super.prototype._clearElements.call(this);
                this._removeCap();
            };

            wijradialgauge.prototype._valueToAngleIncludeOffset = function (value) {
                return gauge.GaugeUtil.mod360(this._valueToAngle(value) + _zeroOffset);
            };

            wijradialgauge.prototype._valueToAngle = function (value) {
                var self = this, alpha = self._valueToLogical(value);
                return self._logicalToAngle(alpha);
            };

            wijradialgauge.prototype._angleToValue = function (angle) {
                var self = this, alpha = self._angleToLogical(angle);
                return self._logicalToValue(alpha);
            };

            wijradialgauge.prototype._logicalToAngle = function (alpha) {
                var self = this, o = self.options, startAngle = o.startAngle, sweepAngle = o.sweepAngle, isInverted = o.isInverted;

                if (isInverted) {
                    return startAngle * alpha + (startAngle + sweepAngle) * (1 - alpha);
                } else {
                    return startAngle * (1 - alpha) + (startAngle + sweepAngle) * alpha;
                }
            };

            wijradialgauge.prototype._angleToLogical = function (angle) {
                var self = this, o = self.options, startAngle = o.startAngle, isInverted = o.isInverted, relativeAngle = gauge.GaugeUtil.mod360(angle - startAngle), absSweepAngle = o.sweepAngle, overflow, underflow;

                if (absSweepAngle === 0 || relativeAngle === 0) {
                    return isInverted ? 1 : 0;
                }
                if (absSweepAngle < 0) {
                    relativeAngle = 360 - relativeAngle;
                    absSweepAngle = -absSweepAngle;
                }
                overflow = relativeAngle - absSweepAngle;
                if (overflow > 0) {
                    underflow = 360 - relativeAngle;
                    return overflow < underflow ? 1 : 0;
                }
                if (isInverted) {
                    return 1 - relativeAngle / absSweepAngle;
                } else {
                    return relativeAngle / absSweepAngle;
                }
            };

            wijradialgauge.prototype._generatePoints = function (fromAngle, toAngle, fromLength, toLength) {
                var self = this, isInverted = self.options.isInverted, max = parseInt((interpMinPoints + interpMinPoints * (Math.abs(parseInt((toAngle - fromAngle).toString(), 10)) / (interpMinPoints * interJump))).toString(), 10), points = [], alpha, length, value, angle, i;

                for (i = 0; i < max; i++) {
                    alpha = i / (max - 1);
                    length = fromLength + (toLength - fromLength) * alpha;
                    angle = fromAngle + (toAngle - fromAngle) * alpha;
                    value = self._angleToValue(angle);
                    points.push(self._valueToPoint(value, length));
                }
                return points;
            };

            wijradialgauge.prototype._valueToPoint = function (value, offset) {
                var self = this, angle = self._valueToAngleIncludeOffset(value) * Math.PI / 180, radius = offset;
                return {
                    x: radius * Math.cos(angle),
                    y: radius * Math.sin(angle)
                };
            };

            wijradialgauge.prototype._pointToValue = function (point) {
                var angle = gauge.GaugeUtil.mod360(Math.atan2(point.x, -point.y) * 180 / Math.PI);
                return this._angleToValue(angle);
            };

            wijradialgauge.prototype._radiusScreen = function (offset) {
                return Math.max(this.options.radius * offset, 0);
            };

            wijradialgauge.prototype._autoCalculate = function () {
                var self = this, o = self.options, width = o.width, height = o.height, majorMarkWidth, minorMarkWidth, labelWidth, maxText = gauge.GaugeUtil.formatString(o.max, o.labels.format), offset = 0, faceBorder, innerHeight = height - o.marginTop - o.marginBottom, innerWidth = width - o.marginLeft - o.marginRight;

                self.centerPoint = {
                    x: o.marginLeft + innerWidth * o.origin.x,
                    y: o.marginTop + innerHeight * o.origin.y
                };
                self.radius = o.radius;
                if (o.radius === "auto") {
                    self.faceRadius = Math.min(innerWidth, innerHeight) / 2;
                    faceBorder = self._getFaceBorder();
                    self.faceRadius -= faceBorder;

                    majorMarkWidth = self._getMarkerbbox(o.tickMajor).width;
                    minorMarkWidth = self._getMarkerbbox(o.tickMinor).width;
                    labelWidth = self._getLabelBBox(maxText).width;
                    if (o.tickMajor.position === "center") {
                        offset -= majorMarkWidth / 2;
                        offset -= labelWidth;
                    } else if (o.tickMajor.position === "outside") {
                        offset -= majorMarkWidth;
                        offset -= labelWidth;
                    }
                    if (o.tickMinor.position === "center") {
                        offset = Math.min(offset, -minorMarkWidth / 2);
                    } else if (o.tickMinor.position === "outside") {
                        offset = Math.min(offset, -minorMarkWidth);
                    }
                    self.radius = self.faceRadius + offset;
                    if (o.tickMajor.position !== "inside") {
                        self.faceRadius += offset;
                    }
                }
            };

            wijradialgauge.prototype._getFaceBorder = function () {
                var self = this, face = self._paintFace(), width = face.attr("stroke-width") || 1;

                if (face.type === "set") {
                    width = face[0].attr("stroke-width") || 1;
                }
                face.wijRemove();
                return width;
            };

            wijradialgauge.prototype._getMaxRangeWidth = function () {
                var self = this, o = self.options, maxWidth = 0;
                $.each(o.ranges, function (i, n) {
                    maxWidth = Math.max(maxWidth, n.width || 0, n.startWidth || 0, n.endWidth || 0);
                });
                return maxWidth;
            };

            wijradialgauge.prototype._getMarkerbbox = function (opt) {
                var self = this, mark = self._paintMarkEle(opt), bbox = mark.wijGetBBox();
                mark.wijRemove();
                return { width: bbox.width, height: bbox.height };
            };

            wijradialgauge.prototype._paintMark = function (value, opt, isMajor) {
                var self = this, mark, position = opt.position || "inside", offset = opt.offset || 0;

                mark = self._paintMarkEle(opt);
                mark.attr(opt.style);
                $.wijraphael.addClass($(mark.node), self.options.wijCSS.radialGaugeMarker);
                $(mark.node).data("value", value);
                self._applyAlignment(mark, position, offset);
                self._setMarkValue(value, mark);
                return mark;
            };

            wijradialgauge.prototype._applyAlignment = function (ele, alignment, offset) {
                if (!ele) {
                    return;
                }
                var Bbox = ele.wijGetBBox(), halfWidth = Bbox.width / 2, left = 0;

                switch (alignment) {
                    case "outside":
                        left -= (halfWidth + offset);
                        break;
                    case "inside":
                        left += (halfWidth + offset);
                        break;
                }
                ele.transform("t" + left + "," + 0);
            };

            wijradialgauge.prototype._paintMarkEle = function (opt) {
                var self = this, o = self.options, startLocation = {
                    x: self.centerPoint.x - self.radius,
                    y: self.centerPoint.y
                }, marker = opt.marker || "circle", baseLength = marker === "rect" ? 5 : 2, width = 2, length, strokeWidth = opt.style["stroke-width"] || 0;

                if (marker === "tri" || marker === "invertedTri") {
                    baseLength = 5;
                    width = 3;
                }

                if (marker === "cross") {
                    opt.style.fill = opt.style.stroke || opt.style.fill;
                }

                if (isNaN(startLocation.x)) {
                    startLocation.x = 0;
                }

                length = baseLength * opt.factor;

                width += strokeWidth * 2;
                length += strokeWidth * 2;

                if ($.isFunction(marker)) {
                    return marker.call(self, self.canvas, startLocation, o);
                } else {
                    if (marker === "tri") {
                        return self.canvas.isoTri(startLocation.x, startLocation.y, length, width, 1 /* west */);
                    } else if (marker === "invertedTri") {
                        return self.canvas.isoTri(startLocation.x, startLocation.y, length, width, 0 /* east */);
                    }
                    return gauge.GaugeUtil.paintMarker(self.canvas, marker, startLocation.x, startLocation.y, length, width, true);
                }
            };

            wijradialgauge.prototype._setMarkValue = function (value, mark) {
                var self = this, angle = self._valueToAngle(value);

                mark.transform(Raphael.format("r{0},{1},{2}...", angle, self.centerPoint.x, self.centerPoint.y));
            };

            wijradialgauge.prototype._paintLabel = function (value, labelInfo) {
                var self = this, angle = self._valueToAngle(value), format = labelInfo.format, style = labelInfo.style, offset = labelInfo.offset, text = value.toString(), markOption = self.options.tickMajor, position = markOption.position || "inside", point, textEle, markBbox, newRadius, maxLabelBBox;

                if (format !== "") {
                    text = gauge.GaugeUtil.formatString(value, format);
                }

                markBbox = self._getMarkerBbox();
                maxLabelBBox = self._getLabelBBox(text);
                switch (position) {
                    case "inside":
                        newRadius = markBbox.x + markBbox.width + maxLabelBBox.width / 2;
                        break;
                    case "outside":
                        newRadius = markBbox.x - maxLabelBBox.width / 2;
                        break;
                    default:
                        newRadius = markBbox.x - maxLabelBBox.width / 2;
                        break;
                }
                newRadius = self.centerPoint.x - newRadius + offset;

                point = gauge.GaugeUtil.getPositionByAngle(self.centerPoint.x, self.centerPoint.y, newRadius, angle);
                textEle = self.canvas.text(point.x, point.y, text);
                textEle.attr(style);
                $.wijraphael.addClass($(textEle.node), self.options.wijCSS.radialGaugeLabel);
                return textEle;
            };

            wijradialgauge.prototype._getLabelBBox = function (value) {
                var self = this, o = self.options, text, bbox;

                text = self.canvas.text(0, 0, value);
                text.attr(o.gaugeLableStyle);
                bbox = text.wijGetBBox();
                text.wijRemove();
                return bbox;
            };

            wijradialgauge.prototype._getMarkerBbox = function () {
                var self = this, o = self.options, markOption = o.tickMajor, markEle;

                if (!self.markBbox) {
                    markEle = self._paintMarkEle(markOption);
                    self._applyAlignment(markEle, markOption.position, markOption.offset || 0);
                    self.markBbox = markEle.wijGetBBox();
                    markEle.wijRemove();
                }
                return self.markBbox;
            };

            wijradialgauge.prototype._paintFace = function () {
                var self = this, o = self.options, r = Math.min(o.width, o.height) / 2, face, ui;
                if (self.faceRadius) {
                    r = self.faceRadius;
                }

                if (o.face && o.face.template && $.isFunction(o.face.template)) {
                    ui = {
                        canvas: self.canvas,
                        r: r,
                        origin: { x: self.centerPoint.x, y: self.centerPoint.y }
                    };
                    return o.face.template.call(self, ui);
                }

                face = self.canvas.circle(self.centerPoint.x, self.centerPoint.y, r);
                if (o.face && o.face.style) {
                    face.attr(o.face.style);
                }
                $.wijraphael.addClass($(face.node), o.wijCSS.radialGaugeFace);
                return face;
            };

            wijradialgauge.prototype._paintPointer = function () {
                var self = this, o = self.options;
                self._paintPointerExcludeCap();
                if (o.cap && o.cap.visible) {
                    self._paintCap();
                    self._positionCapWithBehindPointer();
                }
            };

            wijradialgauge.prototype._paintPointerExcludeCap = function () {
                var self = this, o = self.options, pointerInfo = o.pointer, length = self.radius * pointerInfo.length, startLocation = {
                    x: self.centerPoint.x - length + pointerInfo.offset * self.radius,
                    y: self.centerPoint.y - pointerInfo.width / 2
                }, point;

                if (!pointerInfo.visible) {
                    return;
                }

                if (pointerInfo.template && $.isFunction(pointerInfo.template)) {
                    point = pointerInfo.template.call(self.canvas, startLocation, $.extend({}, pointerInfo, { length: length }));
                } else {
                    if (pointerInfo.shape === "rect") {
                        point = self.canvas.rect(startLocation.x - pointerInfo.width / 2, startLocation.y, length, pointerInfo.width);
                    } else {
                        point = self.canvas.isoTri(startLocation.x - pointerInfo.width / 2, startLocation.y, length, pointerInfo.width);
                    }
                    if (pointerInfo.style) {
                        point.attr(pointerInfo.style);
                    }
                }

                self.pointer = point;
                $.wijraphael.addClass($(point.node), o.wijCSS.radialGaugePointer);
            };

            wijradialgauge.prototype._paintCap = function () {
                var self = this, o = self.options, capInfo = o.cap, ui;

                if (!capInfo) {
                    return;
                }
                if (capInfo.template && $.isFunction(capInfo.template)) {
                    ui = {
                        canvas: self.canvas,
                        origin: { x: self.centerPoint.x, y: self.centerPoint.y }
                    };
                    return capInfo.template.call(self, ui);
                }

                self.cap = self.canvas.circle(self.centerPoint.x, self.centerPoint.y, capInfo.radius);
                if (capInfo.style) {
                    self.cap.attr(capInfo.style);
                }
                $.wijraphael.addClass($(self.cap.node), o.wijCSS.radialGaugeCap);
            };

            wijradialgauge.prototype._positionCapWithBehindPointer = function () {
                var self = this, o = self.options;
                if (o.cap && o.cap.visible) {
                    if (!o.cap.behindPointer) {
                        if (self.cap) {
                            self.cap.toFront();
                        }
                    } else {
                        if (self.pointer) {
                            self.pointer.toFront();
                        }
                    }
                }
            };

            wijradialgauge.prototype._paintRange = function (range) {
                var self = this, o = self.options, calculateFrom = isNaN(range.startValue) ? 0 : range.startValue, calculateTo = isNaN(range.endValue) ? 0 : range.endValue, calculateStartWidth = isNaN(range.startWidth) ? (isNaN(range.width) ? 0 : range.width) : range.startWidth, calculateEndWidth = isNaN(range.endWidth) ? (isNaN(range.width) ? 0 : range.width) : range.endWidth, startDistance = range.startDistance || 1, endDistance = range.endDistance || 1, coercedFrom, coercedTo;

                if (calculateFrom !== calculateTo) {
                    if (calculateTo > calculateFrom) {
                        coercedFrom = Math.max(calculateFrom, o.min);
                        coercedTo = Math.min(o.max, calculateTo);
                    } else {
                        coercedFrom = Math.max(o.min, calculateTo);
                        coercedTo = Math.min(o.max, calculateFrom);
                    }
                    startDistance = startDistance * self.radius;
                    endDistance = endDistance * self.radius;
                    self._drawRange(coercedFrom, coercedTo, startDistance, endDistance, calculateStartWidth, calculateEndWidth, range);
                }
            };

            // fix the issue 42503, in the previous version, here will use math.round to convert the float value to int value, and in this case,
            // concat the points, the path looks not smooth. here I convert the float value to two decimal.
            wijradialgauge.prototype._drawRange = function (from, to, startDistance, endDistance, startWidth, endWidth, range) {
                var self = this, startAngle = self._valueToAngle(from), endAngle = self._valueToAngle(to), outerPointers = self._generatePoints(startAngle, endAngle, startWidth + startDistance, endWidth + endDistance), innerPointers = self._generatePoints(startAngle, endAngle, startDistance, endDistance), i, rangeEl, path = [];

                $.each(outerPointers, function (idx, n) {
                    path.push(idx === 0 ? "M" : "L");
                    path.push($.round(n.x + self.centerPoint.x), ",", $.round(n.y + self.centerPoint.y));
                });

                for (i = innerPointers.length - 1; i >= 0; i--) {
                    path.push("L", $.round(innerPointers[i].x + self.centerPoint.x), ",", $.round(innerPointers[i].y + self.centerPoint.y));
                }
                path.push("Z");

                rangeEl = self.canvas.path(path.join());
                rangeEl.attr(range.style);
                self.ranges.push(rangeEl);
                $.wijraphael.addClass($(rangeEl.node), self.options.wijCSS.radialGaugeRange);
            };

            wijradialgauge.prototype._setOffPointerValue = function () {
                var self = this, angle = self._valueToAngle(0);
                self.pointer.transform(Raphael.format("r{0},{1},{2}", angle, self.centerPoint.x, self.centerPoint.y));
            };

            wijradialgauge.prototype._setPointer = function () {
                var self = this, o = self.options, angle = self._valueToAngle(o.value), animation = o.animation, transform = Raphael.format("r{0},{1},{2}", angle, self.centerPoint.x, self.centerPoint.y);

                if (!self.pointer) {
                    return;
                }
                _super.prototype._setPointer.call(this);

                if (animation.enabled) {
                    self.pointer.stop().wijAnimate({
                        transform: transform
                    }, animation.duration, animation.easing);
                } else {
                    self.pointer.transform(transform);
                }
            };

            /**
            * Remove the functionality completely. This will return the element back to its pre-init state.
            */
            wijradialgauge.prototype.destroy = function () {
                _super.prototype.destroy.call(this);
                this.element.removeClass(this.options.wijCSS.radialGauge);
            };

            wijradialgauge.prototype._clearVariables = function () {
                _super.prototype._clearVariables.call(this);
                var self = this;
                self.radius = null;
                self.centerPoint = null;
                self.faceRadius = null;
            };
            return wijradialgauge;
        })(gauge.wijgauge);
        gauge.wijradialgauge = wijradialgauge;

        wijradialgauge.prototype.widgetEventPrefix = "wijradialgauge";

        var wijradialgauge_options = (function () {
            function wijradialgauge_options() {
                /**
                * @ignore
                */
                this.initSelector = ":jqmData(role='wijradialgauge')";
                /**
                * @ignore
                */
                this.wijCSS = {
                    radialGauge: "wijmo-wijradialgauge",
                    radialGaugeLabel: "wijmo-wijradialgauge-label",
                    radialGaugeMarker: "wijmo-wijradialgauge-mark",
                    radialGaugeFace: "wijmo-wijradialgauge-face",
                    radialGaugePointer: "wijmo-wijradialgauge-pointer",
                    radialGaugeCap: "wijmo-wijradialgauge-cap",
                    radialGaugeRange: "wijmo-wijradialgauge-range"
                };
                /**
                * A value that indicates the radius of the radial gauge in pixels, or use "auto" to have the gauge indicators fill the
                * gauge area.
                * @remarks
                * Values between 50 and 200 are most useful when you use the default size for the gauge area.
                * @type {number|string}
                */
                this.radius = "auto";
                /**
                * A value that indicates in degrees where to start the lowest number in the numeric labels and tickMarks around the face
                * of the RadialGauge.
                * @remarks
                * The default value of 0 degrees renders the lowest number to the left of the origin.
                * A value of -90 degrees renders the lowest number below the origin.
                * A value of 90 degrees renders the lowest number above the origin.
                * A value of 180 degrees renders the lowest number to the right of the origin.
                */
                this.startAngle = 0;
                /**
                * A value that indicates in degrees where to render the highest number in the numeric labels and tickMarks in relation
                * to the startAngle.
                * @example
                * // This code example renders the labels and tickmarks from a starting angle of -45 degrees to a sweep angle of 270
                * degrees, so that the numbers render three quarters of the way around the face
                *    $(document).ready(function () {
                *        $("#radialgauge1").wijradialgauge({
                *			value: 90,
                *			startAngle: -45,
                *			sweepAngle: 270
                *		});
                *	});
                */
                this.sweepAngle = 180;
                /**
                * A value that includes all settings of the gauge pointer.
                * @example
                * // The example above renders the pointer as a purple-outlined blue rectangle of 125% the length of the radius by 10
                * // pixels wide, offset back through the cap by 50% of the length of the radius.
                *    $(document).ready(function () {
                *        $("#radialgauge1").wijradialgauge({
                *			value: 90,
                *			cap: {visible: true},
                *			pointer: {
                *				length: 1.25,
                *				offset: 0.5,
                *				shape: "rect",
                *				style: { fill: "blue", stroke: "purple"},
                *				width: 10
                *			}
                *		});
                *	});
                */
                this.pointer = {
                    /**
                    * Sets the length of the pointer as a percentage of the radius of the gauge.
                    * @remarks
                    * You can set the length to be greater than the radius.
                    */
                    length: 0.8,
                    /**
                    * Sets the fill and outline (stroke) colors of the pointer.
                    */
                    style: {
                        fill: "#1E395B",
                        stroke: "#1E395B"
                    },
                    /**
                    * Sets the width of the pointer in pixels.
                    */
                    width: 8,
                    /**
                    * Sets the percentage of the pointer that is shoved backward through the cap.
                    */
                    offset: 0.15,
                    shape: "tri",
                    visible: true,
                    template: null
                };
                /**
                * Sets the starting point for the center of the radial gauge.
                */
                this.origin = {
                    x: 0.5,
                    y: 0.5
                };
                /**
                * Sets all of the appearance options of the numeric labels that appear around the edge of the gauge.
                * @example
                * // This example sets the color for the labels to purple, and the font to 14 point, bold, Times New Roman.
                *    $(document).ready(function () {
                *        $("#radialgauge1").wijradialgauge({
                *			value: 90,
                *			labels: {
                *			style: {
                *				fill: "purple",
                *					"font-size": "14pt",
                *					"font-weight": "bold",
                *					"font-family": "Times New Roman"
                *				}
                *			}
                *		});
                *	});
                */
                this.labels = {
                    format: "",
                    /**
                    * A value that indicates the color, weight, and size of the numeric labels.
                    * To use a different font, add "font-family" to the style
                    */
                    style: {
                        fill: "#1E395B",
                        "font-size": 12,
                        "font-weight": "800"
                    },
                    /**
                    * A value in pixels that indicates the distance of the numeric labels from the outer reach of the pointer.
                    */
                    offset: 30,
                    visible: true
                };
                /**
                * Sets appearance options for the minor tick marks that appear between  the numeric labels around the face of the gauge,
                * indicating numeric values between the major tick marks.
                * @example
                * // This example renders the minor tick marks as purple crosses, at an interval of once every 2 numbers
                *	$(document).ready(function () {
                *		$("#radialgauge1").wijradialgauge({
                *			value: 90,
                *			tickMinor: {
                *				position: "inside",
                *				style: { fill: "#1E395B", stroke: "purple"},
                *				factor: 2,
                *				marker: 'cross',
                *				visible: true,
                *				offset: 30,
                *				interval: 2
                *			}
                *		});
                *	});
                */
                this.tickMinor = {
                    /**
                    * A value that indicates the position of the minor tick marks in relation to the edge of the face.
                    * @remarks
                    *  Valid Values:
                    *		"inside" -- Draws the minor tick marks inside the edge of the face.
                    *		"outside" -- Draws the minor tick marks outside the edge of the face.
                    *		"cross" -- Draws the minor tick marks centered on the edge of the face.
                    */
                    position: "inside",
                    /**
                    * A value that indicates the distance in pixels from the edge of the face to draw the minor tick marks.
                    */
                    offset: 30,
                    /**
                    * A value that indicates the fill color and outline (stroke) of the minor tick mark.
                    */
                    style: {
                        fill: "#1E395B"
                    },
                    /**
                    * A value that indicates whether to show the minor tick mark.
                    */
                    visible: true,
                    factor: 1,
                    marker: "rect",
                    interval: 5
                };
                /**
                * Sets appearance options for the major tick marks that appear next to the numeric labels around the face of the gauge.
                * @example
                * // This example renders the major tick marks as slightly larger purple filled diamonds with blue outlines, at an interval
                * // of once every 20 numbers
                *	$(document).ready(function () {
                *		$("#radialgauge1").wijradialgauge({
                *			value: 90,
                *			tickMajor: {
                *				position: "inside",
                *				style: { fill: "purple", stroke: "#1E395B"},
                *				factor: 2.5,
                *				marker: 'diamond',
                *				visible: true,
                *				offset: 27,
                *				interval: 20
                *			}
                *		});
                *	});
                */
                this.tickMajor = {
                    /**
                    * A value that indicates the position of the major tick marks in relation to the edge of the face.
                    * @remarks
                    * Valid Values:
                    *		"inside" -- Draws the major tick marks inside the edge of the face.
                    *		"outside" -- Draws the major tick marks outside the edge of the face.
                    *		"cross" -- Draws the major tick marks centered on the edge of the face.
                    */
                    position: "inside",
                    /**
                    * A value that indicates the distance in pixels from the edge of the face to draw the major tick marks.
                    * @remarks
                    * The numeric labels are drawn a few pixels outside of the major tick marks.
                    */
                    offset: 27,
                    /**
                    * A value that indicates the fill color and outline (stroke) of the major tick mark.
                    */
                    style: {
                        fill: "#1E395B",
                        stroke: "#1E395B",
                        "stroke-width": 1
                    },
                    /**
                    * A value that indicates whether to show the major tick mark.
                    */
                    visible: true,
                    interval: 10,
                    factor: 2,
                    marker: "rect"
                };
                /**
                * Sets the size, color, and other properties of the circle at the center of the gauge that anchors the pointer.
                * @example
                * // This example creates a rectangular cap that begins 10 pixels to the left of and 10 pixels above the origin, and is 20
                * // pixels wide by 20 pixels tall. The cap is filled with purple and has no outline (stroke).
                *	$(document).ready(function () {
                *		$("#radialgauge1").wijradialgauge({
                *			value: 180,
                *			max: 200,
                *			min: 0,
                *			cap: {
                *				template: function (ui) {
                *					var origin = ui.origin;
                *					return ui.canvas.rect(origin.x -10, origin.y -10, 20, 20).attr({fill: "purple", stroke: "none"});
                *				}
                *			}
                *		});
                *	});
                */
                this.cap = {
                    /**
                    * A value that indicates the radius of the cap in pixels.
                    */
                    radius: 15,
                    /**
                    * A value that contains the fill color and outline color (stroke) of the cap.
                    */
                    style: {
                        fill: "#1E395B",
                        stroke: "#1E395B"
                    },
                    /**
                    * A value that indicates whether the cap shows behind the pointer or in front.
                    */
                    behindPointer: false,
                    /**
                    * A value that indicates whether to show the cap.
                    */
                    visible: true,
                    /**
                    * A JavaScript callback value that returns a Raphael element (or set) that draws the cap for the pointer.
                    * @remarks
                    * If you are only using one shape, the function returns a Raphael element. If you define multiple shapes,  have the function
                    * create a Raphael set object push all of the Raphael elements to the set, and return the set to wijradialgauge.
                    * In order to use the template, you must know how to draw Raphael graphics. For more information, see the Raphael documentation.
                    * The cap template's callback contains one argument with two properties:
                    *		origin -- The starting point from which to draw the center of the cap.
                    *			This argument is defined by x and y coordinates.
                    *		canvas -- A Raphael paper object that you can use to draw the custom
                    *			graphic to use as the cap.
                    */
                    template: null
                };
                /// <summary>
                /// Sets or draws the image or shape to use for the face of the gauge and the
                /// background area. The origin is the center of the gauge, but the image
                /// draws from the top left, so we first calculate the starting point of the
                /// top left based on the origin, and we calculate the width and height based
                /// on the radius of the face. The radius of the face is half of the min of
                /// the width and height.
                /// Note: The fill property is defined using the Raphael framework. Please
                /// see the Raphael Element attr method for more information. The face can be
                /// filled with a simple color, or a gradient. The default fill is a radial
                /// gradient, indicated by the r in the fill property.
                /// Default: {fill: ""r(0.9, 0.60)#FFFFFF-#D9E3F0"", stroke: "#7BA0CC",
                /// "stroke-width": "4"}, template: null}.
                /// Type: Object.
                /// Code example:
                /// This example uses a custom image for the face of the gauge. The argument
                /// that we name ui in the example is a JSON object. This object has a canvas,
                /// which is a Raphael paper object, and we use the image method of the
                /// Raphael paper that takes five parameters: source, x, y, width, and height.
                /// See the Raphael documentation for more information.
                ///    $(document).ready(function () {
                ///        $("#radialgauge1").wijradialgauge({
                ///			value: 90,
                ///			radius: 120,
                ///			face: {
                ///			style: {},
                ///			template: function (ui) {
                ///                    var url = "images/customGaugeFace.png";
                ///                    return ui.canvas.image(url, ui.origin.x -ui.r, ui.origin.y -ui.r, ui.r * 2, ui.r * 2);
                ///			}
                ///			}
                ///			});
                ///			});
                /// </summary>
                /**
                * Sets or draws the image or shape to use for the face of the gauge and the background area.
                * @remarks
                * The origin is the center of the gauge, but the image draws from the top left, so we first calculate the starting point of the
                * top left based on the origin, and we calculate the width and height based on the radius of the face. The radius of the face is
                * half of the min of the width and height.
                * Note: The fill property is defined using the Raphael framework. Please see the Raphael Element attr method for more information.
                * The face can be filled with a simple color, or a gradient. The default fill is a radial gradient, indicated by the r in the
                * fill property.
                * @example
                * // This example uses a custom image for the face of the gauge. The argument that we name ui in the example is a JSON object.
                * // This object has a canvas, which is a Raphael paper object, and we use the image method of the Raphael paper that takes five
                * // parameters: source, x, y, width, and height. See the Raphael documentation for more information.
                *	$(document).ready(function () {
                *		$("#radialgauge1").wijradialgauge({
                *			value: 90,
                *			radius: 120,
                *			face: {
                *				style: {},
                *				template: function (ui) {
                *					var url = "images/customGaugeFace.png";
                *					return ui.canvas.image(url, ui.origin.x -ui.r, ui.origin.y -ui.r, ui.r * 2, ui.r * 2);
                *				}
                *			}
                *		});
                *	});
                */
                this.face = {
                    /**
                    * A value that indicates the fill color (or gradient), and the outline color  and width of the gauge face
                    */
                    style: {
                        fill: "r(0.9, 0.60)#FFFFFF-#D9E3F0",
                        stroke: "#7BA0CC",
                        "stroke-width": 4
                    },
                    template: null
                };
            }
            return wijradialgauge_options;
        })();
        wijradialgauge.prototype.options = $.extend(true, {}, gauge.wijgauge.prototype.options, new wijradialgauge_options());

        //$.widget("wijmo.wijradialgauge", WijRadialGauge.prototype);
        $.wijmo.registerWidget("wijradialgauge", wijradialgauge.prototype);
    })(wijmo.gauge || (wijmo.gauge = {}));
    var gauge = wijmo.gauge;
})(wijmo || (wijmo = {}));

;
/// <reference path="../Base/jquery.wijmo.widget.ts" />
/// <reference path="../External/declarations/swfobject.d.ts" />
/// <reference path="../External/declarations/jquery.bgiframe.d.ts" />
/// <reference path="../External/declarations/jquery.cookie.d.ts" />
/// <reference path="../wijvideo/jquery.wijmo.wijvideo.ts" />
/*globals jQuery, window, XMLHttpRequest*/
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*
    * Depends:
    *     jquery.ui.core.js
    *     jquery.ui.widget.js
    */
    (function (_lightbox) {
        var $ = jQuery, widgetName = "wijlightbox";

        if (!window["S"] && window["swfobject"]) {
            window["S"] = {
                flash: window["swfobject"]
            };
        }

        /** @widget */
        var wijlightbox = (function (_super) {
            __extends(wijlightbox, _super);
            function wijlightbox() {
                _super.apply(this, arguments);
            }
            wijlightbox.prototype._keyDownHandler = function (event) {
                var o = this.options, self = this, kCode = wijmo.getKeyCodeEnum();
                if (event.keyCode && event.keyCode === kCode.ESCAPE) {
                    if (self._isFullSize()) {
                        self._toggleFullSize();
                    } else {
                        if (o.closeOnEscape) {
                            self._close();
                        }
                    }

                    event.preventDefault();
                    return;
                }

                if (o.keyNav) {
                    if (event.keyCode) {
                        switch (event.keyCode) {
                            case kCode.LEFT:
                            case kCode.DOWN:
                                self.back();
                                event.preventDefault();
                                break;

                            case kCode.RIGHT:
                            case kCode.UP:
                                self.next();
                                event.preventDefault();
                                break;

                            case kCode.HOME:
                                if (o.groupItems.length > 0) {
                                    self.show(0);
                                }
                                event.preventDefault();
                                break;

                            case kCode.END:
                                if (o.groupItems.length > 0) {
                                    self.show(o.groupItems.length - 1);
                                }
                                event.preventDefault();
                                break;
                        }
                    }
                }
            };

            wijlightbox.prototype._create = function () {
                var o = this.options, self = this;

                // enable touch support:
                if (window.wijmoApplyWijTouchUtilEvents) {
                    $ = window.wijmoApplyWijTouchUtilEvents($);
                }
                if (!o.groupItems) {
                    o.groupItems = [];
                }
                this._defaults = {
                    transAnimation: {
                        animated: 'fade',
                        duration: 400,
                        easing: 'linear'
                    },
                    resizeAnimation: {
                        animated: 'sync',
                        duration: 400
                    },
                    textShowOption: {
                        duration: 300,
                        easing: 'linear'
                    },
                    textHideOption: {
                        duration: 300,
                        easing: 'linear'
                    }
                };

                this._parse();

                this.container = $('<div/>').addClass('wijmo-wijlightbox ' + o.wijCSS.widget + ' wijmo-wijlightbox-controls-' + o.controlsPosition).css('z-index', o.zIndex).attr({
                    'tabIndex': -1,
                    'role': 'dialog'
                }).bind('keydown.wijlightbox', $.proxy(self, '_keyDownHandler')).appendTo(document.body).hide();

                this.frame = $('<div></div>').addClass([
                    'wijmo-wijlightbox-frame', o.wijCSS.content,
                    o.wijCSS.cornerAll, o.wijCSS.helperClearFix].join(' ')).appendTo(this.container);

                this.content = $('<div></div>').addClass('wijmo-wijlightbox-content').appendTo(this.frame);

                // Active a panel
                // use "activeIndex" option or try to retrieve:
                // 1. from cookie
                // 2. from actived class attribute on panel
                if (o.activeIndex === undefined) {
                    if (typeof o.activeIndex !== 'number' && o.cookie) {
                        o.activeIndex = parseInt(self._cookie(), 10);
                    }
                    o.activeIndex = o.activeIndex || (o.groupItems.length ? 0 : -1);
                } else if (o.activeIndex === null) {
                    // usage of null is deprecated, TODO remove in next release
                    o.activeIndex = -1;
                }

                // sanity check - default to first page...
                o.activeIndex = ((o.activeIndex >= 0 && o.groupItems[o.activeIndex]) || o.activeIndex < 0) ? o.activeIndex : 0;

                this._initClickBehavior();
                this._createTimerBar();
                this._createDialogButtons();
                this._createCtrlButtons();
                this._createText();
                this._createCounter();
                this._refreshCounter();

                if (this.toolBox) {
                    this.toolBox.find('.wijmo-wijlightbox-toolbox-button').bind({
                        'mouseover': function () {
                            self._addState('hover', $(this));
                        },
                        'mouseout': function () {
                            self._removeState('hover', $(this));
                        },
                        'mousedown': function () {
                            self._addState('active', $(this));
                        },
                        'mouseup': function () {
                            self._removeState('active', $(this));
                        }
                    });
                }

                if (this._groupMode()) {
                    this._createNavButtons();
                }

                this._initHoverBehavior();
                this.container.width(this.frame.outerWidth());
                _super.prototype._create.call(this);
            };

            /**
            * Destroys wijlightbox widget and reset the DOM element.
            */
            wijlightbox.prototype.destroy = function () {
                var o = this.options, self = this;

                this._hideWaiting();
                this._hideOverlay();

                if (o.cookie) {
                    this._cookie(null, o.cookie);
                }

                this.element.find("a").unbind("click");
                this.container.remove();
                _super.prototype.destroy.call(this);
            };

            wijlightbox.prototype._setOption = function (key, value) {
                var oldValue = this.options[key];
                _super.prototype._setOption.call(this, key, value);

                switch (key) {
                    case 'groupItems':
                        if (this.options.activeIndex >= value.length) {
                            this.show(value.length - 1);
                        } else {
                            if (this.options.activeIndex < 0 && value.length) {
                                this.show(0);
                            } else {
                                this.show(this.options.activeIndex);
                            }
                        }
                        break;

                    case 'activeIndex':
                        this.show(value);
                        break;

                    case 'textPosition':
                        this._resetText();
                        break;

                    case 'clickPause':
                        this._initClickBehavior();
                        break;

                    case 'showNavButtons':
                        this._createNavButtons();
                        break;

                    case 'showControlsOnHover':
                        this._initHoverBehavior();
                        break;
                    case "controlsPosition":
                        this._set_controlsPosition(oldValue, value);
                        break;
                    case "showCounter":
                        this._createCounter();
                        break;
                }
            };

            wijlightbox.prototype._set_controlsPosition = function (oldValue, value) {
                //recreate the controls.
                if (oldValue !== value) {
                    this._removeCounter();
                    this._removeNavButtons();
                    this.container.removeClass("wijmo-wijlightbox-controls-outside wijmo-wijlightbox-controls-inside").addClass("wijmo-wijlightbox-controls-" + value);
                    this._createCounter();
                    this._createNavButtons();
                }
            };

            wijlightbox.prototype._initClickBehavior = function () {
                var o = this.options, self = this;

                this.content.unbind('click');
                if (o.clickPause) {
                    if (this._groupMode()) {
                        this.content.click(function () {
                            self[!self.isPlaying() ? 'play' : 'stop']();
                        });
                    }
                } else {
                    if (this._groupMode()) {
                        this.content.click(function (e) {
                            if (self.isPlaying()) {
                                return false;
                            }
                            var rect = $.extend({}, $(this).offset(), {
                                width: $(this).outerWidth(true),
                                height: $(this).outerHeight(true)
                            });
                            if (e.pageX >= rect.left && e.pageX < (rect.left + rect.width / 2)) {
                                if (!self.backBtn.hasAllClasses(o.wijCSS.stateDisabled)) {
                                    self.back();
                                }
                            } else {
                                if (!self.nextBtn.hasAllClasses(o.wijCSS.stateDisabled)) {
                                    self.next();
                                }
                            }
                        });
                    }
                }
            };

            wijlightbox.prototype._initHoverBehavior = function () {
                var o = this.options, self = this;
                this.frame.unbind('.wijlightbox');

                if (o.showControlsOnHover) {
                    this.frame.bind({
                        'mouseenter.wijlightbox': function () {
                            if (self.container.data('moving.wijlightbox')) {
                                return false;
                            }
                            self._showAccessories(true);
                        },
                        'mouseleave.wijlightbox': function () {
                            if (self.container.data('moving.wijlightbox')) {
                                return false;
                            }

                            self._hideAccessories(true);
                        },
                        'mousemove.wijlightbox': function () {
                            if (self.container.data('moving.wijlightbox') === false && self.container.data('accessvisible.wijlightbox') === false) {
                                self.frame.trigger('mouseenter');
                            }
                        }
                    });
                }
            };

            wijlightbox.prototype._getPlugins = function () {
                var plugins = this.container.data('plugins.wijlightbox'), names, detectPlugin, f4m;
                if (!plugins) {
                    plugins = {};
                    if (window.navigator.plugins && window.navigator.plugins.length) {
                        names = [];
                        $.each(window.navigator.plugins, function (i, p) {
                            names.push(p.name);
                        });
                        names = names.join(",");
                        f4m = names.indexOf("Flip4Mac") > -1;
                        plugins = {
                            fla: names.indexOf("Shockwave Flash") > -1,
                            qt: names.indexOf("QuickTime") > -1,
                            wmp: !f4m && names.indexOf("Windows Media") > -1,
                            f4m: f4m
                        };
                    } else {
                        detectPlugin = function (name) {
                            var axo;
                            try  {
                                axo = new ActiveXObject(name);
                            } catch (e) {
                            }
                            return !!axo;
                        };
                        plugins = {
                            fla: detectPlugin("ShockwaveFlash.ShockwaveFlash"),
                            qt: detectPlugin("QuickTime.QuickTime"),
                            wmp: detectPlugin("wmplayer.ocx"),
                            f4m: false
                        };
                    }

                    this.container.data('plugins.wijlightbox', plugins);
                }

                return plugins;
            };

            wijlightbox.prototype._sanitizeSelector = function (hash) {
                // we need this because an id may contain a ":"
                return hash.replace(/:/g, '\\:');
            };

            wijlightbox.prototype._getFragmentId = function (a) {
                var fragmentId = /^#.+/, href = $(a).attr('href') || "", hrefBase = href.split('#')[0], baseEl = $('base')[0];
                if (hrefBase && (hrefBase === window.location.toString().split('#')[0] || (baseEl && hrefBase === baseEl.attributes["href"]))) {
                    href = a.hash;
                    a.href = href;
                }

                // inline links
                return fragmentId.test(href) ? this._sanitizeSelector(href) : "";
            };

            wijlightbox.prototype._parseLink = function (a) {
                var self = this, o = this.options, $a = $(a), opt = { href: undefined, player: undefined, img: undefined, gallery: undefined }, rel, $img, gallery, index, props = [
                    'href', 'player', 'title', 'alt',
                    'height', 'width', 'gallery', 'wijvideosrc'];
                if ($a.length > 0 && $a[0].tagName.toLowerCase() === 'a') {
                    rel = $a.attr('rel');

                    $.each(props, function (i, o) {
                        opt[o] = $a.attr(o) || '';
                    });

                    if (!opt.href) {
                        return;
                    }
                    if (!opt.player) {
                        opt.player = o.player || self._getPlayerName(opt.href);
                    }

                    $img = $a.find('img');
                    if ($img && $img.length === 0) {
                        $img = $a;
                    }

                    if ($img && $img.length >= 1) {
                        $.each(['title', 'alt'], function (i, o) {
                            opt[o] = $img.attr(o) || opt[o];
                        });

                        opt.img = $img;
                    }

                    if (rel) {
                        gallery = rel.match(/\[(.*?)\]/);
                        if (gallery) {
                            opt.gallery = gallery[1] || opt.gallery;
                        }

                        $.each(rel.split(";"), function (i, p) {
                            var match = p.match(/\s*([a-z_]*?)\s*=\s*(.+)\s*/);
                            if (match) {
                                opt[match[1]] = match[2];
                            }
                        });
                    }

                    if (opt.player === 'inline') {
                        opt.href = self._getFragmentId(a);
                    }

                    if (!opt.gallery) {
                        $a.bind({
                            'click': function (e) {
                                e.stopPropagation();
                                e.preventDefault();
                                if (!self._isDisabled()) {
                                    self._open($img, opt);
                                }
                                return false;
                            }
                        });
                    } else {
                        index = o.groupItems.length;
                        o.groupItems[index] = opt;
                        $a.bind({
                            'click': function (e) {
                                e.stopPropagation();
                                e.preventDefault();
                                if (!self._isDisabled()) {
                                    self._open($img, index);
                                }
                                return false;
                            }
                        });
                    }
                }
            };

            wijlightbox.prototype._parse = function () {
                var self = this;

                this._parseLink(this.element);
                this.element.find('a[rel^="wijlightbox"], a[rel^="lightbox"]').each(function (index, element) {
                    self._parseLink(element);
                });
            };

            wijlightbox.prototype._showAccessories = function (fade) {
                this.container.data('accessvisible.wijlightbox', true);
                this._showNavButtons(fade);
                this._showToolboxButtons(fade);
                this._showCounter(fade);
            };

            wijlightbox.prototype._hideAccessories = function (fade) {
                this.container.data('accessvisible.wijlightbox', false);
                this._hideNavButtons(fade);
                this._hideToolboxButtons(fade);
                this._hideCounter(fade);
            };

            wijlightbox.prototype._groupMode = function () {
                var o = this.options;
                return (o.groupItems && o.groupItems.length > 1);
            };

            wijlightbox.prototype._resetText = function () {
                this._removeText();
                this._createText();
            };

            wijlightbox.prototype._createText = function (updateOnly) {
                var self = this, o = self.options, cs, $text, $mask, $title, $detail;
                if (o.textPosition === 'none') {
                    return;
                }

                if (this.container.find('.wijmo-wijlightbox-text').length) {
                    return;
                }

                cs = o.textPosition.toLowerCase();
                $text = $('<div></div>').addClass('wijmo-wijlightbox-text wijmo-wijlightbox-text-' + cs + ' ' + o.wijCSS.content + ' ' + o.wijCSS.helperClearFix);
                $title = $('<h3></h3>').addClass('wijmo-wijlightbox-title wijmo-wijlightbox-title-' + cs + ' ' + o.wijCSS.helperClearFix).appendTo($text);
                $detail = $('<p></p>').addClass('wijmo-wijlightbox-detail wijmo-wijlightbox-detail-' + cs + ' ' + o.wijCSS.helperClearFix).appendTo($text);

                if (o.textPosition === 'inside') {
                    $text.addClass(o.wijCSS.content + ' ' + o.wijCSS.helperClearFix).width(this.frame.width()).appendTo(this.frame);
                } else if (o.textPosition === 'outside') {
                    $text.addClass([o.wijCSS.content, o.wijCSS.cornerAll, o.wijCSS.helperClearFix].join(' ')).width(this.frame.width()).appendTo(this.container);
                } else if (o.textPosition === 'overlay' || o.textPosition === 'titleOverlay') {
                    $mask = $('<div></div>').addClass('wijmo-wijlightbox-mask wijmo-wijlightbox-mask-' + cs + ' ' + o.wijCSS.helperClearFix).width(this.frame.width()).appendTo(this.frame);

                    $text.width(this.frame.width()).appendTo(this.frame);

                    if (o.textPosition === 'titleOverlay') {
                        $text.bind({
                            'mouseenter': function () {
                                $mask.stop();
                                $text.stop();

                                var totalHeight = $title.outerHeight(true) + $detail.outerHeight(true), animOption = $.extend({}, self._defaults.textShowOption, o.textShowOption, { queue: false });
                                $mask.animate({
                                    height: totalHeight
                                }, animOption);

                                $text.animate({
                                    height: totalHeight
                                }, animOption);
                            },
                            'mouseleave': function () {
                                $mask.stop();
                                $text.stop();

                                var titleHeight = $title.height(), animOption = $.extend({}, self._defaults.textHideOption, o.textHideOption, { queue: false });
                                $mask.animate({
                                    height: titleHeight
                                }, animOption);

                                $text.animate({
                                    height: titleHeight
                                }, animOption);
                            }
                        });
                    }
                }

                this._refreshText(updateOnly);
            };

            wijlightbox.prototype._removeText = function () {
                this.container.find(".wijmo-wijlightbox-text," + ".wijmo-wijlightbox-mask").remove();
            };

            wijlightbox.prototype._getActiveItem = function () {
                var o = this.options;

                if (o.groupItems && o.groupItems.length && o.activeIndex >= 0 && o.activeIndex < o.groupItems.length) {
                    return o.groupItems[o.activeIndex];
                }

                return null;
            };

            wijlightbox.prototype._refreshText = function (updateOnly) {
                var self = this, o = this.options, item, $text, $title, $detail, $mask;

                if (o.textPosition === 'none') {
                    return;
                }
                item = this.container.data('item.wijlightbox') || this._getActiveItem();
                if (!item) {
                    return;
                }

                $text = this.container.find('.wijmo-wijlightbox-text');
                $title = this.container.find('.wijmo-wijlightbox-title');
                $detail = this.container.find('.wijmo-wijlightbox-detail');
                $mask = this.container.find('.wijmo-wijlightbox-mask');

                $mask.stop();
                $text.stop();

                $title.html(item.title);
                $detail.html(item.alt);

                if (o.textPosition === 'outside') {
                    $text.width(this.frame.width());
                }

                var titleHeight = $title.outerHeight(true), detailHeight = $detail.outerHeight(true);

                // var toHeight = o.textPosition === 'titleOverlay' ?
                // titleHeight :
                // $text.height();
                var animOption = $.extend({}, self._defaults.textShowOption, o.textShowOption, { queue: false });
                if (o.textPosition === 'overlay' || o.textPosition === 'titleOverlay') {
                    var toHeitht = titleHeight + (o.textPosition === 'overlay' ? detailHeight : 0);
                    $text.height(0);
                    $mask.height(0);
                    $text.animate({
                        height: toHeitht
                    }, animOption);

                    $mask.animate({
                        height: toHeitht
                    }, animOption);
                } else {
                    if (!!updateOnly) {
                        $text.height(titleHeight + detailHeight);
                    } else {
                        $text.height(0);
                        $text.animate({
                            height: titleHeight + detailHeight
                        }, animOption);
                    }
                }
            };

            wijlightbox.prototype._addState = function (state, el) {
                if (el.is(':not(.' + this.options.wijCSS.stateDisabled + ')')) {
                    el.addClass('ui-state-' + state);
                }
            };

            wijlightbox.prototype._removeState = function (state, el) {
                el.removeClass('ui-state-' + state);
            };

            wijlightbox.prototype._createNavButtons = function () {
                var self = this, o = this.options;
                if (!o.showNavButtons || !this._groupMode()) {
                    this._removeNavButtons();
                    return;
                }

                if (!this.backBtn) {
                    this.backBtn = $("<a href='#'/>").addClass('wijmo-wijlightbox-button ' + 'wijmo-wijlightbox-button-prev ' + o.wijCSS.stateDefault + ' ' + (o.controlsPosition === 'inside' ? o.wijCSS.cornerRight : o.wijCSS.cornerLeft)).append("<span class='" + o.wijCSS.icon + " " + o.wijCSS.iconArrowLeft + "'></span>").hide().appendTo(this.frame).bind({
                        'click': function () {
                            if (!$(this).hasAllClasses(o.wijCSS.stateDisabled)) {
                                self.back();
                            }
                            return false;
                        },
                        'mouseover': function () {
                            self._addState('hover', $(this));
                        },
                        'mouseout': function () {
                            self._removeState('hover', $(this));
                        },
                        'mousedown': function () {
                            self._addState('active', $(this));
                        },
                        'mouseup': function () {
                            self._removeState('active', $(this));
                        }
                    });
                }

                if (!this.nextBtn) {
                    this.nextBtn = $("<a href='#'/>").addClass('wijmo-wijlightbox-button ' + 'wijmo-wijlightbox-button-next ' + o.wijCSS.stateDefault + ' ' + (o.controlsPosition === 'inside' ? o.wijCSS.cornerLeft : o.wijCSS.cornerRight)).append("<span class='" + o.wijCSS.icon + " " + o.wijCSS.iconArrowRight + "'></span>").hide().appendTo(this.frame).bind({
                        'click': function () {
                            if (!$(this).hasAllClasses(o.wijCSS.stateDisabled)) {
                                self.next();
                            }
                            return false;
                        },
                        'mouseover': function () {
                            self._addState('hover', $(this));
                        },
                        'mouseout': function () {
                            self._removeState('hover', $(this));
                        },
                        'mousedown': function () {
                            self._addState('active', $(this));
                        },
                        'mouseup': function () {
                            self._removeState('active', $(this));
                        }
                    });
                }
            };

            wijlightbox.prototype._removeNavButtons = function () {
                if (this.backBtn) {
                    this.backBtn.remove();
                    this.backBtn = undefined;
                }

                if (this.nextBtn) {
                    this.nextBtn.remove();
                    this.nextBtn = undefined;
                }
            };

            wijlightbox.prototype._refreshNavButtons = function () {
                var o = this.options, operation;

                if (this.backBtn) {
                    operation = o.activeIndex === 0 ? 'addClass' : 'removeClass';
                    this.backBtn[operation](o.wijCSS.stateDisabled);
                }

                if (this.nextBtn) {
                    operation = o.activeIndex >= o.groupItems.length - 1 ? 'addClass' : 'removeClass';
                    this.nextBtn[operation](o.wijCSS.stateDisabled);
                }
            };

            wijlightbox.prototype._showNavButtons = function (anim) {
                if (this.isPlaying()) {
                    return;
                }

                this.container.find('.wijmo-wijlightbox-button').stop(true, true).fadeIn(anim ? 600 : 0, function () {
                    $(this).css('opacity', '');
                });
            };

            wijlightbox.prototype._hideNavButtons = function (anim) {
                this.container.find('.wijmo-wijlightbox-button').stop(true, true).fadeOut(anim ? 600 : 0);
            };

            wijlightbox.prototype._createToolbox = function () {
                if (!this.toolBox) {
                    this.toolBox = $("<div></div>").addClass('wijmo-wijlightbox-toolbox').appendTo(this.frame);
                }
            };

            wijlightbox.prototype._showToolboxButtons = function (anim) {
                this.container.find('.wijmo-wijlightbox-toolbox-button').stop(true, true).fadeIn(anim ? 600 : 0, function () {
                    $(this).css('opacity', '');
                });
            };

            wijlightbox.prototype._hideToolboxButtons = function (anim) {
                this.container.find('.wijmo-wijlightbox-toolbox-button').stop(true, true).fadeOut(anim ? 600 : 0);
            };

            wijlightbox.prototype._createCtrlButtons = function () {
                var self = this, o = this.options, wijCSS = o.wijCSS;
                if (!o.ctrlButtons || o.ctrlButtons.length === 0 || !this._groupMode()) {
                    this._removeCtrlButtons();
                    return;
                }

                this._createToolbox();

                var buttons = o.ctrlButtons.split('|');
                if (buttons.length === 1 && buttons[0] === o.ctrlButtons) {
                    buttons = o.ctrlButtons.split(',');
                }
                $.each(buttons, function (index, name) {
                    name = $.trim(name);
                    if (name === 'play' && !this.playBtn) {
                        self.playBtn = $("<a href='#'/>").addClass([
                            'wijmo-wijlightbox-toolbox-button', ' wijmo-wijlightbox-toolbox-button-play ',
                            wijCSS.stateDefault, wijCSS.cornerAll].join(' ')).append("<span class='" + wijCSS.icon + " " + wijCSS.iconPlay + "'></span>").hide().click(function () {
                            if (self.isPlaying()) {
                                self.stop();
                            } else {
                                self.play();
                            }
                            return false;
                        });
                    } else if (name === 'stop' && !this.stopBtn) {
                        self.stopBtn = $("<a href='#'/>").addClass([
                            'wijmo-wijlightbox-toolbox-button', 'wijmo-wijlightbox-toolbox-button-stop',
                            wijCSS.stateDefault, wijCSS.stateDisabled, wijCSS.cornerAll].join(' ')).append("<span class='" + wijCSS.icon + " " + wijCSS.iconStop + "'></span>").hide().click(function () {
                            if (self.isPlaying()) {
                                self.stop();
                                self.show(0);
                            }
                            return false;
                        });
                    }
                });

                if (this.stopBtn) {
                    this.stopBtn.appendTo(this.toolBox);
                }

                if (this.playBtn) {
                    this.playBtn.appendTo(this.toolBox);
                }
            };

            wijlightbox.prototype._removeCtrlButtons = function () {
                if (this.playBtn) {
                    this.playBtn.remove();
                    this.playBtn = undefined;
                }

                if (this.stopBtn) {
                    this.stopBtn.remove();
                    this.stopBtn = undefined;
                }
            };

            wijlightbox.prototype._refreshCtrlButtons = function () {
                var css = this.options.wijCSS;
                if (this.playBtn) {
                    var icon = this.playBtn.find('.' + css.icon);
                    if (icon) {
                        icon.removeClass(css.iconPause + ' ' + css.iconPlay);
                        icon.addClass(this.isPlaying() ? css.iconPause : css.iconPlay);
                    }
                }

                if (this.stopBtn) {
                    this.stopBtn[!this.isPlaying() ? 'addClass' : 'removeClass'](css.stateDisabled);
                }
            };

            wijlightbox.prototype._createDialogButtons = function () {
                var self = this, o = this.options, buttons;
                if (!o.dialogButtons || o.dialogButtons.length === 0) {
                    this._removeDialogButtons();
                    return;
                }

                this._createToolbox();

                buttons = o.dialogButtons.split('|');
                if (buttons.length === 1 && buttons[0] === o.dialogButtons) {
                    buttons = o.dialogButtons.split(',');
                }

                $.each(buttons, function (index, name) {
                    name = $.trim(name);
                    if (name === 'close' && !this.closeBtn) {
                        self.closeBtn = $("<a href='#'/>").addClass('wijmo-wijlightbox-toolbox-button ' + 'wijmo-wijlightbox-toolbox-button-close ' + o.wijCSS.stateDefault + ' ' + o.wijCSS.cornerAll).append("<span class='" + o.wijCSS.icon + " " + o.wijCSS.iconClose + "'></span>").hide().click(function () {
                            self._close();
                            return false;
                        });
                    } else if (name === 'fullSize' && !this.fullBtn) {
                        self.fullBtn = $("<a href='#'/>").addClass('wijmo-wijlightbox-toolbox-button ' + 'wijmo-wijlightbox-toolbox-button-fullsize ' + o.wijCSS.stateDefault + ' ' + o.wijCSS.cornerAll).append("<span class='" + o.wijCSS.icon + " " + o.wijCSS.iconArrow4Diag + "'></span>").hide().click(function () {
                            self._toggleFullSize();
                            return false;
                        });
                    }
                });

                if (this.closeBtn) {
                    this.closeBtn.appendTo(this.toolBox);
                }

                if (this.fullBtn) {
                    this.fullBtn.appendTo(this.toolBox);
                }

                if (!this.btnSep) {
                    this.btnSep = $("<a href='#'/>").addClass('wijmo-wijlightbox-toolbox-separator').appendTo(this.toolBox);
                }
            };

            wijlightbox.prototype._removeDialogButtons = function () {
                if (this.closeBtn) {
                    this.closeBtn.remove();
                    this.closeBtn = undefined;
                }

                if (this.fullBtn) {
                    this.fullBtn.remove();
                    this.fullBtn = undefined;
                }
            };

            wijlightbox.prototype._refreshDialogButtons = function () {
                var css = this.options.wijCSS;
                if (this.fullBtn) {
                    var icon = this.fullBtn.find('.' + css.icon);
                    if (icon) {
                        icon.removeClass(css.iconArrow4Diag + ' ' + css.iconNewWin);
                        icon.addClass(this._isFullSize() ? css.iconNewWin : css.iconArrow4Diag);
                    }
                }
            };

            wijlightbox.prototype._createTimerBar = function () {
                var self = this, o = self.options;
                if (!o.showTimer || !self._groupMode()) {
                    self._removeTimerBar();
                    return;
                }

                self._createToolbox();

                if (!self.timerBar) {
                    self.timerBar = $("<div></div>").addClass('wijmo-wijlightbox-timerbar ' + o.wijCSS.content + ' ui-priority-secondary ' + o.wijCSS.cornerAll).appendTo(self.toolBox);

                    self.timerMeter = $("<div></div>").addClass('wijmo-wijlightbox-timermeter ui-progressbar-value ' + o.wijCSS.content + ' ' + o.wijCSS.cornerAll).appendTo(self.toolBox);
                }
            };

            wijlightbox.prototype._removeTimerBar = function () {
                if (this.timerMeter) {
                    this.timerMeter.remove();
                    this.timerMeter = undefined;
                }

                if (this.timerBar) {
                    this.timerBar.remove();
                    this.timerBar = undefined;
                }
            };

            wijlightbox.prototype._createCounter = function () {
                var self = this, o = self.options;
                if (!o.showCounter || !self._groupMode()) {
                    self._removeCounter();
                    return;
                }

                if (!self.counter) {
                    self.counter = $("<div></div>").addClass('wijmo-wijlightbox-counter ' + o.wijCSS.stateDefault + ' ' + (o.controlsPosition === 'inside' ? o.wijCSS.cornerTL : o.wijCSS.cornerAll)).hide().appendTo(self.frame);
                }
            };

            wijlightbox.prototype._removeCounter = function () {
                if (this.counter) {
                    this.counter.remove();
                    this.counter = undefined;
                }
            };

            wijlightbox.prototype._refreshCounter = function (index) {
                var self = this, o = this.options, counter = "";

                if (!this.counter || !this._groupMode()) {
                    return;
                }
                this.counter.empty();

                if (o.showCounter && o.groupItems.length > 1 && this.counter) {
                    if (index === undefined) {
                        index = o.activeIndex;
                    }

                    var len = o.groupItems.length;
                    if (o.counterType === "sequence") {
                        var start = 0, end = len, limit = parseInt(o.counterLimit, 10) || 0;

                        if (limit >= 2 && limit < len) {
                            var h = Math.floor(limit / 2);
                            start = Math.min(end - limit, Math.max(start, index - h));
                            end = Math.min(end, start + limit);
                        }

                        while (start !== end) {
                            $("<a></a>").addClass('wijmo-wijlightbox-counter-item ' + o.wijCSS.content + ' ' + o.wijCSS.stateDefault + (start === index ? ' wijmo-wijlightbox-counter-active ' + o.wijCSS.stateActive : '')).text((++start).toString()).appendTo(this.counter);
                        }

                        this.counter.find('a').click(function (event, data) {
                            if ($(this).hasClass('wijmo-wijlightbox-counter-active')) {
                                return false;
                            }

                            self.show(parseInt($(this).text(), 10) - 1);
                            return false;
                        });
                    } else {
                        var fmt = o.counterFormat || "[i] of [n]";
                        counter = fmt.replace('[i]', index + 1);
                        counter = counter.replace('[n]', len);

                        $("<span></span>").text(counter).appendTo(this.counter);
                    }
                }
            };

            wijlightbox.prototype._showCounter = function (anim) {
                this.container.find('.wijmo-wijlightbox-counter').stop(true, true).fadeIn(anim ? 600 : 0, function () {
                    $(this).css('opacity', '');
                });
            };

            wijlightbox.prototype._hideCounter = function (anim) {
                this.container.find('.wijmo-wijlightbox-counter').stop(true, true).fadeOut(anim ? 600 : 0);
            };

            wijlightbox.prototype._cookie = function (name, value) {
                var cookie = this.cookie || (this.cookie = this.options.cookie.name);
                return $.cookie.apply(null, [cookie].concat($.makeArray(arguments)));
            };

            wijlightbox.prototype._showOverlay = function () {
                if (this.container.data('overlay.wijlightbox')) {
                    return;
                }
                this.container.data('overlay.wijlightbox', new $.wijmo.wijlightbox.overlay(this));
            };

            wijlightbox.prototype._hideOverlay = function () {
                var $overlay = this.container.data('overlay.wijlightbox');
                if (!$overlay) {
                    return;
                }

                $overlay.close();
                this.container.removeData('overlay.wijlightbox');
            };

            wijlightbox.prototype._hasOverlay = function () {
                return this.container.hasData('overlay.wijlightbox');
            };

            wijlightbox.prototype._showWaiting = function () {
                if (this.container.data('waiting.wijlightbox')) {
                    return;
                }
                this.container.data('waiting.wijlightbox', new $.wijmo.wijlightbox.overlay(this, true));
            };

            wijlightbox.prototype._hideWaiting = function () {
                var $overlay = this.container.data('waiting.wijlightbox');
                if (!$overlay) {
                    return;
                }

                $overlay.close();
                this.container.removeData('waiting.wijlightbox');
            };

            wijlightbox.prototype._hasWaiting = function () {
                return this.container.hasData('waiting.wijlightbox');
            };

            wijlightbox.prototype._getUrl = function (item) {
                var o = this.options, url = (typeof item === 'string') ? item : item.href, rootUrl = o.rootUrl;
                if (rootUrl && rootUrl.length > 0) {
                    if (rootUrl.indexOf('//') === -1) {
                        rootUrl = window.location.protocol + '//' + window.location.host + (rootUrl.startsWith('/') ? '' : '/') + rootUrl;
                    }

                    if (rootUrl.substr(rootUrl.length - 1, 1) !== '/') {
                        rootUrl += '/';
                    }

                    url = rootUrl + (url.substr(0, 1) === '/' ? url.substr(1) : url);
                }

                return url;
            };

            wijlightbox.prototype._preload = function () {
                var o = this.options, i;
                for (i = Math.max(0, o.activeIndex); i < Math.min(o.activeIndex + 5, o.groupItems.length); i++) {
                    if (!o.groupItems[i].image) {
                        o.groupItems[i].image = new Image();
                        o.groupItems[i].image.src = this._getUrl(o.groupItems[i]);
                    }
                }
            };

            wijlightbox.prototype._slideAnimate = function (o, el, done) {
                var props = ["position", "top", "bottom", "left", "right", "width", "height"], mode = $.setMode(el, o.mode || "show"), show = mode === "show", direction = o.direction || "left", ref = (direction === "up" || direction === "down") ? "top" : "left", positiveMotion = (direction === "up" || direction === "left"), distance, animation = {};

                // Adjust
                $.save(el, props);
                el.show();
                distance = o.distance || el[ref === "top" ? "outerHeight" : "outerWidth"](true);

                $.createWrapper(el).css({
                    overflow: "hidden"
                });

                if (show) {
                    el.css(ref, positiveMotion ? (isNaN(distance) ? parseInt("-" + distance) : -distance) : distance);
                }

                // Animation
                animation[ref] = (show ? (positiveMotion ? "+=" : "-=") : (positiveMotion ? "-=" : "+=")) + distance;

                el.animate(animation, {
                    queue: false,
                    duration: o.duration,
                    easing: o.easing,
                    complete: function () {
                        if (mode === "hide") {
                            el.hide();
                        }
                        $.restore(el, props);
                        $.removeWrapper(el);
                        done();
                    }
                });
            };

            wijlightbox.prototype._slideTo = function (prevPlayer, player, animation, next, complete) {
                var o = this.options, self = this, curImage = prevPlayer.getElement(), wrapper, slideContainer, direction, w, h, $img, slideCallback, slideOpts;

                if (curImage.parent().is('.wijmo-wijlightbox-aniwrapper')) {
                    wrapper = curImage.parent();
                } else {
                    wrapper = $.createWrapper(curImage).css({ overflow: 'hidden' });
                    wrapper.removeClass('ui-effects-wrapper');
                    wrapper.addClass('wijmo-wijlightbox-aniwrapper');
                }

                if (wrapper.parent().is('.wijmo-wijlightbox-aniwrapper')) {
                    slideContainer = wrapper.parent();
                } else {
                    slideContainer = $.createWrapper(wrapper).css({ overflow: 'hidden' });
                    slideContainer.removeClass('ui-effects-wrapper');
                    slideContainer.addClass('wijmo-wijlightbox-aniwrapper');
                }

                direction = o.slideDirection || 'horizontal';
                w = curImage.outerWidth();
                h = curImage.outerHeight();

                if (direction === 'horizontal') {
                    curImage.width(w).css('float', next ? 'left' : 'right');
                    wrapper.width(2 * w).css({
                        left: (next ? 0 : -1 * w),
                        position: 'absolute'
                    });
                } else {
                    curImage.height(h);
                    wrapper.width(w).css({
                        top: (next ? 0 : -1 * h),
                        position: 'absolute'
                    }).height(2 * h);
                }

                player.appendTo(wrapper);
                $img = player.getElement();
                if (direction === 'horizontal') {
                    $img.width(w).css('float', next ? 'left' : 'right');
                } else {
                    $img.height(h);
                }

                this.container.data('animating.wijlightbox', true);
                slideCallback = function () {
                    curImage = wrapper.children(':last');
                    while (curImage.parent().is('.wijmo-wijlightbox-aniwrapper')) {
                        curImage.parent().replaceWith(curImage);
                    }
                    curImage.css({ float: '', width: '', height: '' });

                    if (o.autoSize && !self._isFullSize()) {
                        self._resize(complete);
                    } else {
                        if ($.isFunction(complete)) {
                            complete.apply(self);
                        }
                        self._refreshText();
                    }
                };
                slideOpts = {
                    mode: 'hide',
                    direction: direction === 'horizontal' ? (next ? 'left' : 'right') : (next ? 'up' : 'down'),
                    easing: animation.easing,
                    distance: direction === 'horizontal' ? w : h,
                    duration: animation.duration
                };
                if ($.effects) {
                    wrapper.effect('slide', slideOpts, slideCallback);
                } else {
                    self._slideAnimate(slideOpts, wrapper, slideCallback);
                }
            };

            wijlightbox.prototype._moveFrom = function (rect, animation, complete) {
                var self = this, o = this.options, toRect;

                if ($.isFunction(animation)) {
                    complete = animation;
                    animation = $.extend({}, self._defaults.resizeAnimation, o.resizeAnimation);
                } else {
                    animation = $.extend({}, self._defaults.resizeAnimation, o.resizeAnimation, animation);
                }

                self._removeText();
                if (animation.animated === 'none' || animation.duration <= 0) {
                    self._createText();
                    if ($.isFunction(complete)) {
                        complete.apply(self);
                    }

                    this.container.data('moving.wijlightbox', false);
                    return;
                }

                toRect = $.extend({
                    width: self.frame.width(),
                    height: self.frame.height()
                }, self.container.offset());

                self.frame.width(rect.width).height(rect.height);
                self.container.css({
                    left: rect.left,
                    top: rect.top,
                    width: self.frame.outerWidth(),
                    position: 'absolute',
                    opacity: ''
                });

                self._moveTo(toRect, animation, function () {
                    self.frame.width(toRect.width);
                    self.container.width(self.frame.outerWidth());
                    self._createText();
                    self.container.data('moving.wijlightbox', false);
                    if ($.isFunction(complete)) {
                        complete.apply(self);
                    }
                });
            };

            wijlightbox.prototype._moveTo = function (rect, animation, complete) {
                var self = this, o = this.options;

                if ($.isFunction(animation)) {
                    complete = animation;
                    animation = $.extend({}, self._defaults.resizeAnimation, o.resizeAnimation);
                } else {
                    animation = $.extend({}, self._defaults.resizeAnimation, o.resizeAnimation, animation);
                }

                var hd = animation.duration / 2, animated = animation.animated, movePos = self._isOpen(), pos1 = animated === 'wh' ? { left: rect.left, top: undefined } : { top: rect.top }, pos2 = animated === 'wh' ? { top: rect.top, left: undefined } : { left: rect.left }, size1 = animated === 'wh' ? { width: rect.width, height: undefined } : { height: rect.height }, size2 = animated === 'wh' ? { height: rect.height, width: undefined } : { width: rect.width };

                if (animated === 'wh' || animated === 'hw') {
                    if (movePos) {
                        self.container.animate(pos1, {
                            duration: hd,
                            easing: animation.easing,
                            queue: true
                        });
                    }

                    self.frame.animate(size1, {
                        duration: hd,
                        easing: animation.easing,
                        complete: function () {
                            if (movePos) {
                                self.container.animate(pos2, {
                                    duration: hd,
                                    easing: animation.easing,
                                    queue: true
                                });
                            }

                            self.frame.animate(size2, {
                                duration: hd,
                                easing: animation.easing,
                                complete: function () {
                                    self.container.data('moving.wijlightbox', false);
                                    if ($.isFunction(complete)) {
                                        complete.apply(self);
                                    }
                                }
                            });
                        }
                    });

                    return;
                }

                if (movePos) {
                    self.container.animate({
                        left: rect.left,
                        top: rect.top
                    }, {
                        duration: animation.duration,
                        easing: animation.easing,
                        queue: true
                    });
                }

                self.frame.animate({
                    width: rect.width,
                    height: rect.height,
                    opacity: 1
                }, {
                    duration: animation.duration,
                    easing: animation.easing,
                    complete: function () {
                        self.container.data('moving.wijlightbox', false);
                        if ($.isFunction(complete)) {
                            complete.apply(self);
                        }
                    }
                });
            };

            /** Shows the content in specified index.
            * @example $("#id").wijlightbox('show');
            * @param {number} index The zero-based index of the picture to show.
            */
            wijlightbox.prototype.show = function (index) {
                this._show(index);
                return this;
            };

            wijlightbox.prototype._resize = function (complete) {
                var self = this, rect = $.extend({}, self.container.offset(), {
                    width: self.frame.width(),
                    height: self.frame.height()
                });

                self._size();
                if (self._isOpen()) {
                    self._position();
                }

                self._moveFrom(rect, complete);
            };

            wijlightbox.prototype._onAfterShow = function () {
                var self = this, o = this.options, data;

                self._refreshNavButtons();
                self.container.data('animating.wijlightbox', false);

                if (!o.modal) {
                    self._hideOverlay();
                }

                data = {
                    index: o.activeIndex,
                    item: o.groupItems[o.activeIndex]
                };
                self._trigger('show', null, data);
                self._startTimer();
            };

            wijlightbox.prototype._show = function (item, next, complete) {
                var self = this, o = this.options, sq, index;

                if (this.container.data('showing.wijlightbox')) {
                    sq = [
                        function () {
                            self._show(item, next, complete);
                        }
                    ];
                    this.container.queue('showqueue', sq);
                    return this;
                }

                index = o.activeIndex;
                if (!$.isPlainObject(item)) {
                    index = item;
                    if (index < 0 || index >= o.groupItems.length) {
                        return this;
                    }
                    item = o.groupItems[index];
                }

                if (item) {
                    this.container.data('item.wijlightbox', item);
                }

                if (this._groupMode()) {
                    this._preload();
                }

                if ($.isFunction(next)) {
                    complete = next;
                    next = undefined;
                }

                if (!complete) {
                    complete = self._onAfterShow;
                }

                var data = {
                    index: index,
                    item: item
                };
                if (self._trigger('beforeShow', null, data) === false) {
                    return this;
                }

                this.container.data('showing.wijlightbox', true);
                var cleanup = function () {
                    if ($.isFunction(complete)) {
                        complete.apply(self);
                    }

                    self.container.data('showing.wijlightbox', false);
                    self.container.dequeue('showqueue');
                    self.container.clearQueue('showqueue');
                };

                self._refreshCounter(index);

                var prevPlayer = this.container.data('player.wijlightbox'), player, onload = function () {
                    self.container.data('playerwidth.wijlightbox', player.width);
                    self.container.data('playerheight.wijlightbox', player.height);

                    var animation = $.extend({}, self._defaults.transAnimation, o.transAnimation);
                    if (o.activeIndex === index || animation.animated === 'none' || animation.duration <= 0 || !self._isOpen()) {
                        o.activeIndex = index;
                        if (prevPlayer) {
                            prevPlayer.remove();
                        }
                        player.appendTo(self.content);
                        self._refreshText();
                        cleanup();
                        return;
                    }

                    if (o.cookie) {
                        self._cookie(o.activeIndex, o.cookie);
                    }

                    if (animation.animated === 'slide') {
                        next = (next === undefined) ? (index > o.activeIndex) : next;
                        self._slideTo(prevPlayer, player, animation, next, cleanup);

                        o.activeIndex = index;
                    } else {
                        o.activeIndex = index;
                        var fadeIn = function () {
                            if (player) {
                                player.appendTo(self.content, true);
                                player.fadeIn(animation.duration, cleanup);
                            }
                        };

                        if ($.browser.msie) {
                            self.frame.trigger('mouseleave');
                        }

                        var onFadeOut = function () {
                            if (prevPlayer) {
                                prevPlayer.remove();
                            }

                            if (o.autoSize && !self._isFullSize()) {
                                self._resize(fadeIn);
                            } else {
                                fadeIn();
                                self._refreshText();
                            }
                        };

                        if (prevPlayer) {
                            prevPlayer.fadeOut(animation.duration * 0.4, onFadeOut);
                        } else {
                            onFadeOut();
                        }
                    }
                };

                player = this._createPlayer(item, onload);

                return this;
            };

            /** Moves to the next panel.*/
            wijlightbox.prototype.next = function () {
                var o = this.options;
                if (!this._groupMode()) {
                    return false;
                }

                var index = o.activeIndex + 1;
                if (o.loop) {
                    index = index % o.groupItems.length;
                }

                if (index < o.groupItems.length) {
                    this._show(index, true);
                    return true;
                }
                return false;
            };

            /** Moves to the previous panel.*/
            wijlightbox.prototype.back = function () {
                var o = this.options;
                if (!this._groupMode()) {
                    return false;
                }

                var index = o.activeIndex - 1;
                if (o.loop) {
                    index = index < 0 ? o.groupItems.length - 1 : index;
                }

                if (index >= 0) {
                    this._show(index, false);
                    return true;
                }
                return false;
            };

            /**
            * Adjust the position of lightbox according to the "position" option set it originally to a new location. .
            * It is usually called after window resized.
            */
            wijlightbox.prototype.adjustPosition = function () {
                this._position();
            };

            /**
            * Determines whether the lightbox is currently displaying images automatically.See the play method for more information.
            * @returns {boolean} A value that indicate whether it is playing.
            */
            wijlightbox.prototype.isPlaying = function () {
                return !!this.container.data('playing.wijlightbox');
            };

            wijlightbox.prototype._startTimer = function () {
                if (!this.isPlaying() || !this._groupMode()) {
                    return;
                }

                var o = this.options, self = this, width;
                if (o.showTimer === true) {
                    if (!this.timerMeter) {
                        this._createTimerBar();
                    }
                    width = this.timerBar.width();
                    self.timerMeter.width('0');
                    self.timerMeter.animate({ width: width }, o.delay, null, function () {
                        if (self.isPlaying() && !self.next()) {
                            self.stop();
                        }
                    });
                } else {
                    window.setTimeout(function () {
                        if (self.isPlaying() && !self.next()) {
                            self.stop();
                        }
                    }, o.delay);
                }
            };

            /** Starts displaying the images in order automatically.*/
            wijlightbox.prototype.play = function () {
                var o = this.options;
                if (!this._groupMode()) {
                    return false;
                }

                if (!this.container.data('playing.wijlightbox')) {
                    this.container.data('playing.wijlightbox', true);
                }

                this._refreshCtrlButtons();
                this._hideNavButtons();
                if (o.activeIndex >= o.groupItems.length - 1) {
                    this._show(0);
                } else {
                    this._startTimer();
                }
            };

            /** Stops the slide playing mode.*/
            wijlightbox.prototype.stop = function () {
                this.container.removeData('playing.wijlightbox');

                this._refreshCtrlButtons();
                this._removeTimerBar();
            };

            wijlightbox.prototype._size = function (size, calcOnly) {
                var o = this.options, width = o.width, height = o.height, playerWidth = o.autoSize ? (this.container.data('playerwidth.wijlightbox') || width) : width, playerHeight = o.autoSize ? (this.container.data('playerheight.wijlightbox') || height) : height, player, ratio = playerHeight / playerWidth;

                if (typeof size === 'boolean') {
                    calcOnly = size;
                } else if ($.isPlainObject(size) && ('width' in size) && ('height' in size)) {
                    width = size.width;
                    height = size.height;
                } else {
                    player = this.container.data('player.wijlightbox');
                    if (o.autoSize && (player && player.name === 'img')) {
                        if (playerWidth > width) {
                            playerWidth = width;
                            playerHeight = Math.round(width * ratio);
                        }

                        if (playerHeight > height) {
                            playerHeight = height;
                            playerWidth = Math.round(height / ratio);
                        }
                    }

                    width = playerWidth;
                    height = playerHeight;

                    if (calcOnly) {
                        return { width: width, height: height };
                    }
                }

                this.frame.width(width).height(height);
                this.container.width(this.frame.outerWidth(true));
            };

            wijlightbox.prototype._position = function () {
                var o = this.options, myAt = [], offset = [0, 0], isVisible, pos = o.position;

                if (pos) {
                    // deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
                    if (typeof pos === 'string' || (typeof pos === 'object' && '0' in pos)) {
                        myAt = pos.split ? pos.split(' ') : [pos[0], pos[1]];
                        if (myAt.length === 1) {
                            myAt[1] = myAt[0];
                        }

                        $.each(['left', 'top'], function (i, offsetPosition) {
                            if (+myAt[i] === myAt[i]) {
                                offset[i] = myAt[i];
                                myAt[i] = offsetPosition;
                            }
                        });

                        pos = {
                            my: myAt.join(" "),
                            at: myAt.join(" "),
                            offset: offset.join(" ")
                        };
                    }

                    pos = $.extend({}, o.position, pos);
                }

                // need to show the dialog to get the actual offset in the position plugin
                isVisible = this.container.is(':visible');
                if (!isVisible) {
                    this.container.show();
                }

                this.container.css({ top: 0, left: 0 }).position(pos);
                if (!isVisible) {
                    this.container.hide();
                }
            };

            wijlightbox.prototype._getRelRect = function (rel) {
                var rect;
                if (rel) {
                    if ($.isPlainObject(rel) && ('left' in rel) && ('top' in rel) && ('width' in rel) && ('height' in rel)) {
                        rect = $.merge({}, rel);
                    } else {
                        rel = $(rel);
                    }

                    if (rel.jquery && rel.length) {
                        rect = $.extend({}, rel.offset(), {
                            width: rel.width(),
                            height: rel.height()
                        });
                    }
                }

                return rect;
            };

            wijlightbox.prototype._close = function (rel) {
                var o = this.options, self = this, rect, data, complete;

                if (!this._isOpen()) {
                    return;
                }
                data = { rel: rel };
                if (false === this._trigger('beforeClose', null, data)) {
                    return;
                }

                rel = data.rel;
                if (!rel && this._groupMode()) {
                    rel = o.groupItems[o.activeIndex].img;
                }

                this.container.data('moving.wijlightbox', true);
                this._hideAccessories(false);
                this._hideWaiting();
                this._hideOverlay();
                this.stop();

                complete = function () {
                    self._removePlayer();
                    self.container.hide();
                    self._trigger('close');

                    self.container.unbind('keypress.wijlightbox');
                    self.container.removeData('open.wijlightbox').removeData('rect.wijlightbox').removeData('moving.wijlightbox').removeData('fullsize.wijlightbox');

                    $(document).unbind('keydown.wijlightbox').unbind('click.wijlightbox');
                };

                rect = this._getRelRect(rel);
                if (!rect) {
                    if (this.container.data('rect.wijlightbox')) {
                        rect = this.container.data('rect.wijlightbox');
                    }
                }

                this._removeText();
                if (rect) {
                    this._moveTo(rect, { animated: 'sync', duration: 200 }, complete);
                    return;
                }

                complete.call();
                return this;
            };

            wijlightbox.prototype._isOpen = function () {
                return !!this.container.data('open.wijlightbox');
            };

            wijlightbox.prototype._open = function (rel, item) {
                if (this._isOpen()) {
                    return;
                }

                var o = this.options, self = this;
                if (this.toolBox) {
                    if (this._isFullSize()) {
                        this.toolBox.css({
                            top: '2px',
                            right: '4px'
                        });
                    } else {
                        this.toolBox.css({ top: '', right: '' });
                    }
                }

                var complete = function () {
                    if (o.modal) {
                        self._showOverlay();
                    }

                    if (o.showControlsOnHover) {
                        this._hideAccessories(false);
                    } else {
                        this._showAccessories(false);
                    }
                    var rect = self._getRelRect(rel);
                    self.container.css('opacity', 0);
                    self.container.show();
                    self._size();
                    self._createText(true);
                    self._refreshText(true);
                    self._position();
                    self.container.data('open.wijlightbox', true);

                    if (rel && rect) {
                        self.container.data('rect.wijlightbox', rect);
                        self._moveFrom(rect, { animated: 'sync' });
                    } else {
                        var animation = $.extend({}, self._defaults.transAnimation, o.transAnimation);
                        if (animation.animated === 'fade') {
                            self.container.hide();
                            self.container.fadeIn(animation.duration, function () {
                                self._createText();
                            });
                        } else {
                            self._createText();
                        }

                        this.container.data('moving.wijlightbox', false);
                    }

                    $(document).bind('keydown.wijlightbox', $.proxy(self, '_keyDownHandler')).bind('click.wijlightbox', function (e) {
                        var srcElement = e.target || e.srcElement;
                        if (self._isOpen() && !!o.closeOnOuterClick) {
                            if (srcElement !== self.container.get(0) && $(srcElement).parents().index(self.container) < 0) {
                                self._close();
                            }
                        }
                    });

                    if (o.autoPlay) {
                        this.play();
                    }

                    self._refreshNavButtons();
                    self._refreshDialogButtons();

                    var data = {
                        index: o.activeIndex,
                        item: o.groupItems[o.activeIndex]
                    };
                    self._trigger('show', null, data);
                    self._trigger('open');
                };

                this.container.data('moving.wijlightbox', true);
                this._show(item, true, complete);
                return this;
            };

            wijlightbox.prototype._getWinRect = function () {
                var $win = $(window);
                return $.extend({
                    width: $win.width(),
                    height: $win.height()
                }, $win.offset() || { left: 2, top: 2 });
            };

            wijlightbox.prototype._resizeHandler = function () {
                var self = this;

                self._removeText();
                self._size(self._getWinRect());
                self._createText();
            };

            wijlightbox.prototype._isFullSize = function () {
                return !!this.container.data('fullsize.wijlightbox');
            };

            wijlightbox.prototype._toggleFullSize = function () {
                var self = this, $win = $(window);

                if (!self._isOpen()) {
                    return;
                }

                if (this._isFullSize()) {
                    if (self.toolBox) {
                        self.toolBox.css({ top: '', right: '' });
                    }

                    this.container.data('fullsize.wijlightbox', false);
                    $win.unbind('resize.wijlightbox', $.proxy(this, '_resizeHandler'));
                    self._resize(function () {
                        self._adjustPlayerSize(self.content.innerWidth(), self.content.innerHeight());
                    });
                } else {
                    this.container.data('fullsize.wijlightbox', true);
                    $win.bind('resize.wijlightbox', $.proxy(this, '_resizeHandler'));

                    var toRect = self._getWinRect(), bd = this.frame.borderSize();

                    toRect.width -= bd.width;
                    toRect.height -= bd.height;
                    self._removeText();
                    self._moveTo(toRect, { animated: 'sync' }, function () {
                        if (self.toolBox) {
                            self.toolBox.css({ top: '2px', right: '4px' });
                        }

                        self.frame.width(toRect.width);
                        self.container.width(self.frame.outerWidth());
                        self._createText();

                        self._adjustPlayerSize(self.content.innerWidth(), self.content.innerHeight());
                    });
                }

                this._refreshDialogButtons();
            };

            wijlightbox.prototype._getExt = function (url) {
                var ext, m, regExt = /[0-9a-z]+$/i, q = url.indexOf("?");

                if (q > -1) {
                    url = url.substring(0, q);
                }

                m = url.match(regExt);
                if (m) {
                    ext = m[0].toLowerCase();
                }

                return ext;
            };

            wijlightbox.prototype._getPlayerName = function (url) {
                if (url.indexOf("#") === 0 || (url.indexOf("#") > 0 && url.indexOf(document.location.href) === 0)) {
                    return "inline";
                }

                var imgExt = ["bmp", "gif", "jpg", "jpeg", "png"], swfExt = ["swf"], flvExt = ["flv", "m4v"], qtExt = ["dv", "mov", "moov", "movie", "mp4", "avi", "mpg", "mpeg"], wmpExt = ["asf", "avi", "mpg", "mpeg", "wm", "wmv"], html5Video = ["mp4", "mpg", "mpeg", "ogg", "ogv"], ext = this._getExt(url);

                if (ext) {
                    if ($.inArray(ext, imgExt) >= 0) {
                        return "img";
                    }
                    if ($.inArray(ext, swfExt) >= 0) {
                        return "swf";
                    }
                    if ($.inArray(ext, flvExt) >= 0) {
                        return "flv";
                    }
                    if ($.inArray(ext, wmpExt) >= 0) {
                        return "wmp";
                    }
                    if ($.inArray(ext, qtExt) >= 0) {
                        return "qt";
                    }
                    if ($.inArray(ext, html5Video) >= 0) {
                        return "wijvideo";
                    }
                }
                return "iframe";
            };

            wijlightbox.prototype._adjustPlayerSize = function (width, height) {
                var player = this.container.data('player.wijlightbox');
                if (player && player.adjustSize) {
                    player.adjustSize(width, height);
                }
            };

            wijlightbox.prototype._removePlayer = function () {
                var player = this.container.data('player.wijlightbox');
                if (player) {
                    player.remove();
                    this.container.data('player.wijlightbox', null);
                }
            };

            wijlightbox.prototype._createPlayer = function (item, onload, onerror) {
                var playerName = item.player;
                if (!$.isFunction($.wijmo.wijlightbox[playerName])) {
                    throw "unknown player " + playerName;
                }

                var self = this, cached = false, player, handleLoad = function () {
                    cached = true;
                    this._hideWaiting();
                    if ($.isFunction(onload)) {
                        window.setTimeout(function () {
                            onload.apply(self);
                        }, 1);
                    }
                }, handlerError = function () {
                    this._hideWaiting();
                    if ($.isFunction(onerror)) {
                        onerror.apply(self);
                    }
                };

                player = new $.wijmo.wijlightbox[playerName](this, item, handleLoad, handlerError);
                this.container.data('player.wijlightbox', player);

                window.setTimeout(function () {
                    if (cached === false) {
                        self._showWaiting();
                    }
                }, 200);

                return player;
            };
            return wijlightbox;
        })(wijmo.wijmoWidget);
        _lightbox.wijlightbox = wijlightbox;

        var wijlightbox_options = (function () {
            function wijlightbox_options() {
                /** wijMobileCSS
                * @ignore
                */
                this.wijMobileCSS = {
                    header: "ui-header ui-bar-a",
                    content: "ui-body-c",
                    stateDefault: "ui-btn ui-btn-a",
                    stateHover: "ui-btn-down-a",
                    stateActive: "ui-btn-down-a",
                    iconPlay: "ui-icon-arrow-r",
                    iconPause: "ui-icon-grid"
                };
                /** Selector option for auto self initialization.
                * This option is internal.
                * @ignore
                */
                this.initSelector = ":jqmData(role='wijlightbox')";
                /** Determines the position of text description.
                * Possible values are:
                * 'inside', 'outside', 'overlay', 'titleOverlay' and 'none'
                * @type {string}
                * @example
                *  $("#id").wijlightbox({
                *      textPosition: 'titleOverlay'
                *  });
                */
                this.textPosition = 'overlay';
                /** Determines the maximum width of the content.
                * @example
                *  $("#id").wijlightbox({
                *      width: 800
                *  });
                */
                this.width = 600;
                /** Determines the maximum height of the content.
                * @example
                *  $("#id").wijlightbox({
                *      height: 500
                *  });
                */
                this.height = 400;
                /** A value determines whether to auto-size to
                * keep the original width/height ratio of content.
                * @example
                *  $("#id").wijlightbox({
                *      autoSize: false
                *  });
                */
                this.autoSize = true;
                /** Determines the name of player to host the content.
                * Possible values are:
                * 'inline', 'iframe', 'img', 'swf', 'flv', 'wmp', 'qt', 'wijvideo'
                * @example
                *  $("#id").wijlightbox({
                *      player: 'img'
                *  });
                */
                this.player = '';
                /** Determines the array of data items.
                * @example
                *  $("#id").wijlightbox({
                *      groupItems: []
                *  });
                */
                this.groupItems = null;
                /** Determines the root url for each item.
                */
                this.rootUrl = '';
                /** Determines the visibility of the control buttons.
                * Possible values are: 'play', 'stop' separated by '|'.
                * @example
                *  $("#id").wijlightbox({
                *      ctrlButtons: 'play|stop'
                *  });
                */
                this.ctrlButtons = '';
                /** Determines the visibility of the dialog buttons.
                * Possible values are: 'close', 'fullSize' separated by '|'.
                * @example
                *  $("#id").wijlightbox({
                *      dialogButtons: 'close|fullSize'
                *  });
                */
                this.dialogButtons = 'close';
                /** Determines the type counter style.
                * Possible values are: 'default', 'sequence'
                * @example
                *  $("#id").wijlightbox({
                *      counterType: 'sequence'
                *  });
                */
                this.counterType = 'default';
                /** Determines the text format of counter.
                * '[i]' and '[n]' are built-in parameters represents
                * the current page index and the number of pages.
                * @example
                *  $("#id").wijlightbox({
                *      counterFormat: '[i]/[n]'
                *  });
                */
                this.counterFormat = '[i] of [n]';
                /** Determines the maximum number of
                * digit buttons in sequence counter type.
                * @example
                *  $("#id").wijlightbox({
                *      counterLimit: 5
                *  });
                */
                this.counterLimit = 10;
                /** Determines whether to display the counter.
                * @example
                *  $("#id").wijlightbox({
                *      showCounter: false
                *  });
                */
                this.showCounter = true;
                /** Determines whether to display the navigation buttons.
                * @example
                *  $("#id").wijlightbox({
                *      showNavButtons: false
                *  });
                */
                this.showNavButtons = true;
                /** Determines whether to display the time bar.
                * @example
                *  $("#id").wijlightbox({
                *      showTimer: true
                *  });
                */
                this.showTimer = false;
                /** Determines the position of control buttons.
                * @remark Possible values are: 'inside', 'outside'
                * @example
                *  $("#id").wijlightbox({
                *      controlsPosition: 'outside'
                *  });
                */
                this.controlsPosition = 'inside';
                /** Determines whether to display the control buttons only when hovering the mouse over the content.
                * @example
                *  $("#id").wijlightbox({
                *      showControlsOnHover: false
                *  });
                */
                this.showControlsOnHover = true;
                /** Determines whether to pause the auto-play when clicking the content.
                * @example
                *  $("#id").wijlightbox({
                *      clickPause: true
                *  });
                */
                this.clickPause = false;
                /** Determines whether to allow keyboard navigation.
                * @example
                *  $("#id").wijlightbox({
                *      keyNav: true
                *  });
                */
                this.keyNav = false;
                /** Determines whether the window is modal.
                */
                this.modal = false;
                /** Determines the pop-up position of content window.
                * Please see jquery.ui.position for possible options.
                * @type {object}
                */
                this.position = {
                    my: 'center',
                    at: 'center',
                    of: window,
                    collision: 'fit',
                    // ensure that the titlebar is never outside the document
                    using: function (pos) {
                        var t = $(this);
                        t.css(pos);
                        var topOffset = t.offset().top;
                        if (topOffset < 0) {
                            t.css('top', pos.top - topOffset);
                        }
                    }
                };
                /** Determines the z-index of popup container.
                */
                this.zIndex = 1000;
                /** Determines whether to close the pop-up window
                * when a user presses the ESC key.
                */
                this.closeOnEscape = true;
                /** Determines whether to close the pop-up window
                * when user clicks on the outside of content.
                */
                this.closeOnOuterClick = true;
                /** Determines whether pages are automatically displayed in order.
                */
                this.autoPlay = false;
                /** Determines the time span in milliseconds
                * between panels in autoplay mode.
                */
                this.delay = 2000;
                /** Determines whether start from the first page
                * when reaching the end in autoplay mode.
                */
                this.loop = true;
                /** Store the latest active index in a cookie.
                * The cookie is then used to determine the initially active index
                * @type {object}
                * @remarks
                * if the activeIndex option is not defined.
                * This requires cookie plugin.
                * The object needs to have key/value pairs of
                * the form the cookie plugin expects as options.
                * e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
                */
                this.cookie = null;
                /** Determines the animation style when switching between pages.
                * Possible values are 'slide', 'fade', 'none'
                * @type {object}
                * @example
                *  $("#id").wijlightbox({
                *      transAnimation: {
                *         animated: slide
                *     }
                *  });
                */
                this.transAnimation = {
                    animated: "fade",
                    duration: 400,
                    easing: 'linear'
                };
                /** Determines the slide direction.
                * Possible values are: 'horizontal', 'vertical'
                * @example
                *  $("#id").wijlightbox({
                *      slideDirection: 'vertical'
                *  });
                */
                this.slideDirection = 'horizontal';
                /** Determines the animation style when resizing.
                * @type {object}
                * @example
                *  $("#id").wijlightbox({
                *      resizeAnimation: { animated: 'wh'}
                *  });
                */
                this.resizeAnimation = {
                    animated: 'sync',
                    duration: 400
                };
                /** Determines the animation style when showing the text.
                * @type {object}
                * @example
                *  $("#id").wijlightbox({
                *      textShowOption: {
                *         duration: 500,
                *         easing: 'linear'
                *     }
                *  });
                */
                this.textShowOption = {
                    duration: 300,
                    easing: 'linear'
                };
                /** Determines the animation style when hidding the text.
                * @type {object}
                * @example
                *  $("#id").wijlightbox({
                *      textHideOption: {
                *         duration: 500,
                *         easing: 'linear'
                *     }
                *  });
                */
                this.textHideOption = {
                    duration: 300,
                    easing: 'linear'
                };
                /** Determines whether to turn on the movie controls in movie player.
                */
                this.showMovieControls = true;
                /** Determines whether to turn on the autoplay option in movie player.
                */
                this.autoPlayMovies = true;
                /** Determines a hash object that contains parameters for a flash object.
                * @type {object}
                * @example
                *  $("#id").wijlightbox({
                *      flashParams: {
                *          autostart: true,
                *          allowscriptaccess: 'always'
                *      }
                *  });
                */
                this.flashParams = {
                    bgcolor: "#000000",
                    allowfullscreen: true
                };
                /** Determines a hash object that contains variants for a flash object.
                * @type {object}
                * @example
                *  $("#id").wijlightbox({
                *      flashVars: {
                *          backcolor: "0x000000",
                *          frontcolor: "0xCCCCCC"
                *      }
                *  });
                */
                this.flashVars = {};
                /** Version of Flash object.
                * @type {string}
                * @example
                *  $("#id").wijlightbox({
                *      flashVersion: "9.0.115"
                *  });
                */
                this.flashVersion = "9.0.115";
                /** Determines the relative path and name of the flash vedio player.
                * @example
                *  $("#id").wijlightbox({
                *      flvPlayer: "player\\myplayer.swf"
                *  });
                */
                this.flvPlayer = 'player\\player.swf';
                /** Determines the relative path and name of the flash installation guide.
                * @example
                *  $("#id").wijlightbox({
                *      flashInstall: "player\\installFlash.swf"
                *  });
                */
                this.flashInstall = 'player\\expressInstall.swf';
                /** The beforeShow event handler.
                * A function called before a page's content is shown.
                * @event
                */
                this.beforeShow = null;
                /** The show event handler.
                * A function called after a page's content is shown.
                * @event
                */
                this.show = null;
                /** The open event handler.
                * A function called after the popped up container is opened.
                * @event
                */
                this.open = null;
                /** The showbeforeClose event handler.
                * A function called before the popped up container is closed.
                * @event
                */
                this.beforeClose = null;
                /** The close event handler.
                * A function called after the popped up container is closed.
                * @event
                */
                this.close = null;
            }
            return wijlightbox_options;
        })();

        wijlightbox.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijlightbox_options());

        $.wijmo.registerWidget("wijlightbox", wijlightbox.prototype);

        $.extend($.wijmo.wijlightbox, {
            img: function (lightbox, item, onload, onerror) {
                this.name = 'img';
                this.lightbox = lightbox;
                this.item = item;
                this.url = this.lightbox._getUrl(item);

                var self = this;
                $('<img></img>').css({ width: 'auto', height: 'auto', display: 'none' }).appendTo(document.body).bind({
                    'load': function () {
                        var img = $(this);
                        self.width = item.width ? parseInt(item.width, 10) : img.width();
                        self.height = item.height ? parseInt(item.height, 10) : img.height();
                        img.remove();

                        if (onload && $.isFunction(onload)) {
                            onload.apply(lightbox);
                        }
                    },
                    'error': function () {
                        $(this).remove();
                        if (onerror && $.isFunction(onerror)) {
                            onerror.apply(lightbox);
                        }
                    }
                }).attr('src', this.url);
            },
            swf: function (lightbox, item, onload, onerror) {
                this.name = 'swf';
                var lo = lightbox.options;
                this.id = 'flashhost';
                this.lightbox = lightbox;
                this.item = item;
                this.url = this.lightbox._getUrl(item);

                this.width = item.width ? parseInt(item.width, 10) : lo.width;
                this.height = item.height ? parseInt(item.height, 10) : lo.height;
                if (onload && $.isFunction(onload)) {
                    onload.apply(lightbox);
                }
            },
            iframe: function (lightbox, item, onload, onerror) {
                this.name = 'swf';
                this.lightbox = lightbox;
                this.item = item;
                this.url = this.lightbox._getUrl(item);

                if (item.width) {
                    this.width = parseInt(item.width, 10);
                }
                if (item.height) {
                    this.height = parseInt(item.height, 10);
                }

                this.$iframe = $('<iframe></iframe>').addClass('wijmo-wijlightbox-iframe').attr({
                    frameborder: '0',
                    marginwidth: '0',
                    marginheight: '0',
                    scrolling: 'auto',
                    allowtransparency: 'true'
                }).hide().appendTo(lightbox.content).bind('load', function () {
                    if (onload && $.isFunction(onload)) {
                        onload.apply(lightbox);
                    }
                }).attr('src', this.url);
            },
            inline: function (lightbox, item, onload, onerror) {
                this.name = 'inline';
                var lo = lightbox.options, css = lo.wijCSS, frameCSS = "wijmo-wijlightbox-frame " + css.content;
                " " + css.cornerAll + " " + css.helperClearFix;
                this.lightbox = lightbox;
                this.item = item;

                this.width = item.width ? parseInt(item.width, 10) : lo.width;
                if (item.height) {
                    this.height = parseInt(item.height, 10);
                } else {
                    var $temp = $(this.item.href).clone().show().append('<br clear="all" />').wrap('<div class="wijmo-wijlightbox ' + css.widget + '">' + '<div class="' + frameCSS + '">' + '<div class="' + frameCSS + '">' + '<div class="wijmo-wijlightbox-content"> ' + '</div></div></div></div>').appendTo(document.body).width(this.width);
                    this.height = $temp.outerHeight(true) + 10;

                    $temp.unwrap();
                    $temp.remove();
                }

                if (onload && $.isFunction(onload)) {
                    onload.apply(lightbox);
                }
            },
            flv: function (lightbox, item, onload, onerror) {
                this.name = 'flv';
                var lo = lightbox.options;
                this.id = 'flvhost';
                this.lightbox = lightbox;
                this.item = item;
                this.url = this.lightbox._getUrl(item);

                var jwControllerHeight = 20;
                this.width = item.width ? parseInt(item.width, 10) : lo.width;
                this.height = item.height ? parseInt(item.height, 10) : lo.height;
                if (lo.showMovieControls) {
                    this.height += jwControllerHeight;
                }

                if (onload && $.isFunction(onload)) {
                    onload.apply(lightbox);
                }
            },
            wmp: function (lightbox, item, onload, onerror) {
                var lo = lightbox.options, wmpControllerHeight;

                this.name = 'wmp';
                this.id = 'wmphost';
                this.lightbox = lightbox;
                this.item = item;
                this.url = this.lightbox._getUrl(item);

                wmpControllerHeight = ($.browser.msie ? 70 : 45);
                this.width = item.width ? parseInt(item.width, 10) : lo.width;
                this.height = item.height ? parseInt(item.height, 10) : lo.height;
                if (lo.showMovieControls) {
                    this.height += wmpControllerHeight;
                }

                if (onload && $.isFunction(onload)) {
                    onload.apply(lightbox);
                }
            },
            qt: function (lightbox, item, onload, onerror) {
                var lo = lightbox.options, qtControllerHeight = 16;

                this.name = 'qt';
                this.id = 'qthost';
                this.lightbox = lightbox;
                this.item = item;
                this.url = this.lightbox._getUrl(item);

                this.width = item.width ? parseInt(item.width, 10) : lo.width;
                this.height = item.height ? parseInt(item.height, 10) : lo.height;
                if (lo.showMovieControls) {
                    this.height += qtControllerHeight;
                }

                if (onload && $.isFunction(onload)) {
                    onload.apply(lightbox);
                }
            },
            wijvideo: function (lightbox, item, onload, onerror) {
                var lo = lightbox.options;
                this.name = 'wijvideo';
                this.id = 'wijvideohost';
                this.lightbox = lightbox;
                this.item = item;
                this.url = this.lightbox._getUrl(item);
                this.wijvideosrc = (!!item.wijvideosrc && item.wijvideosrc !== "") ? this.lightbox._getUrl(item.wijvideosrc) : null;
                this.width = item.width ? parseInt(item.width, 10) : lo.width;
                this.height = item.height ? parseInt(item.height, 10) : lo.height;

                if (onload && $.isFunction(onload)) {
                    onload.apply(lightbox);
                }
            }
        });

        $.extend($.wijmo.wijlightbox.img.prototype, {
            appendTo: function ($content, hidden) {
                this.$element = $('<img></img>').addClass('wijmo-wijlightbox-image').attr('src', this.url);
                if (hidden) {
                    this.$element.hide();
                }
                if (this.lightbox.options.transAnimation && this.lightbox.options.transAnimation.animated == "fade") {
                    //fixed bug 20925
                    //"fade" animation will not clean the prev element sometimes.
                    if ($content.children().length) {
                        $content.empty();
                    }
                    this.$element.prependTo($content);
                } else {
                    this.$element.appendTo($content);
                }
            },
            remove: function () {
                if (this.$element) {
                    this.$element.remove();
                }
            },
            fadeOut: function (duration, complete) {
                if (this.$element) {
                    this.$element.fadeOut(duration, complete);
                }
            },
            fadeIn: function (duration, complete) {
                if (this.$element) {
                    this.$element.fadeIn(duration, complete);
                }
            },
            getElement: function () {
                return this.$element;
            }
        });

        $.extend($.wijmo.wijlightbox.swf.prototype, {
            appendTo: function ($content) {
                this.$container = $('<div/>').css({
                    width: '100%',
                    height: '100%',
                    overflow: 'hidden'
                }).attr('id', this.id).appendTo($content);

                var lo = this.lightbox.options, express = lo.flashInstall, version = lo.flashVersion, flashvars = lo.flashVars, params = lo.flashParams;
                S.flash.embedSWF(this.item.href, this.id, '100%', '100%', version, express, flashvars, params);
            },
            remove: function () {
                S.flash.expressInstallCallback();
                S.flash.removeSWF(this.id);
                this.$container.remove();
            },
            fadeOut: function (duration, complete) {
                if (this.$container) {
                    this.$container.fadeOut(duration, complete);
                }
            },
            fadeIn: function (duration, complete) {
                if (this.$container) {
                    this.$container.fadeIn(duration, complete);
                }
            },
            getElement: function () {
                return this.$container;
            }
        });

        $.extend($.wijmo.wijlightbox.iframe.prototype, {
            appendTo: function ($content, hidden) {
                if (!hidden) {
                    this.$iframe.show();
                }
            },
            remove: function () {
                if (this.$iframe) {
                    this.$iframe.remove();
                }
            },
            fadeOut: function (duration, complete) {
                if (this.$iframe) {
                    this.$iframe.fadeOut(duration, complete);
                }
            },
            fadeIn: function (duration, complete) {
                if (this.$iframe) {
                    this.$iframe.fadeIn(duration, complete);
                }
            },
            getElement: function () {
                return this.$iframe;
            }
        });

        $.extend($.wijmo.wijlightbox.inline.prototype, {
            appendTo: function ($content, hidden) {
                this.$element = $(this.item.href).clone().appendTo($content);
                if (!hidden) {
                    this.$element.show();
                }
            },
            remove: function () {
                if (this.$element) {
                    this.$element.remove();
                }
            },
            fadeOut: function (duration, complete) {
                if (this.$element) {
                    this.$element.fadeOut(duration, complete);
                }
            },
            fadeIn: function (duration, complete) {
                if (this.$element) {
                    this.$element.fadeIn(duration, complete);
                }
            },
            getElement: function () {
                return this.$element;
            }
        });

        $.extend($.wijmo.wijlightbox.flv.prototype, {
            appendTo: function ($content) {
                this.$container = $('<div/>').css({
                    width: '100%',
                    height: '100%',
                    overflow: 'hidden'
                }).attr('id', this.id).appendTo($content);

                var lo = this.lightbox.options, width = '100%', height = '100%', swf = lo.flvPlayer, express = lo.flashInstall, version = lo.flashVersion, flashvars = $.extend({
                    file: this.url,
                    width: width,
                    height: height,
                    autostart: (lo.autoPlayMovies ? 'true' : 'false'),
                    controlbar: (lo.showMovieControls ? 'bottom' : "none"),
                    backcolor: "0x000000",
                    frontcolor: "0xCCCCCC",
                    lightcolor: "0x557722"
                }, lo.flashVars), params = $.extend({
                    autostart: (lo.autoPlayMovies ? 'true' : 'false'),
                    allowscriptaccess: 'always'
                }, lo.flashParams);

                S.flash.embedSWF(swf, this.id, width, height, version, express, flashvars, params);
            },
            remove: function () {
                S.flash.expressInstallCallback();
                S.flash.removeSWF(this.id);
                this.$container.remove();
            },
            fadeOut: function (duration, complete) {
                if (this.$container) {
                    this.$container.fadeOut(duration, complete);
                }
            },
            fadeIn: function (duration, complete) {
                if (this.$container) {
                    this.$container.fadeIn(duration, complete);
                }
            },
            getElement: function () {
                return this.$container;
            }
        });

        $.extend($.wijmo.wijlightbox.wmp.prototype, {
            appendTo: function ($content) {
                this.$container = $('<div/>').css({
                    width: '100%',
                    height: '100%',
                    overflow: 'hidden'
                }).appendTo($content);

                var lo = this.lightbox.options, movie = '<object id="' + this.id + '" name="' + this.id + '" height="' + this.height + '" width="' + this.width + '"', params = {
                    autostart: lo.autoPlayMovies ? 1 : 0,
                    url: undefined,
                    uimode: undefined,
                    showcontrols: undefined
                }, p;
                if ($.browser.msie) {
                    movie += ' classid="clsid:6BF52A52-394A-11d3-B153-00C04F79FAA6"';
                    params.url = this.url;
                    params.uimode = lo.showMovieControls ? "full" : "none";
                } else {
                    movie += ' type="video/x-ms-wmv"';
                    movie += ' data="' + this.url + '"';
                    params.showcontrols = lo.showMovieControls ? 1 : 0;
                }
                movie += ">";
                for (p in params) {
                    movie += '<param name="' + p + '" value="' + params[p] + '">';
                }
                movie += "</object>";
                this.$container.html(movie);
            },
            remove: function () {
                if ($.browser.msie) {
                    try  {
                        window[this.id].controls.stop();
                        window[this.id].URL = "movie" + now() + ".wmv";
                        window[this.id] = function () {
                        };
                    } catch (e) {
                    }
                }

                this.$container.remove();
            },
            fadeOut: function (duration, complete) {
                if (this.$container) {
                    this.$container.fadeOut(duration, complete);
                }
            },
            fadeIn: function (duration, complete) {
                if (this.$container) {
                    this.$container.fadeIn(duration, complete);
                }
            },
            getElement: function () {
                return this.$container;
            }
        });

        $.extend($.wijmo.wijlightbox.qt.prototype, {
            appendTo: function ($content, first) {
                this.$container = $('<div/>').css({
                    width: '100%',
                    height: '100%',
                    overflow: 'hidden'
                }).appendTo($content);

                var lo = this.lightbox.options, autoplay = lo.autoPlayMovies ? 'true' : 'false', controls = lo.showMovieControls ? 'true' : 'false', movie = $.browser.msie ? "<object" : "<embed", attrs = {
                    id: this.id,
                    name: this.id,
                    width: this.width,
                    height: this.height,
                    kioskmode: "true",
                    classid: undefined,
                    codebase: undefined,
                    type: undefined,
                    src: undefined,
                    autoplay: undefined,
                    controller: undefined
                }, m, p;
                if ($.browser.msie) {
                    attrs.classid = "clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B";
                    attrs.codebase = "http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0";
                } else {
                    attrs.type = "video/quicktime";
                    attrs.src = this.url;
                    attrs.autoplay = autoplay;
                    attrs.controller = controls;
                }
                for (m in attrs) {
                    if (attrs[m]) {
                        movie += " " + m + '="' + attrs[m] + '"';
                    }
                }
                movie += ">";
                if ($.browser.msie) {
                    var params = {
                        src: this.url,
                        scale: "aspect",
                        controller: controls,
                        autoplay: autoplay
                    };
                    for (p in params) {
                        movie += '<param name="' + p + '" value="' + params[p] + '">';
                    }
                }
                movie += $.browser.msie ? "</object>" : "</embed>";
                if (first) {
                    $content.hide();
                }
                this.$container.html(movie);
                if (first) {
                    $content.show();
                }
            },
            remove: function () {
                try  {
                    document[this.id].Stop();
                    document[this.id] = null;
                } catch (e) {
                }

                this.$container.remove();
            },
            fadeOut: function (duration, complete) {
                complete.call();
                return;
                // if (this.$container) {
                //     this.$container.fadeOut(duration, complete);
                // }
            },
            fadeIn: function (duration, complete) {
                complete.call();
                return;
                // if (this.$container) {
                //     this.$container.fadeIn(duration, complete);
                // }
            },
            getElement: function () {
                return this.$container;
            }
        });

        $.extend($.wijmo.wijlightbox.wijvideo.prototype, {
            appendTo: function ($content) {
                var lo = this.lightbox.options;
                this.$container = $('<video/>').css({
                    overflow: 'hidden'
                }).attr({
                    width: this.width,
                    height: this.height,
                    autoPlay: (lo.autoPlayMovies ? 'true' : 'false'),
                    controls: (lo.showMovieControls ? 'controls' : '')
                }).appendTo($content);

                if (!!this.url) {
                    $('<source/>').attr({ src: this.url }).appendTo(this.$container);
                }

                if (!!this.wijvideosrc) {
                    $('<source/>').attr({ src: this.wijvideosrc }).appendTo(this.$container);
                }

                this.$container.wijvideo({ fullScreenButtonVisible: false });
            },
            remove: function () {
                this.$container.remove();
            },
            fadeOut: function (duration, complete) {
                if (this.$container) {
                    this.$container.fadeOut(duration, complete);
                }
            },
            fadeIn: function (duration, complete) {
                if (this.$container) {
                    this.$container.fadeIn(duration, complete);
                }
            },
            getElement: function () {
                return this.$container;
            },
            adjustSize: function (width, height) {
                this.$container.wijvideo('setWidth', width);
                this.$container.wijvideo('setHeight', height);
            }
        });

        $.extend($.wijmo.wijlightbox, {
            overlay: function (lightbox, waiting) {
                this.mask = $('<div></div>').addClass(lightbox.options.wijCSS.overlay + ' wijmo-wijlightbox-overlay' + (waiting ? " wijmo-wijlightbox-waitingoverlay" : "")).appendTo(document.body).css({
                    width: this.width(),
                    height: this.height()
                }).bind("click", function () {
                    if (lightbox.options.closeOnOuterClick) {
                        lightbox._close();
                    }
                    return false;
                });

                if ($.fn.bgiframe) {
                    this.mask.bgiframe();
                }

                if (waiting) {
                    this.mask.css('z-index', this.zIndex);
                    var $sandglass = $('<div></div>').addClass('wijmo-wijlightbox-waiting').css('z-index', this.zIndex + 1).appendTo(this.mask);

                    $sandglass.css({
                        left: (this.mask.width() - $sandglass.width()) / 2,
                        top: (this.mask.height() - $sandglass.height()) / 2
                    });
                }

                // handle window resize
                $(window).bind('resize.wijlightbox-overlay', $.proxy(this, 'resize'));

                window.setTimeout(function () {
                    var lay;
                    if (this.mask) {
                        lay = $.wijmo.wijlightbox.overlay;
                        $(document).bind(lay.events, function (event) {
                            if ($(event.target).zIndex() < lay.zIndex) {
                                return false;
                            }
                        });
                    }
                }, 1);
            }
        });

        $.extend($.wijmo.wijlightbox.overlay.prototype, {
            mask: null,
            zIndex: 1000,
            events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','), function (event) {
                return event + '.wijlightbox-overlay';
            }).join(' '),
            close: function () {
                $(document).unbind('.wijlightbox-overlay');
                $(window).unbind('.wijlightbox-overlay');
                this.mask.remove();
                this.mask = undefined;
            },
            height: function () {
                var scrollHeight, offsetHeight;

                // handle IE 6
                if ($.browser.msie && parseInt($.browser.version) < 7) {
                    scrollHeight = Math.max(document.documentElement.scrollHeight, document.body.scrollHeight);
                    offsetHeight = Math.max(document.documentElement.offsetHeight, document.body.offsetHeight);

                    if (scrollHeight < offsetHeight) {
                        return $(window).height();
                    } else {
                        return scrollHeight;
                    }
                    // handle "good" browsers
                } else {
                    return $(document).height();
                }
            },
            width: function () {
                var scrollWidth, offsetWidth;

                // handle IE 6
                if ($.browser.msie && parseInt($.browser.version) < 7) {
                    scrollWidth = Math.max(document.documentElement.scrollWidth, document.body.scrollWidth);
                    offsetWidth = Math.max(document.documentElement.offsetWidth, document.body.offsetWidth);

                    if (scrollWidth < offsetWidth) {
                        return $(window).width();
                    } else {
                        return scrollWidth;
                    }
                    // handle "good" browsers
                } else {
                    return $(document).width();
                }
            },
            resize: function () {
                if (this.mask) {
                    this.mask.css({
                        width: this.width(),
                        height: this.height()
                    });
                }
            }
        });
    })(wijmo.lightbox || (wijmo.lightbox = {}));
    var lightbox = wijmo.lightbox;
})(wijmo || (wijmo = {}));



;
/// <reference path="../wijbarchart/jquery.wijmo.wijbarchart.ts"/>
/// <reference path="../wijbubblechart/jquery.wijmo.wijbubblechart.ts"/>
/// <reference path="../wijpiechart/jquery.wijmo.wijpiechart.ts"/>
/// <reference path="../wijlinechart/jquery.wijmo.wijlinechart.ts"/>
/// <reference path="../wijscatterchart/jquery.wijmo.wijscatterchart.ts"/>
/// <reference path="../wijcandlestickchart/jquery.wijmo.wijcandlestickchart.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*globals jQuery, Globalize*/
    /*
    * Depends:
    *  raphael.js
    *  globalize.min.js
    *  jquery.ui.widget.js
    *  jquery.wijmo.wijchartcore.js
    *  jquery.wijmo.wijbarchart.js
    *  jquery.wijmo.wijlinechart.js
    *  jquery.wijmo.wijpiechart.js
    *  jquery.wijmo.wijscatterchart.js
    *
    */
    (function (_chart) {
        var wijcandlestickchartFn = $.wijmo.wijcandlestickchart;

        /**
        * @widget
        */
        var wijcompositechart = (function (_super) {
            __extends(wijcompositechart, _super);
            function wijcompositechart() {
                _super.apply(this, arguments);
            }
            wijcompositechart.prototype._create = function () {
                var self = this, o = self.options, defFill = self._getDefFill(), yAxis, yAxes, severOptions;

                $.each(o.seriesList, function (idx, series) {
                    if (series.type === "bar") {
                        if ($.isArray(o.axis.y)) {
                            $.each(o.axis.y, function (idx, yAxis) {
                                yAxis.compass = self._adjustCompassForBarChart(yAxis.compass, "y");
                            });
                        } else {
                            o.axis.y.compass = self._adjustCompassForBarChart(o.axis.y.compass, "y");
                        }
                        o.axis.x.compass = self._adjustCompassForBarChart(o.axis.x.compass, "x");
                        return true;
                    } else if (series.type === "pie" && series.pieSeriesList) {
                        series.data = series.pieSeriesList;
                    } else if (series.type === "sharedPie" && series.sharedPieChartSeries && series.sharedPieChartSeries.length > 0) {
                        $.each(series.sharedPieChartSeries, function (i, sPCSeries) {
                            if (sPCSeries.pieSeriesList) {
                                sPCSeries.data = sPCSeries.pieSeriesList;
                            }
                        });
                        series.data = series.sharedPieChartSeries;
                    } else if (series.candlestickSeries && series.candlestickSeries.data && $.inArray(series.type, ["hl", "ohlc", "candlestick"]) != -1) {
                        series.data = series.candlestickSeries.data;
                    } else if (series.type === _chart.ChartConsts.strTrendline) {
                        if (series.trendlineSeries) {
                            if (series.trendlineSeries.data) {
                                series.data = series.trendlineSeries.data;
                            }
                            series.fitType = series.trendlineSeries.fitType;
                            series.order = series.trendlineSeries.order;
                            series.sampleCount = series.trendlineSeries.sampleCount;
                        }
                    }
                });

                $.extend(true, {
                    compass: "east"
                }, o.hint);

                // set the is100percent to default value.
                if (o.is100Percent) {
                    o.is100Percent = false;
                }

                //add a new variable which type is set to any in order to access yAxes and the typescript builds successfully.
                severOptions = o;

                //handle the multiple y axis for extender, controls and AngularJS markup .
                if (severOptions.yAxes && $.isArray(severOptions.yAxes) && severOptions.yAxes.length > 0) {
                    // for composite chart, if user set the y axis option, here should get the settings from y axis.
                    yAxes = [];

                    //yAxis = $.extend(true, {}, o.axis.y);
                    //o.axis.y = o.yAxes;
                    $.each(severOptions.yAxes, function (i, axis) {
                        yAxes.push($.extend({}, severOptions.axis.y, axis));
                    });
                    o.axis.y = yAxes;
                }
                self._handleChartStyles();

                self._checkChartType();

                _super.prototype._create.call(this);
                self.chartElement.addClass(o.wijCSS.compositechart);
            };

            wijcompositechart.prototype._setOption = function (key, value) {
                // ignore the is100Percent option.
                if (key !== "is100Percent") {
                    if (key === "axis" && this.isContainsCandlestick) {
                        if (wijcandlestickchartFn) {
                            wijcandlestickchartFn.prototype._handleMaxMinInAxis.apply(this, [value]);
                        }
                    }
                    _super.prototype._setOption.call(this, key, value);
                }
            };

            wijcompositechart.prototype._seriesListSeted = function () {
                this._checkChartType();
                //if (this.isContainsCandlestick) {
                //    if (this.timeUtil) {
                //        this.timeUtil.dispose();
                //        this.timeUtil = null;
                //    }
                //	this._handleXDataForCandlestick();
                //}
            };

            wijcompositechart.prototype._supportStacked = function () {
                return true;
            };

            wijcompositechart.prototype._adjustCompassForBarChart = function (compass, axisType) {
                var adjustCompass;
                switch (compass) {
                    case "west":
                        if (axisType === "y") {
                            adjustCompass = "south";
                        } else {
                            adjustCompass = compass;
                        }
                        break;
                    case "east":
                        if (axisType === "y") {
                            adjustCompass = "north";
                        } else {
                            adjustCompass = compass;
                        }
                        break;
                    case "south":
                        if (axisType === "x") {
                            adjustCompass = "west";
                        } else {
                            adjustCompass = compass;
                        }
                        break;
                    case "north":
                        if (axisType === "x") {
                            adjustCompass = "east";
                        } else {
                            adjustCompass = compass;
                        }
                        break;
                    default:
                        if (axisType === "x") {
                            adjustCompass = "west";
                        } else {
                            adjustCompass = "south";
                        }
                        break;
                }
                return adjustCompass;
            };

            /**
            * Remove the functionality completely. This will return the element back to its pre-init state.
            */
            wijcompositechart.prototype.destroy = function () {
                var self = this, element = self.chartElement, fields = element.data("fields"), aniBarsAttr = fields && fields.aniBarsAttr;

                element.removeClass(self.options.wijCSS.compositechart);
                if (this.timeUtil) {
                    this.timeUtil.dispose();
                }
                _super.prototype.destroy.call(this);
                self._destroyRaphaelArray(aniBarsAttr);
                self.aniPathsAttr = null;

                element.data("fields", null);
            };

            wijcompositechart.prototype._isBarChart = function () {
                return true;
            };

            wijcompositechart.prototype._clearChartElement = function () {
                var self = this, o = self.options, element = self.chartElement, fields = element.data("fields");

                if (fields && fields.allElements) {
                    $.each(fields.allElements, function (key, eles) {
                        if (key === "scatters") {
                            if (eles.length) {
                                $.each(eles, function (i, ele) {
                                    if (ele.length) {
                                        $.each(ele, function (j, n) {
                                            if (n && n.remove) {
                                                n.remove();
                                            }
                                            ele[j] = null;
                                        });
                                        eles[i] = null;
                                    }
                                });
                            }
                        }
                        self._destroyRaphaelArray(eles);
                    });
                    fields.allElements = null;
                }

                _super.prototype._clearChartElement.call(this);
                if (fields && fields.ctracers) {
                    fields.ctracers = null;
                }

                self.element.removeData("plotInfos");

                if (!o.seriesTransition.enabled) {
                    if (fields && fields.aniBarsAttr) {
                        fields.aniBarsAttr = null;
                    }
                }

                if (fields && fields.pieSeriesTitles) {
                    self._destroyRaphaelArray(fields.pieSeriesTitles);
                }
            };

            // handle data bind
            wijcompositechart.prototype._bindSeriesData = function (ds, series, sharedXList) {
                var _this = this;
                var self = this, data = series.data, type = series.type, dataLabel, dataValue, dataOffset, pieData = [], sharedPieData;
                if (type === "pie") {
                    dataLabel = data.label;
                    dataValue = data.value;
                    dataOffset = data.offset;
                    if (dataLabel && dataLabel.bind) {
                        dataLabel = this._getBindData(ds, dataLabel.bind);
                    }
                    if (dataValue && dataValue.bind) {
                        dataValue = this._getBindData(ds, dataValue.bind);
                    }
                    if (dataOffset && dataOffset.bind) {
                        dataOffset = this._getBindData(ds, dataOffset.bind);
                    }
                    if (dataLabel && $.isArray(dataLabel) && dataLabel.length && dataValue && $.isArray(dataValue) && dataValue.length) {
                        $.each(dataValue, function (idx, val) {
                            var label, offset = 0;
                            if (idx >= 0 && idx < dataLabel.length) {
                                label = dataLabel[idx];
                            }
                            if (dataOffset && $.isArray(dataValue) && dataOffset.length && idx >= 0 && idx < dataOffset.length) {
                                offset = typeof dataOffset[idx] === 'undefined' ? 0 : dataOffset[idx];
                            }
                            pieData.push({
                                data: val,
                                label: label,
                                offset: offset,
                                legendEntry: true
                            });
                        });
                        series.data = pieData;
                    }
                } else if (type === "sharedPie") {
                    if ($.isArray(data)) {
                        series.sharedPieChartSeries = [];
                        $.each(data, function (pIndex, pData) {
                            var pieChartData = pData.data;
                            var pieDataSource = pData.datasource;
                            if (pieDataSource) {
                                dataLabel = pieChartData.label;
                                dataValue = pieChartData.value;
                                dataOffset = pieChartData.offset;
                                if (dataLabel && dataLabel.bind) {
                                    dataLabel = self._getBindData(pieDataSource, dataLabel.bind);
                                }
                                if (dataValue && dataValue.bind) {
                                    dataValue = self._getBindData(pieDataSource, dataValue.bind);
                                }
                                if (dataOffset && dataOffset.bind) {
                                    dataOffset = self._getBindData(pieDataSource, dataOffset.bind);
                                }
                                sharedPieData = {
                                    center: pData.center,
                                    label: pData.label,
                                    legendEntry: pData.legendEntry,
                                    radius: pData.radius,
                                    data: []
                                };
                                if (dataValue) {
                                    $.each(dataValue, function (idx, val) {
                                        var label, offset = 0;
                                        if (idx >= 0 && idx < dataLabel.length) {
                                            label = dataLabel[idx];
                                        }
                                        if (dataOffset && $.isArray(dataValue) && dataOffset.length && idx >= 0 && idx < dataOffset.length) {
                                            offset = typeof dataOffset[idx] === 'undefined' ? 0 : dataOffset[idx];
                                        }
                                        sharedPieData.data.push({
                                            data: val,
                                            label: label,
                                            offset: offset,
                                            legendEntry: true
                                        });
                                    });
                                }
                                series.sharedPieChartSeries.push(sharedPieData);
                            }
                        });

                        var sharedPieLegendInfors = [];
                        var pieSeries;

                        if (dataLabel && $.isArray(dataLabel)) {
                            $.each(dataLabel, function (dlIndex, label) {
                                pieSeries = {};
                                pieSeries.valueArray = [];
                                pieSeries.label = label;
                                pieSeries.legendEntry = (series.legendEntry !== false);

                                sharedPieLegendInfors.push(pieSeries);
                            });
                        }
                        series.sharedPieLegends = sharedPieLegendInfors;
                    }
                } else {
                    _super.prototype._bindSeriesData.call(this, ds, series, sharedXList);
                    if (data.x && $.isArray(data.x)) {
                        this.bindXData = true;
                    }
                    $.each(["high", "low", "open", "close", "y1"], function (i, name) {
                        var d = data[name];
                        if (d && d.bind) {
                            data[name] = _this._getBindData(ds, d.bind);
                        }
                    });
                }
            };

            wijcompositechart.prototype._preHandleSeriesData = function () {
                var self = this, o = self.options, tempPieSharedSeries, pieLegend;

                if (self.isContainsCandlestick) {
                    if (self.timeUtil) {
                        self.timeUtil.dispose();
                        self.timeUtil = null;
                    }
                    self._handleXDataForCandlestick();
                }

                _super.prototype._preHandleSeriesData.call(this);

                $.each(o.seriesList, function (i, series) {
                    if (series.type === "sharedPie") {
                        if (!series.sharedPieChartSeries || series.sharedPieChartSeries.length === 0) {
                            series.sharedPieChartSeries = [];
                            for (var j = 0; j < series.data.length; j++) {
                                if (series.data[j]) {
                                    series.sharedPieChartSeries.push(series.data[j]);
                                }
                            }
                        }
                        if (!series.sharedPieLegends || series.sharedPieLegends.length === 0) {
                            series.sharedPieLegends = [];
                            if (series.sharedPieChartSeries.length === 0) {
                                return;
                            }
                            tempPieSharedSeries = series.sharedPieChartSeries[0];
                            $.each(tempPieSharedSeries.data, function (tdIndex, tdata) {
                                pieLegend = {};
                                pieLegend.label = tdata.label;
                                pieLegend.legendEntry = tdata.legendEntry;
                                pieLegend.visible = (tdata.visible !== false);
                                series.sharedPieLegends.push(pieLegend);
                            });
                        }
                    }
                });
            };

            /**
            * Returns the raphael element with the given type and index.
            * @param {string} type The type of the chart element.
            * @param {number} index The index of the element.
            * @param {number} seriesIndex The index of the series.
            * @returns {Raphael Element} Returns the specified raphael object.
            */
            wijcompositechart.prototype.getElement = function (type, index, seriesIndex) {
                var element = this.chartElement, fields = element.data("fields"), chartElements = fields.chartElements;

                switch (type) {
                    case "bar":
                    case "column":
                        return chartElements.bars[index];
                    case "line":
                    case "area":
                        return chartElements.paths[index];
                    case "linemarkers":
                        return chartElements.markersSet[index];
                    case "pie":
                    case "sharedPie":
                        //return chartElements.sectors[index];
                        return this._getPie(chartElements, index, seriesIndex);
                    case _chart.ChartConsts.strTrendline:
                        return chartElements.trendLines[index];
                }

                return null;
            };

            wijcompositechart.prototype._getPie = function (chartElements, index, seriesIndex) {
                if (seriesIndex !== undefined) {
                    if (chartElements["sectors" + seriesIndex]) {
                        return chartElements["sectors" + seriesIndex][index];
                    }
                    return null;
                } else {
                    var sectors = [];
                    $.each(chartElements, function (key, val) {
                        if (/sectors/.test(key) && key !== "sectors") {
                            $.each(val, function (i, n) {
                                sectors.push(n);
                            });
                        }
                    });
                    if (sectors.length === 0) {
                        sectors = chartElements.sectors;
                    }
                    return sectors[index];
                }
            };

            wijcompositechart.prototype._getLegendSeriesInfoList = function () {
                var self = this, o = self.options, legendInfo, chartsSeries = o.seriesList, chartsSeriesStyles = o.seriesStyles, legendInfoList = [], seriesIdx = 0;
                $.each(chartsSeries, function (idx, series) {
                    var seriesType;
                    if (series.isTrendline) {
                        if (series.legendEntry !== false) {
                            legendInfo = self._getTrendLineLegendInfoFromSeries(seriesIdx, series, chartsSeriesStyles[seriesIdx]);
                            if (legendInfo) {
                                legendInfoList.push(legendInfo);
                            }
                        }
                        if (_chart.TrendlineRender.validateType(series.fitType)) {
                            seriesIdx++;
                        }
                    } else {
                        seriesType = series.type;
                        if (!(seriesType === "pie" || seriesType === "sharedPie")) {
                            if (series.legendEntry !== false) {
                                legendInfo = self._getLegendInfoFromSeries(seriesIdx, series, chartsSeriesStyles[seriesIdx]);
                                legendInfoList.push(legendInfo);
                            }
                            seriesIdx++;
                        } else {
                            var pieSeries = seriesType === "pie" ? series.data : series.sharedPieLegends;
                            $.each(pieSeries, function (j, data) {
                                data = $.extend({ legendEntry: series.legendEntry }, data);
                                if (data.legendEntry !== false) {
                                    legendInfo = self._getLegendInfoFromSeries(seriesIdx, data, chartsSeriesStyles[seriesIdx]);
                                    legendInfoList.push(legendInfo);
                                }
                                seriesIdx++;
                            });
                        }
                    }
                });

                return legendInfoList;
            };

            wijcompositechart.prototype._getLegendInfoFromSeries = function (seriesIdx, series, seriesStyle) {
                if (series.LegendEntry === false) {
                    return undefined;
                }

                var o = this.options, type = series.type, legendSize, strokeWidth, iconStyle, markerStyle, legendInfo;

                legendInfo = _super.prototype._getLegendInfoFromSeries.call(this, seriesIdx, series, seriesStyle);
                iconStyle = legendInfo.iconStyle;

                if (type === "line" || type === "area" || type === "spline" || type === "bezier") {
                    legendInfo.icon = "line";
                    legendSize = $.extend(true, { width: 22, height: 3 }, this.options.legend.size);
                    if (iconStyle) {
                        strokeWidth = legendSize.height;
                        iconStyle = $.extend(true, {}, iconStyle, {
                            "stroke-width": strokeWidth
                        });
                        if (iconStyle["stroke-dasharray"]) {
                            iconStyle = $.extend(true, {}, iconStyle, {
                                "stroke-width": 1,
                                "stroke-dasharray": iconStyle["stroke-dasharray"]
                            });
                        }
                    }
                    legendInfo.iconSize = legendSize;
                    legendInfo.iconStyle = iconStyle;
                    legendInfo.markers = series.markers ? series.markers.type : undefined;
                    legendInfo.markerVisible = series.markers ? series.markers.visible : false;

                    markerStyle = $.extend({
                        fill: iconStyle.stroke,
                        stroke: iconStyle.stroke,
                        opacity: 1
                    }, series.markerStyle);

                    legendInfo.markerStyle = markerStyle;
                } else if (type === "scatter" || type === "bubble") {
                    legendSize = $.extend(true, { width: 20, height: 10 }, this.options.legend.size);

                    var iconRadius = type === "scatter" ? 6 : (legendSize.r ? legendSize.r : Math.min(legendSize.width, legendSize.height));
                    markerStyle = $.extend({
                        fill: iconStyle.fill,
                        stroke: iconStyle.stroke,
                        opacity: 1
                    }, series.markerStyle);

                    legendInfo.iconStyle = markerStyle;

                    if (series.markerType) {
                        legendInfo.icon = series.markerType;
                    } else {
                        legendInfo.icon = "circle";
                    }

                    legendInfo.markers = undefined;
                    legendInfo.markerVisible = false;
                    legendInfo.markerStyle = undefined;
                    legendInfo.iconSize = $.extend(true, {}, { r: iconRadius }, legendSize);
                }

                return legendInfo;
            };

            wijcompositechart.prototype._showHideCandlestickSeries = function (seriesEle, type) {
                if (wijcandlestickchartFn) {
                    wijcandlestickchartFn.prototype._showHideSeries.apply(this, arguments);
                }
            };

            wijcompositechart.prototype._showSerieEles = function (seriesEle) {
                var type = seriesEle.type, eles = seriesEle.eles, sharedPieEles = [], showLabels = this.options.showChartLabels, dataObj;

                switch (type) {
                    case "pie":
                        if (eles) {
                            sharedPieEles = [seriesEle];
                        } else {
                            sharedPieEles = seriesEle.sharedSeriesEles;
                        }
                        $.each(sharedPieEles, function (i, seriseE) {
                            eles = seriseE.eles;
                            if (eles.sector) {
                                eles.sector.show();
                                if (eles.sector.shadow) {
                                    eles.sector.shadow.show();
                                }
                                if (eles.sector.tracker) {
                                    eles.sector.tracker.show();
                                }
                            }
                            if (eles.label) {
                                eles.label.show();
                            }
                        });
                        break;
                    case "line":
                    case "spline":
                    case "bezier":
                    case "area":
                        if (eles.markers) {
                            $.each(eles.markers, function (i, marker) {
                                dataObj = $(marker.node).data("wijchartDataObj");
                                if (dataObj && dataObj.lineSeries && dataObj.lineSeries.markers) {
                                    if (!dataObj.lineSeries.markers.visible) {
                                        return true;
                                    }
                                }
                                marker.show();
                            });
                        }

                        if (eles.dcl) {
                            $.each(eles.dcl, function (i, dcl) {
                                if (showLabels) {
                                    dcl.show();
                                }
                            });
                        }

                        if (eles.path) {
                            dataObj = $(eles.path.node).data("wijchartDataObj");

                            // if markers are invisible and line path is invisible, when click the legend, show the line path.
                            if (dataObj.visible || !(!dataObj.visible && dataObj.markers && dataObj.markers.visible)) {
                                eles.path.show();
                                if (eles.path.shadow) {
                                    eles.path.shadow.show();
                                }
                                if (eles.path.area) {
                                    eles.path.area.show();
                                }
                                if (eles.path.tracker) {
                                    eles.path.tracker.show();
                                }
                                if ($(eles.path.node).data("wijchartDataObj") && $(eles.path.node).data("wijchartDataObj").virtualMarkers) {
                                    $.each($(eles.path.node).data("wijchartDataObj").virtualMarkers, function (i, markerObj) {
                                        markerObj.visible = true;
                                    });
                                }
                            }
                        }
                        break;
                    case "bar":
                    case "column":
                        $.each(eles, function (i, bar) {
                            if (bar.bar) {
                                bar.bar.show();
                                if (bar.bar.shadow) {
                                    bar.bar.shadow.show();
                                }
                                if (bar.bar.tracker) {
                                    bar.bar.tracker.show();
                                }
                                if ($(bar.bar.node).data("wijchartDataObj")) {
                                    $(bar.bar.node).data("wijchartDataObj").visible = true;
                                }
                            }
                            if (bar.dcl) {
                                bar.dcl.show();
                            }
                            if (bar.animatedBar && !bar.animatedBar.removed) {
                                bar.animatedBar.show();
                            }
                        });
                        break;
                    case "scatter":
                        $.each(eles, function (i, dot) {
                            dot.show();
                            if (dot.label) {
                                dot.label.show();
                            }
                            if ($(dot.element).data("wijchartDataObj")) {
                                $(dot.element).data("wijchartDataObj").visible = true;
                            }
                        });
                        break;
                    case "ohlc":
                    case "hl":
                    case "candlestick":
                        this._showHideCandlestickSeries(eles, "show");
                        break;
                    case "bubble":
                        $.each(eles, function (i, bubbleInfo) {
                            if (bubbleInfo.bubble) {
                                bubbleInfo.bubble.show();
                                if (bubbleInfo.bubble.shadow) {
                                    bubbleInfo.bubble.shadow.show();
                                }
                                if (bubbleInfo.bubble.tracker) {
                                    bubbleInfo.bubble.tracker.show();
                                }
                                if ($(bubbleInfo.bubble.node).data("wijchartDataObj")) {
                                    $(bubbleInfo.bubble.node).data("wijchartDataObj").visible = true;
                                }
                            }
                            if (bubbleInfo.dcl) {
                                bubbleInfo.dcl.show();
                            }
                            if (bubbleInfo.symbol) {
                                bubbleInfo.symbol.show();
                            }
                        });
                    case _chart.ChartConsts.strTrendline:
                        _chart.TrendlineRender.showSerieEles(eles);
                        break;
                }
            };

            wijcompositechart.prototype._hideSerieEles = function (seriesEle) {
                var type = seriesEle.type, eles = seriesEle.eles, sharedPieEles = [];

                switch (type) {
                    case "pie":
                        if (eles) {
                            sharedPieEles = [seriesEle];
                        } else {
                            sharedPieEles = seriesEle.sharedSeriesEles;
                        }
                        $.each(sharedPieEles, function (i, seriseE) {
                            eles = seriseE.eles;
                            if (eles.sector) {
                                eles.sector.hide();
                                if (eles.sector.shadow) {
                                    eles.sector.shadow.hide();
                                }
                                if (eles.sector.tracker) {
                                    eles.sector.tracker.hide();
                                }
                            }
                            if (eles.label) {
                                eles.label.hide();
                            }
                        });
                        break;
                    case "line":
                    case "spline":
                    case "bezier":
                    case "area":
                        if (eles.markers) {
                            $.each(eles.markers, function (i, marker) {
                                marker.hide();
                            });
                        }

                        if (eles.dcl) {
                            $.each(eles.dcl, function (i, dcl) {
                                dcl.hide();
                            });
                        }

                        if (eles.path) {
                            eles.path.hide();
                            if (eles.path.shadow) {
                                eles.path.shadow.hide();
                            }
                            if (eles.path.area) {
                                eles.path.area.hide();
                            }
                            if (eles.path.tracker) {
                                eles.path.tracker.hide();
                            }
                            if ($(eles.path.node).data("wijchartDataObj") && $(eles.path.node).data("wijchartDataObj").virtualMarkers) {
                                $.each($(eles.path.node).data("wijchartDataObj").virtualMarkers, function (i, markerObj) {
                                    markerObj.visible = false;
                                });
                            }
                        }
                        break;
                    case _chart.ChartConsts.strTrendline:
                        _chart.TrendlineRender.hideSerieEles(eles);
                        break;
                    case "bar":
                    case "column":
                        $.each(eles, function (i, bar) {
                            if (bar.bar) {
                                bar.bar.hide();
                                if (bar.bar.shadow) {
                                    bar.bar.shadow.hide();
                                }
                                if (bar.bar.tracker) {
                                    bar.bar.tracker.hide();
                                }
                                if ($(bar.bar.node).data("wijchartDataObj")) {
                                    $(bar.bar.node).data("wijchartDataObj").visible = false;
                                }
                            }
                            if (bar.dcl) {
                                bar.dcl.hide();
                            }
                            if (bar.animatedBar && !bar.animatedBar.removed) {
                                bar.animatedBar.hide();
                            }
                        });
                        break;
                    case "scatter":
                        $.each(eles, function (i, dot) {
                            dot.hide();
                            if (dot.label) {
                                dot.label.hide();
                            }
                            if ($(dot.element).data("wijchartDataObj")) {
                                $(dot.element).data("wijchartDataObj").visible = false;
                            }
                        });
                        break;
                    case "ohlc":
                    case "hl":
                    case "candlestick":
                        this._showHideCandlestickSeries(eles, "hide");
                        break;
                    case "bubble":
                        $.each(eles, function (i, bubbleInfo) {
                            if (bubbleInfo.bubble) {
                                bubbleInfo.bubble.hide();
                                if (bubbleInfo.bubble.shadow) {
                                    bubbleInfo.bubble.shadow.hide();
                                }
                                if (bubbleInfo.bubble.tracker) {
                                    bubbleInfo.bubble.tracker.hide();
                                }
                                if ($(bubbleInfo.bubble.node).data("wijchartDataObj")) {
                                    $(bubbleInfo.bubble.node).data("wijchartDataObj").visible = false;
                                }
                            }
                            if (bubbleInfo.dcl) {
                                bubbleInfo.dcl.hide();
                            }
                            if (bubbleInfo.symbol) {
                                bubbleInfo.symbol.hide();
                            }
                        });
                        break;
                }
            };

            wijcompositechart.prototype._indicatorLineShowing = function (objs) {
                var type;
                _super.prototype._indicatorLineShowing.call(this, objs);
                $.each(objs, function (i, obj) {
                    type = obj.type;
                    if (type === "column" || type === "bar") {
                        if (obj.bar) {
                            obj.bar.attr(obj.hoverStyle);
                        }
                    } else if (type === "marker") {
                        if (obj.marker) {
                            obj.marker.attr(obj.markerHoverStyle);
                        }
                    } else if (type === "scatter") {
                        if (obj.dot) {
                            obj.dot.attr(obj.hoverStyle);
                            obj.dot.scale(1.5, 1.5);
                        }
                    }
                });
            };

            wijcompositechart.prototype._removeIndicatorStyles = function (objs) {
                var type;
                $.each(objs, function (i, obj) {
                    type = obj.type;
                    if (type === "column" || type === "bar") {
                        if (obj.bar) {
                            obj.bar.attr(obj.style);
                        }
                    } else if (type === "marker") {
                        if (obj.marker) {
                            obj.marker.attr(obj.markerStyle);
                            obj.marker.transform("s1");
                        }
                    } else if (type === "scatter") {
                        if (obj.dot) {
                            obj.dot.attr(obj.style);
                            obj.dot.scale(1, 1);
                        }
                    }
                });
            };

            wijcompositechart.prototype._paintTooltip = function () {
                var self = this, element = self.chartElement, fields = element.data("fields") || {}, ctracers = fields.ctracers || [];

                _super.prototype._paintTooltip.call(this);

                if (self.tooltip) {
                    $.each(ctracers, function (idx, ctracer) {
                        if (ctracer.trackers && ctracer.trackers.length) {
                            if (idx === 0) {
                                self.tooltip.setOptions({ relatedElement: ctracer.trackers[0] });
                            }
                        }
                    });
                }
            };

            wijcompositechart.prototype._setDefaultTooltipText = function (data) {
                if (data.type === "candlestick" && wijcandlestickchartFn) {
                    return wijcandlestickchartFn.prototype._setDefaultTooltipText.apply(this, arguments);
                }
                return _super.prototype._setDefaultTooltipText.call(this, data);
            };

            wijcompositechart.prototype._checkChartType = function () {
                var _this = this;
                this.isContainsBubble = false;
                this.isContainsCandlestick = false;

                $.each(this.options.seriesList, function (i, series) {
                    var type = series.type;
                    if (!_this.isContainsCandlestick && (type === "ohlc" || type === "hl" || type === "candlestick")) {
                        _this.isContainsCandlestick = true;
                    } else if (!_this.isContainsBubble && type === "bubble") {
                        _this.isContainsBubble = true;
                    }
                });
            };

            wijcompositechart.prototype._handleXDataForCandlestick = function () {
                if (wijcandlestickchartFn) {
                    wijcandlestickchartFn.prototype._handleXData.apply(this, arguments);
                }
            };

            wijcompositechart.prototype._isCandlestickSeries = function (series) {
                var type = series.type;
                return type === "ohlc" || type === "hl" || type === "candlestick";
            };

            wijcompositechart.prototype._paintChartArea = function () {
                var self = this, seriesList = self.options.seriesList;

                if (self._isSeriesListDataEmpty()) {
                    return;
                }

                // add the hl to data.y
                $.each(seriesList, function (i, n) {
                    var data = n.data;
                    if (self._isCandlestickSeries(n)) {
                        data.y = [].concat(data.high).concat(data.low);
                    }
                });

                if (this.bubbleAxisAdjust) {
                    this.bubbleAxisAdjust.dispose();
                }
                this.bubbleAxisAdjust = new _chart.BubbleAxisAdjust(this);

                _super.prototype._paintChartArea.call(this);

                // delete data.y;
                // and recover data.x
                $.each(seriesList, function (i, n) {
                    if (self._isCandlestickSeries(n)) {
                        delete n.data.y;
                    }
                    if (n.data && n.data.originalXValue) {
                        n.data.x = n.data.originalXValue;
                        delete n.data.originalXValue;
                    }
                });
            };

            wijcompositechart.prototype._checkSeriesDataEmpty = function (series) {
                var type = series.type, data = series.data, result = false, checkEmptyData = this._checkEmptyData;

                if (this._isCandlestickSeries(series)) {
                    if (!data || checkEmptyData(data.x) || checkEmptyData(data.high) || checkEmptyData(data.low)) {
                        return true;
                    }
                    if (type === "ohlc" || type === "candlestick") {
                        if (checkEmptyData(data.open) || checkEmptyData(data.low)) {
                            return true;
                        }
                    }
                    return false;
                } else if (type === "pie") {
                    if (!data || !$.isArray(data)) {
                        return true;
                    }
                    return false;
                } else if (type === "sharedPie") {
                    data = series.sharedPieChartSeries;

                    if (!data || !$.isArray(data)) {
                        result = true;
                    } else {
                        $.each(series.sharedPieChartSeries, function (ssIndex, ssItem) {
                            if (ssItem.data && $.isArray(ssItem.data)) {
                                result = false;
                                return false;
                            }
                        });
                    }
                    return result;
                } else {
                    if (type === "bubble") {
                        if (!data || checkEmptyData(data.y1)) {
                            return true;
                        }
                    }
                    return _super.prototype._checkSeriesDataEmpty.call(this, series);
                }
            };

            wijcompositechart.prototype._getXAxisInfoValueLabels = function (xAxisInfo, xAxisOptions) {
                if (this.isContainsCandlestick && xAxisInfo.id === "x") {
                    wijcandlestickchartFn.prototype._getXAxisInfoValueLabels.apply(this, arguments);
                } else {
                    _super.prototype._getXAxisInfoValueLabels.call(this, xAxisInfo, xAxisOptions);
                }
            };

            wijcompositechart.prototype._calculateMajorMinor = function (axisOptions, axisInfo) {
                if (this.isContainsCandlestick && axisInfo.id === "x") {
                    wijcandlestickchartFn.prototype._calculateMajorMinor.apply(this, arguments);
                } else {
                    _super.prototype._calculateMajorMinor.call(this, axisOptions, axisInfo);
                }
            };

            wijcompositechart.prototype._adjustXValueLabelsByMajorUnit = function (unitMajor, axisInfo) {
                if (this.isContainsCandlestick && axisInfo.id === "x") {
                    wijcandlestickchartFn.prototype._adjustXValueLabelsByMajorUnit.apply(this, arguments);
                }
            };

            wijcompositechart.prototype._getXTickText = function (text) {
                //return text;
                var self = this, formatString = self.formatString;
                if (self.isContainsCandlestick && wijcandlestickchartFn) {
                    return wijcandlestickchartFn.prototype._getXTickText.apply(this, arguments);
                }
                return text;
            };

            wijcompositechart.prototype._adjustTickValuesForCandlestickChart = function (tickValues) {
                if (this.isContainsCandlestick && wijcandlestickchartFn) {
                    return wijcandlestickchartFn.prototype._adjustTickValuesForCandlestickChart.apply(this, arguments);
                } else {
                    return _super.prototype._adjustTickValuesForCandlestickChart.call(this, tickValues);
                }
            };

            wijcompositechart.prototype._getTickTextForCalculateUnit = function (value, axisInfo, prec) {
                if (axisInfo.id === "x" && this.isContainsCandlestick) {
                    return wijcandlestickchartFn.prototype._getTickTextForCalculateUnit.apply(this, arguments);
                }
                return _super.prototype._getTickTextForCalculateUnit.call(this, value, axisInfo, prec);
            };

            wijcompositechart.prototype._AdjustAxisBounds = function (axisInfo, axisOptions) {
                var self = this, o = self.options, mx, mn, sizeMax, sizeMin, maxData = axisInfo.max, minData = axisInfo.min, dx = maxData - minData, prec = _chart.ChartDataUtil.nicePrecision(dx), _prec = prec + 1, bounds = axisInfo.bounds, textStyle = $.extend(true, {}, o.textStyle, axisOptions.textStyle, axisOptions.labels.style);

                mx = self._text(-1000, -1000, $.round(maxData, _prec).toString()).attr(textStyle);
                mn = self._text(-1000, -1000, $.round(minData, _prec).toString()).attr(textStyle);

                sizeMax = mx.wijGetBBox();
                sizeMin = mn.wijGetBBox();

                if (!axisInfo.isStartAxis) {
                    bounds.startY += sizeMin.height;
                }

                if (!axisInfo.isLastAxis) {
                    bounds.endY -= (sizeMax.height);
                }
            };

            wijcompositechart.prototype._initYAxisHeight = function () {
                var self = this, o = self.options, axisOpt = o.axis, yaxisOpt = axisOpt.y, bounds = self.canvasBounds, width = bounds.endX - bounds.startX, height = bounds.endY - bounds.startY, axisInfo = self.axisInfo, yAxisInfo = axisInfo.y, othersHeight = 0, autoHeightIndex = -1, totalHeight = 0, lastBounds;

                if ($.isArray(yaxisOpt)) {
                    $.each(yaxisOpt, function (i, axisOpt) {
                        if (axisOpt.height && !isNaN(axisOpt.height)) {
                            othersHeight += axisOpt.height;
                        } else if (axisOpt.height === "auto") {
                            autoHeightIndex = i;
                        }

                        yAxisInfo[i].height = axisOpt.height;
                    });

                    if (autoHeightIndex > -1) {
                        yAxisInfo[autoHeightIndex].height = height - othersHeight;
                    }

                    $.each(yAxisInfo, function (i, axis) {
                        var yHeight = axis.height;

                        if (yHeight === undefined || yHeight === null) {
                            return true;
                        }

                        if (yHeight > 0) {
                            axis.isPartAxis = true;
                            axis.isLastAxis = (parseInt(i) === yaxisOpt.length - 1);
                            axis.isStartAxis = parseInt(i) === 0;
                        }

                        if (!lastBounds) {
                            axis.bounds = {
                                startY: bounds.startY,
                                endY: bounds.startY + yHeight
                            };
                        } else {
                            axis.bounds = {
                                startY: lastBounds.endY,
                                endY: lastBounds.endY + yHeight
                            };
                        }
                        axis.bounds.startX = bounds.startX;
                        axis.bounds.endX = bounds.endX;
                        self._AdjustAxisBounds(axis, yaxisOpt[i]);
                        if (axis.bounds) {
                            lastBounds = $.extend({}, axis.bounds);
                        }
                    });
                }
            };

            wijcompositechart.prototype._getDataExtreme = function (isMultiYAxis) {
                var self = this;
                self._initYAxisHeight();
                return _super.prototype._getDataExtreme.call(this, isMultiYAxis);
            };

            wijcompositechart.prototype._getPieRendererData = function (series, pieID, styles, hoverStyles, styleStartIndex) {
                var pie = {}, style = {}, hoverStyle = {}, seriesData = series.data;
                pie.sIndex = styleStartIndex;

                $.each(seriesData, function (j, data) {
                    data.pieID = pieID;
                    style = $.extend({}, styles[styleStartIndex]);
                    hoverStyle = $.extend({}, hoverStyles[styleStartIndex]);

                    if (!pie["seriesList"]) {
                        pie["seriesList"] = [];
                    }

                    if (!pie["seriesStyles"]) {
                        pie["seriesStyles"] = [];
                    }

                    if (!pie["seriesHoverStyles"]) {
                        pie["seriesHoverStyles"] = [];
                    }
                    pie["seriesList"].push(data);
                    pie["seriesStyles"].push(style);
                    pie["seriesHoverStyles"].push(hoverStyle);

                    styleStartIndex++;
                });
                pie.radius = series.radius;
                pie.center = series.center;
                pie.label = series.label;

                return pie;
            };

            wijcompositechart.prototype._saveTrakers = function (mergeTrackers) {
                var self = this, o = self.options, field = self.chartElement.data("fields"), trackers = field.trackers, i;
                if (mergeTrackers && trackers && trackers.length) {
                    for (i = 0; i < trackers.length; i++) {
                        mergeTrackers.push(trackers[i]);
                    }
                }
            };

            wijcompositechart.prototype._paintPlotArea = function () {
                var self = this, o = self.options, seriesList = "seriesList", seriesStyles = "seriesStyles", seriesHoverStyles = "seriesHoverStyles", styles = o[seriesStyles], hoverStyles = o[seriesHoverStyles], bounds = self.canvasBounds, charts = {}, index = 0, pSIndex = -1, seriesIndexs = [], isMulityYAxis = $.isArray(o.axis.y), options = {
                    canvas: self.canvas,
                    tooltip: self.tooltip,
                    bounds: bounds,
                    widgetName: self.widgetName,
                    seriesTransition: o.seriesTransition,
                    showChartLabels: o.showChartLabels,
                    textStyle: o.textStyle,
                    chartLabelStyle: o.chartLabelStyle,
                    chartLabelFormatString: o.chartLabelFormatString,
                    chartLabelFormatter: o.chartLabelFormatter,
                    shadow: o.shadow,
                    stacked: o.stacked,
                    hint: o.hint,
                    animation: o.animation,
                    disabled: self._isDisabled(),
                    culture: self._getCulture(),
                    widget: this,
                    wijCSS: o.wijCSS,
                    mouseDown: function (e, args) {
                        self._trigger("mouseDown", e, args);
                    },
                    mouseUp: function (e, args) {
                        self._trigger("mouseUp", e, args);
                    },
                    mouseOver: function (e, args) {
                        self._trigger("mouseOver", e, args);
                    },
                    mouseOut: function (e, args) {
                        self._trigger("mouseOut", e, args);
                    },
                    mouseMove: function (e, args) {
                        self._trigger("mouseMove", e, args);
                    },
                    click: function (e, args) {
                        self._trigger("click", e, args);
                    }
                }, fields = self.chartElement.data("fields"), pieID = -1, stepIndex, tempSerieses, sharedPies, tmpOptions, chartgroup, _chartRender, mergeField, mergeTracker = self.canvas.set(), annoPoints = {};

                if (fields) {
                    fields.ctracers = [];
                }

                $.each(o[seriesList], function (i, series) {
                    var type = _chart.TrendlineRender.getSeriesChartType(series), chartItem = {}, chartType = type, pie = {}, style = $.extend({}, styles[index]), hoverStyle = $.extend({}, hoverStyles[index]), yAxis = series.yAxis;

                    if (!type || type.length === 0) {
                        return true;
                    }

                    if (chartType === "spline" || chartType === "bezier") {
                        chartType = "line";
                    }
                    if (chartType === "sharedPie") {
                        chartType = "pie";
                    }

                    chartItem = charts[chartType];

                    if (!chartItem) {
                        if (type === "pie" || type === "sharedPie") {
                            chartItem = [];
                        } else {
                            chartItem = {};
                        }

                        charts[chartType] = chartItem;

                        if (series.hint) {
                            chartItem.hint = series.hint;

                            if (!o.hint.content) {
                                o.hint.content = series.hint.content;
                            }

                            if (!o.hint.title) {
                                o.hint.title = series.hint.title;
                            }
                        }
                    }
                    if (type === "pie") {
                        if (pieID === -1) {
                            pieID = i + 1;
                        }
                        if (pSIndex === -1) {
                            pSIndex = index;
                        }

                        pie = self._getPieRendererData(series, pieID, styles, hoverStyles, index);

                        chartItem.push(pie);
                        pieID++;

                        index = pSIndex + (series.data.length ? series.data.length : 0);

                        pSIndex = -1;
                        return true;
                    } else if (type === "sharedPie") {
                        if (pieID === -1) {
                            pieID = i + 1;
                        }
                        tempSerieses = series.sharedPieChartSeries; // ? series.sharedPieChartSeries : [];
                        sharedPies = { type: "sharedPies", pies: [] };

                        if (pSIndex === -1) {
                            pSIndex = index;
                        }
                        $.each(tempSerieses, function (spindex, tSeries) {
                            pie = {};
                            tSeries.radius = tSeries.radius || series.radius;
                            tSeries.label = tSeries.label || series.label;
                            if (!tSeries.center && series.center) {
                                tSeries.center = { x: series.center.x, y: series.center.y };
                            }

                            index = pSIndex;
                            pie = self._getPieRendererData(tSeries, pieID, styles, hoverStyles, index);

                            sharedPies.pies.push(pie);
                            pieID++;
                            index = pSIndex + (tSeries.data.length ? tSeries.data.length : 0);
                        });
                        if (type === "sharedPie") {
                            chartItem.push(sharedPies);
                        }
                        pSIndex = -1;
                        return true;
                    } else if (type === "column") {
                        chartItem.horizontal = false;
                    } else if (type === "bar") {
                        chartItem.horizontal = true;
                    } else if (type === "spline") {
                        series.fitType = "spline";
                    } else if (type === "bezier") {
                        series.fitType = "bezier";
                    }

                    if (isMulityYAxis) {
                        chartItem.yAxis = yAxis || 0;
                    }

                    if (type === "line" || type === "spline" || type === "bezier" || type === _chart.ChartConsts.strTrendline) {
                        delete style.fill;
                        delete hoverStyle.fill;
                    }

                    if (!chartItem[seriesList]) {
                        chartItem[seriesList] = [];
                    }

                    if (!chartItem[seriesStyles]) {
                        chartItem[seriesStyles] = [];
                    }

                    if (!chartItem[seriesHoverStyles]) {
                        chartItem[seriesHoverStyles] = [];
                    }

                    if (type === "scatter") {
                        chartItem.showChartLabels = o.showChartLabels;
                        if (series.showChartLabels !== undefined) {
                            chartItem.showChartLabels = series.showChartLabels;
                        }
                    }

                    series.sIndex = index;
                    chartItem[seriesList].push(series);
                    chartItem[seriesStyles].push(style);
                    chartItem[seriesHoverStyles].push(hoverStyle);
                    index++;
                });

                $.each(charts, function (type, chartItem) {
                    var chartModule = wijmo.chart;
                    var yAxisIndex = chartItem.yAxis, chartLabel;

                    if (yAxisIndex !== undefined && self.axisInfo.y[yAxisIndex].bounds) {
                        options.bounds = self.axisInfo.y[yAxisIndex].bounds;
                    }

                    switch (type) {
                        case "pie":
                            var pSIndex;
                            $.each(chartItem, function (cidx, chartpie) {
                                var isSharedPie = (chartpie.type === "sharedPies"), pies = isSharedPie ? chartpie.pies : [chartpie];
                                $.each(pies, function (idx, pie) {
                                    var center = pie.center, r = pie.radius || 50, pieBounds, width = bounds.endX - bounds.startX, height = bounds.endY - bounds.startY, seriesTitleText = pie.label, seriesTitleStyle = $.extend(true, {}, o.textStyle, o.chartLabelStyle), seriesTitle, textBounds;
                                    if (width < 2 * r) {
                                        r = width / 2;
                                    }
                                    if (height < 2 * r) {
                                        r = height / 2;
                                    }
                                    pie.radius = r;

                                    center = center ? center : {
                                        x: bounds.startX + width / 2,
                                        y: bounds.startY + height / 2
                                    };

                                    pieBounds = {
                                        startX: center.x - r,
                                        startY: center.y - r,
                                        endX: center.x + r,
                                        endY: center.y + r
                                    };

                                    tmpOptions = $.extend(true, {}, options, {
                                        bounds: pieBounds,
                                        radius: r,
                                        isTouchBehaviorEnable: false
                                    }, pie);
                                    _chartRender = new chartModule.PieChartRender(self.chartElement, tmpOptions);
                                    _chartRender.render();

                                    if (isSharedPie && seriesTitleText && seriesTitleText.length) {
                                        seriesTitle = self._text(0, 0, seriesTitleText).attr(seriesTitleStyle);
                                        textBounds = seriesTitle.wijGetBBox();

                                        // Offset 6px : Avoid the title being too close to the pie chart.
                                        seriesTitle.transform(Raphael.format("...T{0},{1}", center.x, center.y - r - (textBounds.height / 2 + 6)));

                                        if (!self.chartElement.data("fields").pieSeriesTitles) {
                                            self.chartElement.data("fields").pieSeriesTitles = [];
                                        }
                                        self.chartElement.data("fields").pieSeriesTitles.push(seriesTitle);
                                    }
                                    self._saveTrakers(mergeTracker);
                                    self.chartElement.data("fields").aniSectorAttrs = null;
                                    self.chartElement.data("fields").aniLabelAttrs = null;
                                    self._savechartData(type, pie.sIndex);
                                });
                            });

                            break;
                        case "bar":
                        case "column":
                            tmpOptions = $.extend(true, {}, options, {
                                stacked: o.stacked,
                                axis: o.axis,
                                clusterOverlap: o.clusterOverlap,
                                clusterWidth: o.clusterWidth,
                                clusterSpacing: o.clusterSpacing,
                                is100Percent: o.is100Percent,
                                clusterRadius: o.clusterRadius,
                                isYTime: self.axisInfo.y[0].isTime,
                                isXTime: self.axisInfo.x.isTime,
                                yAxisInfo: self.axisInfo.y,
                                yAxisIndex: yAxisIndex
                            }, chartItem);
                            _chartRender = new chartModule.BarChartRender(self.chartElement, tmpOptions);
                            _chartRender.render();
                            $.each(tmpOptions.seriesList, function (i, e) {
                                annoPoints[e.sIndex] = _chartRender.annoPoints[i];
                            });
                            seriesIndexs = [];
                            $.each(chartItem.seriesList, function (i, sl) {
                                seriesIndexs.push(sl.sIndex);
                            });
                            self._saveTrakers(mergeTracker);
                            self._savechartData(type, seriesIndexs);
                            break;
                        case "line":
                        case "spline":
                        case "bezier":
                        case "area":
                            chartgroup = self._getyAxisGroup(chartItem);
                            if (!self.aniPathsAttr) {
                                self.aniPathsAttr = {};
                            }
                            $.each(chartgroup, function (ykey, subchart) {
                                if (!self.aniPathsAttr[ykey]) {
                                    self.aniPathsAttr[ykey] = [];
                                }
                                if (!self.aniPathsAttr[ykey][type]) {
                                    self.aniPathsAttr[ykey][type] = [];
                                }
                                tmpOptions = $.extend(true, {}, options, {
                                    axis: o.axis,
                                    isXTime: self.axisInfo.x.isTime,
                                    isYTime: self.axisInfo.y[0].isTime,
                                    //aniPathsAttr: self.aniPathsAttr,
                                    //chartLabelEles: self.chartLabelEles,
                                    type: type === "area" ? "area" : "line",
                                    hole: o.hole
                                }, subchart);
                                tmpOptions.aniPathsAttr = self.aniPathsAttr[ykey][type];
                                tmpOptions.chartLabelEles = self.chartLabelEles;
                                if (isMulityYAxis) {
                                    tmpOptions.axis.y = o.axis.y[ykey];
                                }

                                tmpOptions.extremeValue = {
                                    txx: self.extremeValue.txx,
                                    txn: self.extremeValue.txn,
                                    tyx: self.extremeValue.y[ykey].tyx,
                                    tyn: self.extremeValue.y[ykey].tyn
                                };
                                _chartRender = new chartModule.LineChartRender(self.chartElement, tmpOptions);
                                _chartRender.render();
                                $.each(tmpOptions.seriesList, function (i, e) {
                                    annoPoints[e.sIndex] = _chartRender.annoPoints[i];
                                });

                                seriesIndexs = [];
                                $.each(subchart.seriesList, function (i, sl) {
                                    seriesIndexs.push(sl.sIndex);
                                });
                                self._saveTrakers(mergeTracker);
                                self._savechartData(type, seriesIndexs);
                            });
                            break;
                        case _chart.ChartConsts.strTrendline:
                            chartgroup = self._getyAxisGroup(chartItem);
                            if (!self.aniPathsAttr) {
                                self.aniPathsAttr = {};
                            }
                            $.each(chartgroup, function (ykey, subchart) {
                                if (!self.aniPathsAttr[type]) {
                                    self.aniPathsAttr[type] = [];
                                }
                                tmpOptions = $.extend(true, {}, options, {
                                    axis: o.axis,
                                    hole: o.hole
                                }, subchart);
                                tmpOptions.aniPathsAttr = self.aniPathsAttr[type];
                                if (isMulityYAxis) {
                                    tmpOptions.axis.y = o.axis.y[ykey];
                                }

                                tmpOptions.extremeValue = {
                                    txx: self.extremeValue.txx,
                                    txn: self.extremeValue.txn,
                                    y: {}
                                };
                                tmpOptions.extremeValue.y[ykey] = self.extremeValue.y[ykey];
                                _chartRender = new chartModule.TrendlineRender(self.chartElement, tmpOptions);
                                _chartRender.render();
                                $.each(tmpOptions.seriesList, function (i, e) {
                                    annoPoints[e.sIndex] = _chartRender.annoPoints[i];
                                });
                                seriesIndexs = [];
                                $.each(subchart.seriesList, function (i, sl) {
                                    seriesIndexs.push(sl.sIndex);
                                });
                                self._savechartData(type, seriesIndexs);
                            });
                            break;
                        case "scatter":
                            chartgroup = self._getyAxisGroup(chartItem);
                            $.each(chartgroup, function (ykey, subchart) {
                                tmpOptions = $.extend(true, {}, options, {
                                    axis: o.axis,
                                    isXTime: self.axisInfo.x.isTime,
                                    isYTime: self.axisInfo.y[0].isTime,
                                    zoomOnHover: o.zoomOnHover
                                }, subchart);
                                if (isMulityYAxis) {
                                    tmpOptions.axis.y = o.axis.y[ykey];
                                }
                                _chartRender = new chartModule.ScatterChartRender(self.chartElement, tmpOptions);
                                _chartRender.render();
                                $.each(tmpOptions.seriesList, function (i, e) {
                                    annoPoints[e.sIndex] = _chartRender.annoPoints[i];
                                });
                                seriesIndexs = [];
                                $.each(subchart.seriesList, function (i, sl) {
                                    seriesIndexs.push(sl.sIndex);
                                });
                                self._savechartData(type, seriesIndexs);
                            });
                            break;
                        case "ohlc":
                        case "hl":
                        case "candlestick":
                            chartgroup = self._getyAxisGroup(chartItem);
                            $.each(chartgroup, function (ykey, subchart) {
                                tmpOptions = $.extend(true, {}, options, {
                                    axis: o.axis,
                                    timeUtil: self.timeUtil,
                                    type: type
                                }, subchart);
                                if (isMulityYAxis) {
                                    tmpOptions.axis.y = o.axis.y[ykey];
                                }

                                // extend the styles.
                                tmpOptions.seriesStyles = wijcandlestickchartFn.prototype._getStyles(type, tmpOptions.seriesStyles, "seriesStyles", true);
                                tmpOptions.seriesHoverStyles = wijcandlestickchartFn.prototype._getStyles(type, tmpOptions.seriesHoverStyles, "seriesHoverStyles", true);
                                _chartRender = new chartModule.CandlestickChartRender(self.chartElement, tmpOptions);
                                _chartRender.render();
                                $.each(tmpOptions.seriesList, function (i, e) {
                                    annoPoints[e.sIndex] = _chartRender.annoPoints[i];
                                });
                                seriesIndexs = [];
                                $.each(subchart.seriesList, function (i, sl) {
                                    seriesIndexs.push(sl.sIndex);
                                });
                                self._savechartData(type, seriesIndexs);
                                self._saveTrakers(mergeTracker);
                            });
                            break;
                        case "bubble":
                            chartgroup = self._getyAxisGroup(chartItem);

                            if (!chartLabel) {
                                chartLabel = { visible: o.showChartLabels, style: o.chartLabelStyle };
                            }

                            $.each(chartgroup, function (ykey, subchart) {
                                tmpOptions = $.extend(true, {}, options, {
                                    axis: o.axis,
                                    isXTime: self.axisInfo.x.isTime,
                                    isYTime: self.axisInfo.y[0].isTime,
                                    xAxisInfo: self.axisInfo.x,
                                    yAxisInfo: self.axisInfo.y,
                                    chartLabel: chartLabel,
                                    minimumSize: o.minimumSize || 5,
                                    maximumSize: o.maximumSize || 20,
                                    sizingMethod: o.sizingMethod || "diameter",
                                    bubbleRadius: self.bubbleAxisAdjust.bubbleRadius
                                }, subchart);

                                if (isMulityYAxis) {
                                    tmpOptions.axis.y = o.axis.y[ykey];
                                }
                                tmpOptions.yAxisInfo = self.axisInfo.y[ykey] || self.axisInfo.y[0];
                                _chartRender = new chartModule.BubbleChartRender(self.chartElement, tmpOptions);
                                _chartRender.render();
                                $.each(tmpOptions.seriesList, function (i, e) {
                                    annoPoints[e.sIndex] = _chartRender.annoPoints[i];
                                });

                                seriesIndexs = [];
                                $.each(subchart.seriesList, function (i, sl) {
                                    seriesIndexs.push(sl.sIndex);
                                });
                                self._savechartData(type, seriesIndexs);
                                self._saveTrakers(mergeTracker);
                            });
                            break;
                            break;
                    }
                });
                self.chartElement.data("fields").seriesEles = null;
                mergeField = self.chartElement.data("fields");
                if (mergeField) {
                    mergeField.trackers = mergeTracker;
                    self.chartElement.data("fields", mergeField);
                }
                self._bindtooltip();
                self._paintAnnotations(options, annoPoints);
            };

            wijcompositechart.prototype._paintAnnotations = function (options, annoPoints) {
                var self = this, o = self.options, compositeChartRender = new CompositeChartRender(self.chartElement, $.extend(true, {}, options, {
                    annotations: o.annotations,
                    axis: o.axis,
                    hint: o.hint,
                    seriesList: o.seriesList
                }));
                compositeChartRender.annoPoints = annoPoints;
                compositeChartRender.render();
            };

            wijcompositechart.prototype._savechartData = function (type, sIndex) {
                var self = this, fields = self.chartElement.data("fields"), seriesEles = fields.seriesEles, allElements = fields.allElements || {}, ctracers, index = sIndex, sharedSeriesEles;

                if ($.isArray(index)) {
                    index = 0;
                }
                $.each(seriesEles, function (i, ele) {
                    // fixed the issue for legend click.
                    if ($.isArray(sIndex)) {
                        self.seriesEles[sIndex[index]] = { eles: ele, type: type };
                        index++;
                    } else {
                        if (type === "pie" && self.seriesEles[index]) {
                            if (!self.seriesEles[index].sharedSeriesEles) {
                                sharedSeriesEles = [self.seriesEles[index]];
                                self.seriesEles[index] = { type: "pie", sharedSeriesEles: sharedSeriesEles };
                            }

                            self.seriesEles[index].sharedSeriesEles.push({ eles: ele, type: type });
                        } else {
                            self.seriesEles[index] = { eles: ele, type: type };
                        }
                        index++;
                    }
                });

                ctracers = fields.ctracers || [];
                ctracers.push({
                    trackers: fields.trackers,
                    type: type
                });
                fields.ctracers = ctracers;

                if (fields && fields.chartElements) {
                    $.each(fields.chartElements, function (key, eles) {
                        self._copyElements(allElements, key, eles);
                    });
                }
                fields.allElements = allElements;
            };

            wijcompositechart.prototype._copyElements = function (target, key, source) {
                var tar;
                if (source && $.isArray(source)) {
                    tar = target[key] || [];
                    target[key] = tar.concat(source);
                } else if (source) {
                    tar = target[key] || [];
                    tar.concat([source]);
                }
            };

            wijcompositechart.prototype._getyAxisGroup = function (chart) {
                var group = {};
                $.each(chart.seriesList, function (idx, series) {
                    var yAxis = series.yAxis || 0;
                    if (!group[yAxis]) {
                        group[yAxis] = {
                            seriesList: [],
                            seriesStyles: [],
                            seriesHoverStyles: []
                        };
                    }
                    group[yAxis].seriesList.push(series);
                    group[yAxis].seriesStyles.push(chart.seriesStyles[idx]);
                    group[yAxis].seriesHoverStyles.push(chart.seriesHoverStyles[idx]);
                });
                return group;
            };

            wijcompositechart.prototype._bindtooltip = function () {
                var self = this, namespace = self.widgetName, fields = self.chartElement.data("fields");
                if (fields && fields.ctracers) {
                    $.each(fields.ctracers, function (index, ctracer) {
                        var type = ctracer.type;
                        if (ctracer.trackers) {
                            ctracer.trackers.toFront();
                        }
                    });
                }

                self.chartElement.delegate(".linetracker, .wijchart-canvas-marker, .bartracker, .pietracker, .wijscatterchart, .bubbletracker, .candlesticktracker, .trendlinetracker", "mouseover." + namespace, $.proxy(self._tooltipMouseOver, self));
                self.chartElement.delegate(".linetracker, .wijchart-canvas-marker, .bartracker, .pietracker, .wijscatterchart, .bubbletracker, .candlesticktracker, .trendlinetracker", "mouseout." + namespace, $.proxy(self._tooltipMouseOut, self));
                self.chartElement.delegate(".linetracker, .wijchart-canvas-marker, .bartracker, .pietracker, .wijscatterchart, .bubbletracker, .candlesticktracker, .trendlinetracker", "mousemove." + namespace, $.proxy(self._tooltipMouseMove, self));
            };

            wijcompositechart.prototype._tooltipMouseOver = function (e) {
                var target = e.target, self = this, tooltip = self.tooltip, hint = self.options.hint, op = null, title = hint.title, content = hint.content, hintStyle = hint.style, isTitleFunc = $.isFunction(title), isContentFunc = $.isFunction(content), data, bbox, position, raphaelObj;

                position = $(self.canvas.canvas.parentNode).offset();
                if (self.indicatorLine) {
                    return;
                }

                if ($(target).data("owner")) {
                    target = $(target).data("owner");
                }
                target = $(target);
                data = target.data("wijchartDataObj");
                if (self.tooltip) {
                    op = tooltip.getOptions();
                    if (isTitleFunc || isContentFunc) {
                        if (isTitleFunc) {
                            op.title = $.proxy(title, data);
                        }
                        if (isContentFunc) {
                            op.content = $.proxy(content, data);
                        }
                    }
                    if (data.type === "line" || data.type === "marker") {
                        if (data.type === "marker") {
                            data = data.lineSeries;
                        }
                        if (data.path.removed) {
                            return;
                        }
                        if (self.hoverLine !== data || self.hoverLine === null) {
                            self.isNewLine = true;
                            if (self.hoverLine) {
                                if (!self.hoverLine.path.removed) {
                                    self.hoverLine.path.wijAttr(self.hoverLine.lineStyle);
                                    if (self.hoverPoint && !self.hoverPoint.isSymbol) {
                                        self.hoverPoint.marker.wijAttr(self.hoverPoint.markerStyle);
                                        self.hoverPoint.marker.transform("s1");
                                    }
                                }
                            }
                            if (data.lineHoverStyle) {
                                data.path.wijAttr(data.lineHoverStyle);
                            }
                            self.hoverLine = data;
                            self.hoverPoint = null;
                            self.hoverVirtualPoint = null;
                        }
                    } else if (data.type === "scatter" || hint.relativeTo === "element") {
                        self._clearHoverState();
                        if (data.type === "scatter") {
                            bbox = data.dot.getBBox();
                        } else if (target[0] && target[0].raphael && target[0].raphaelid) {
                            raphaelObj = self.canvas.getById(target[0].raphaelid);
                            if (raphaelObj) {
                                bbox = raphaelObj.getBBox();
                            }
                        }
                        op.style.stroke = hintStyle.stroke || target.attr("stroke");
                        if (bbox) {
                            self.tooltip.showAt({
                                x: bbox.x + bbox.width / 2,
                                y: bbox.y
                            }, e);
                        }
                    } else {
                        self._clearHoverState();
                        if (data.type === _chart.ChartConsts.strTrendline) {
                            return;
                        }
                        op.style.stroke = hintStyle.stroke || target.attr("stroke");
                        self.tooltip.showAt({
                            x: e.pageX - position.left,
                            y: e.pageY - position.top
                        }, e);
                    }
                }
            };

            wijcompositechart.prototype._tooltipMouseMove = function (e) {
                var self = this, target = e.target, data, hint = self.options.hint, position = $(self.canvas.canvas.parentNode).offset();

                if ($(target).data("owner")) {
                    target = $(target).data("owner");
                }
                target = $(target);
                data = target.data("wijchartDataObj");

                if (self.tooltip && !this.indicatorLine) {
                    if (data.type !== "line" && data.type !== "marker" && data.type !== "scatter" && hint.relativeTo !== "element" && data.type !== _chart.ChartConsts.strTrendline) {
                        self.tooltip.showAt({
                            x: e.pageX - position.left,
                            y: e.pageY - position.top
                        }, e);
                    }
                }
            };

            wijcompositechart.prototype._tooltipMouseOut = function (e) {
                var self = this, target = e.target, data;

                if ($(target).data("owner")) {
                    target = $(target).data("owner");
                }
                target = $(target);
                data = target.data("wijchartDataObj");
                if (data.type !== "line" && data.type !== "marker" && !self.indicatorLine) {
                    if (self.tooltip) {
                        self.tooltip.hide();
                    }
                }
            };

            wijcompositechart.prototype._mouseMoveInsidePlotArea = function (e, mousePos) {
                var self = this, tooltip = self.tooltip, hint = self.options.hint, markers, virtualMarkers, idx = 0, p, point, valueX, valueY, s = null, dataObj = null, op = null, title = hint.title, content = hint.content, isTitleFunc = $.isFunction(title), isContentFunc = $.isFunction(content), distance = 0, hoverLine;

                if (tooltip) {
                    op = tooltip.getOptions();
                }

                if (self.hoverLine && !self.indicatorLine) {
                    hoverLine = self.hoverLine;
                    if (self.isNewLine) {
                        if (hint.enable && tooltip) {
                            tooltip.hide();
                        }
                        self.isNewLine = false;
                    }
                    markers = hoverLine.lineMarkers;
                    virtualMarkers = hoverLine.virtualMarkers;
                    idx = -1;
                    p = { x: 0, y: 0 };
                    if (markers && markers.length) {
                        $.each(markers, function (i, marker) {
                            if (marker.removed) {
                                return true;
                            }
                            var box = marker.wijGetBBox(), pos = box.x + box.width / 2, dis = Math.abs(pos - mousePos.left);
                            if (i === 0 || dis < distance) {
                                distance = dis;
                                idx = i;
                                p = {
                                    x: pos,
                                    y: box.y + box.height / 2
                                };
                            }
                        });
                        if (self.hoverPoint && self.hoverPoint.index === idx) {
                            return;
                        }
                        if (idx > -1) {
                            if (markers[idx].removed) {
                                return;
                            }
                            point = $(markers[idx].node).data("wijchartDataObj");

                            if (point) {
                                if (self.hoverPoint && !self.hoverPoint.isSymbol) {
                                    if (!self.hoverPoint.removed) {
                                        self.hoverPoint.marker.wijAttr(self.hoverPoint.markerStyle);
                                        self.hoverPoint.marker.transform("s1");
                                    }
                                }
                                if (!point.isSymbol) {
                                    if (!point.marker.removed) {
                                        point.marker.wijAttr(point.markerHoverStyle);
                                    }
                                }
                            }

                            self.hoverPoint = point;
                            self.hoverVirtualPoint = virtualMarkers[idx];
                        }
                    } else {
                        $.each(virtualMarkers, function (i, marker) {
                            var dis = Math.abs(marker.x - mousePos.left);
                            if (i === 0 || dis < distance) {
                                distance = dis;
                                idx = i;
                                p = {
                                    x: marker.x,
                                    y: marker.y
                                };
                            }
                        });
                        if (self.hoverVirtualPoint && self.hoverVirtualPoint.index === idx) {
                            return;
                        }
                        if (idx > -1) {
                            self.hoverPoint = null;
                            self.hoverVirtualPoint = virtualMarkers[idx];
                        }
                    }
                    if (tooltip) {
                        dataObj = self.hoverVirtualPoint;
                        valueX = dataObj.valX;
                        valueY = dataObj.valY;

                        //dataObj = self.hoverPoint;
                        //valueX = dataObj.valX;
                        //valueY = dataObj.valY;
                        if (isTitleFunc || isContentFunc) {
                            if (isTitleFunc) {
                                op.title = function () {
                                    var obj = {
                                        pointIndex: idx,
                                        //lineIndex: dataObj.lineSeries.index,
                                        lineIndex: hoverLine.index,
                                        x: valueX,
                                        y: valueY,
                                        //label: dataObj.lineSeries.label,
                                        label: hoverLine.label,
                                        data: dataObj,
                                        fmt: title
                                    }, fmt = $.proxy(obj.fmt, obj), tit = fmt();
                                    return tit;
                                };
                            }
                            if (isContentFunc) {
                                op.content = function () {
                                    var obj = {
                                        pointIndex: idx,
                                        //lineIndex: dataObj.lineSeries.index,
                                        lineIndex: hoverLine.index,
                                        x: valueX,
                                        y: valueY,
                                        //label: dataObj.lineSeries.label,
                                        label: hoverLine.label,
                                        data: dataObj,
                                        fmt: content
                                    }, fmt = $.proxy(obj.fmt, obj), con = fmt();
                                    return con;
                                };
                            }
                        }
                        s = $.extend({
                            stroke: hoverLine.path.attr("stroke")
                        }, hint.style);
                        op.style.stroke = s.stroke;
                        tooltip.showAt(p);
                    }
                }

                _super.prototype._mouseMoveInsidePlotArea.call(this, e, mousePos);
            };

            wijcompositechart.prototype._mouseDownInsidePlotArea = function (e, mousePos) {
                _super.prototype._mouseDownInsidePlotArea.call(this, e, mousePos);
                this._clearHoverState(true);
            };

            wijcompositechart.prototype._mouseMoveOutsidePlotArea = function (e, mousePos) {
                var self = this;
                self._clearHoverState();
                _super.prototype._mouseMoveOutsidePlotArea.call(this, e, mousePos);
            };

            wijcompositechart.prototype._clearHoverState = function (keepTooltip) {
                var self = this, tooltip = self.tooltip, hint = self.options.hint;

                if (self.hoverLine) {
                    if (hint.enable && tooltip && !keepTooltip) {
                        tooltip.hide();
                    }
                    if (!self.hoverLine.path.removed) {
                        self.hoverLine.path.wijAttr(self.hoverLine.lineStyle);
                        if (self.hoverPoint && !self.hoverPoint.isSymbol) {
                            self.hoverPoint.marker.wijAttr(self.hoverPoint.markerStyle);

                            //hoverPoint.marker.scale(1, 1);
                            self.hoverPoint.marker.transform("s1");
                        }
                    }
                }
                self.hoverLine = null;
                self.hoverPoint = null;
                self.hoverVirtualPoint = null;
            };

            wijcompositechart.prototype._getTooltipText = function (fmt, target) {
                return "";
            };

            wijcompositechart.prototype._calculateParameters = function (axisInfo, options) {
                var self = this, hasBarType = false, minor, maxAdj = 0, minAdj = 0, bubbleAdj, max, min, barAdj, candlestickAdj;

                _super.prototype._calculateParameters.call(this, axisInfo, options);

                max = axisInfo.max, min = axisInfo.min;

                $.each(self.options.seriesList, function (idx, series) {
                    if (series.type === "column" || series.type === "bar") {
                        hasBarType = true;
                        return false;
                    }
                });

                // check for bar chart and x axis expansion
                if (axisInfo.id === "x") {
                    minor = options.unitMinor;
                    if (hasBarType) {
                        barAdj = self._getBarAdjustment(axisInfo, minor);
                        maxAdj = Math.max(maxAdj, barAdj.maxAdj);
                        minAdj = Math.max(minAdj, barAdj.minAdj);
                    }

                    if (self.isContainsCandlestick && wijcandlestickchartFn) {
                        candlestickAdj = wijcandlestickchartFn.prototype._getCandlestickAdjustment.apply(this, [axisInfo, minor]);
                        maxAdj = Math.max(maxAdj, candlestickAdj);
                        minAdj = Math.max(minAdj, candlestickAdj);
                    }
                }

                if (self.isContainsBubble && $.wijmo.wijbubblechart) {
                    bubbleAdj = this.bubbleAxisAdjust.getAdjust(axisInfo, options);
                    maxAdj = Math.max(maxAdj, bubbleAdj.max - max);
                    minAdj = Math.max(minAdj, min - bubbleAdj.min);
                }

                if (minAdj) {
                    axisInfo.min = min - minAdj;
                }
                if (maxAdj) {
                    axisInfo.max = max + maxAdj;
                }

                if (maxAdj || minAdj) {
                    self._calculateMajorMinor(options, axisInfo);
                }
            };

            wijcompositechart.prototype._getBarAdjustment = function (axisInfo, minor) {
                var len = 0, o = this.options, max = axisInfo.max, min = axisInfo.min, xLen = 0, adj;

                $.each(o.seriesList, function (idx, series) {
                    if (series.type === "pie") {
                        return true;
                    }
                    if (series.data.x === undefined || series.data.y === undefined) {
                        return true;
                    }
                    xLen = series.data.x.length;

                    if (len < xLen) {
                        len = xLen;
                    }
                });

                if (len > 1) {
                    var clusterRelativeWidth = (max - min) / (len - 1) * (o.clusterWidth / 100);

                    // Make a "0.25" offset to avoid the column being too close to axis.
                    adj = (clusterRelativeWidth * 1.25) / 2;
                } else if (len === 1) {
                    if (min === 0.0 && max === 1.0) {
                        min = -1.0;
                    }

                    adj = (max - min) * 0.0125;
                } else {
                    adj = 0;
                }

                if (adj === 0) {
                    adj = minor;
                } else {
                    if (minor < adj && minor !== 0) {
                        adj = Math.floor(adj / minor) * minor;
                    }
                }
                return {
                    maxAdj: adj,
                    minAdj: axisInfo.min - min + adj
                };
            };
            return wijcompositechart;
        })(_chart.wijchartcore);
        _chart.wijcompositechart = wijcompositechart;

        wijcompositechart.prototype.widgetEventPrefix = "wijcompositechart";

        /** @ignore */
        var CompositeChartRender = (function (_super) {
            __extends(CompositeChartRender, _super);
            function CompositeChartRender(element, options) {
                _super.call(this, element, options);
            }
            CompositeChartRender.prototype.getChartElementPosition = function (seriesIndex, pointIndex) {
                //pie chart annotation
                if (!this.annoPoints[seriesIndex] || !this.annoPoints[seriesIndex][pointIndex]) {
                    return;
                }

                // other charts annotation
                return _super.prototype.getChartElementPosition.call(this, seriesIndex, pointIndex);
            };
            return CompositeChartRender;
        })(_chart.BaseChartRender);
        _chart.CompositeChartRender = CompositeChartRender;

        var wijcompositechart_css = (function (_super) {
            __extends(wijcompositechart_css, _super);
            function wijcompositechart_css() {
                _super.apply(this, arguments);
                this.compositechart = "wijmo-wijcompositechart";
                this.barLabel = "wijbarchart-label";
                this.barElement = "wijbarchart";
                this.barTracker = "bartracker";
                this.bubbleElement = "wijbubblechart-bubble";
                this.bubbleTracker = "bubbletracker";
                this.bubbleLabel = "wijbubblechart-label";
                this.bubbleSymbol = "wijbubblechart-symbol";
                this.scatterElement = "wijscatterchart";
                this.pieLabel = "wijpiechart-label";
                this.pieElement = "wijpiechart";
                this.pieTracker = "pietracker";
                this.lineLabel = "wijlinechart-label";
                this.lineElement = "wijlinechart";
                this.areaElement = "wijlinechart-area";
                this.lineTracker = "linetracker";
                this.canvasMarker = "wijchart-canvas-marker";
                this.wijCandlestickChart = "wijmo-wijcandlestickchart";
                this.candlestickChart = "wijcandlestickchart";
                this.candlestickChartTracker = "candlesticktracker";
            }
            return wijcompositechart_css;
        })(_chart.wijchartcore_css);
        _chart.wijcompositechart_css = wijcompositechart_css;

        var wijcompositechart_options = (function (_super) {
            __extends(wijcompositechart_options, _super);
            function wijcompositechart_options() {
                _super.apply(this, arguments);
                /**
                * Selector option for auto self initialization. This option is internal.
                * @ignore
                */
                this.initSelector = ":jqmData(role='wijcompositechart')";
                /**
                * @ignore
                */
                this.wijCSS = new wijmo.chart.wijcompositechart_css();
                /**
                * A value that determines whether to show a stacked chart.
                */
                this.stacked = false;
                /**
                * A value that indicates the percentage of bar elements in the same cluster overlap.
                */
                this.clusterOverlap = 0;
                /**
                * A value that indicates the percentage of the plot area that each bar cluster occupies.
                */
                this.clusterWidth = 85;
                /**
                * A value that indicates the corner-radius for the bar.
                */
                this.clusterRadius = 0;
                /**
                * A value that indicates the spacing between the adjacent bars.
                */
                this.clusterSpacing = 0;
                /**
                * An array collection that contains the data that will be displayed by the chart."
                * @example
                *	$("#compositechart").wijcompositechart({
                *				seriesList: [{
                *					type: "bar",
                *					label: "Q1",
                *					legendEntry: true,
                *					data: {
                *						x: [1, 2, 3, 4, 5],
                *						y: [12, 21, 9, 29, 30]
                *					}}, {
                *					type: "bar",
                *					label: "Q2",
                *					legendEntry: true,
                *					data: {
                *						xy: [1, 21, 2, 10, 3, 19, 4, 31, 5, 20]
                *					}}, {
                *					type: "line",
                *					label: "Q3",
                *					legendEntry: true,
                *					data: {
                *						x: [1, 2, 3, 4, 5],
                *						y: [12, 21, 9, 29, 30]
                *					}}, {
                *					type: "pie",
                *					label: "title for pie chart",
                *					legendEntry: false,
                *					data: [{
                *						label: "Q4",
                *						data: 12,
                *						offset: 15
                *					}, {
                *						label: "Q5",
                *						data: 21,
                *						offset: 0
                *					}, {
                *						label: "Q5",
                *						data: 21,
                *						offset: 0
                *					}],
                *					center: {
                *						x: 150,
                *						y: 150
                *					},
                *					radius: 100
                *					}
                *				}]
                *				OR
                *				seriesList: [{
                *					type: "bar"
                *					label: "Q1",
                *					legendEntry: true,
                *					data: {
                *						x: ["A", "B", "C", "D", "E"],
                *						y: [12, 21, 9, 29, 30]
                *					}
                *				}, {
                *					type: "line"
                *					label: "Q1",
                *					legendEntry: true,
                *					data: {
                *						x: ["A", "B", "C", "D", "E"],
                *						y: [12, 21, 9, 29, 30]
                *					}
                *				}
                *				]
                *				OR
                *				seriesList: [{
                *					type: "bar",
                *					label: "Q1",
                *					legendEntry: true,
                *					data: {
                *						x: [new Date(1978, 0, 1), new Date(1980, 0, 1),
                *							new Date(1981, 0, 1), new Date(1982, 0, 1),
                *							new Date(1983, 0, 1)],
                *						y: [12, 21, 9, 29, 30]
                *					}
                *				}, {
                *					type: "bar",
                *					label: "Q2",
                *					legendEntry: true,
                *					data: {
                *						x: [new Date(1978, 0, 1), new Date(1980, 0, 1),
                *							new Date(1981, 0, 1), new Date(1982, 0, 1),
                *							new Date(1983, 0, 1)],
                *						y: [10, 25, 5, 25, 35]
                *					}
                *				}]
                *  });
                */
                this.seriesList = [];
                /**
                * The animation option defines the animation effect and controls other aspects of the widget's animation,
                * such as duration and easing.
                */
                this.animation = {
                    /**
                    * A value that determines whether to show animation.
                    */
                    enabled: true,
                    /**
                    * The duration option defines the length of the animation effect in milliseconds.
                    */
                    duration: 400,
                    /**
                    * Sets the type of animation easing effect that users experience when the wijcompositechart series is loaded to the page.
                    * @remarks
                    * The easing is defined in Raphael, the documentation is:http://raphaeljs.com/reference.html#Raphael.easing_formulas
                    */
                    easing: ">"
                };
                /**
                * The seriesTransition option is used to animate series in the chart when just their values change.
                * @remarks
                * This is helpful for visually showing changes in data for the same series.
                * Note: When programmatically updating the seriesList with a different number of series in the array make sure
                * to disable seriesTransition like the following:
                * seriesTransition: { enabled: false}
                */
                this.seriesTransition = {
                    /**
                    * A value that determines whether to show animation when reloading data.
                    */
                    enabled: true,
                    /**
                    * A value that indicates the duration for the series transition.
                    */
                    duration: 400,
                    /**
                    * Sets the type of animation easing effect that users experience when the wijcompositechart series is
                    * reloaded after they have changed the data for the seriesList option.
                    */
                    easing: ">"
                };
                /**
                * Occurs when the user clicks a mouse button.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {ICompositeChartEventArgs} data Information about an event
                */
                this.mouseDown = null;
                /**
                * Occurs when the user releases a mouse button while the pointer is over the chart element.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {ICompositeChartEventArgs} data Information about an event
                */
                this.mouseUp = null;
                /**
                * Occurs when the user first places the pointer over the chart element.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {ICompositeChartEventArgs} data Information about an event
                */
                this.mouseOver = null;
                /**
                * Occurs when the user moves the pointer off of the chart element.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {ICompositeChartEventArgs} data Information about an event
                */
                this.mouseOut = null;
                /**
                * Occurs when the user moves the mouse pointer while it is over a chart element.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {ICompositeChartEventArgs} data Information about an event
                */
                this.mouseMove = null;
                /**
                * Occurs when the user clicks the chart element.
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {ICompositeChartEventArgs} data Information about an event
                */
                this.click = null;
                /** Gets or sets the hole value.*/
                this.hole = {};
            }
            return wijcompositechart_options;
        })(_chart.wijchartcore_options);

        wijcompositechart.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijcompositechart_options());

        $.wijmo.registerWidget("wijcompositechart", wijcompositechart.prototype);
    })(wijmo.chart || (wijmo.chart = {}));
    var chart = wijmo.chart;
})(wijmo || (wijmo = {}));

;
/// <reference path="../external/declarations/globalize.d.ts" />
/// <reference path="../Base/jquery.wijmo.widget.ts" />
/// <reference path="../wijpopup/jquery.wijmo.wijpopup.ts" />
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*globals jQuery,$,window,alert,document,confirm,location,setTimeout, Globalize,
    clearTimeout,amplify*/
    /*jslint white: false */
    /*jslint nomen: false*/
    /*
    * Depends:
    *  jquery.ui.core.js
    *  jquery.ui.widget.js
    *  globalize.js
    *  jquery.wijmo.wijpopup.js
    *  jquery.ui.wijutil.js
    *
    */
    (function (datepager) {
        var $ = jQuery, widgetName = "wijdatepager", datePagerClass = "wijmo-wijdatepager", incButtonClass = "wijmo-wijdatepager-increment", decButtonClass = "wijmo-wijdatepager-decrement", containerClass = "wijmo-wijdatepager-container", pagesClass = "wijmo-wijdatepager-pages", pageLabelClass = "wijmo-wijdatepager-pagelabel", pageLabelFirstClass = "wijmo-wijdatepager-pagelabel-first", pageLabelLastClass = "wijmo-wijdatepager-pagelabel-last", pageHeaderClass = "wijmo-wijdatepager-pageheader", pageRangeClass = "wijmo-wijdatepager-pagerange", tooltipClass = "wijmo-wijdatepager-tooltip", tooltipInnerClass = "wijmo-wijdatepager-tooltip-inner", triangleClass = "wijmo-wijdatepager-triangle", widthSmallestClass = "wijmo-wijdatepager-width-smallest", widthSmallClass = "wijmo-wijdatepager-width-small", widthMediumClass = "wijmo-wijdatepager-width-medium", widthNormalClass = "wijmo-wijdatepager-width-normal";

        /** @widget */
        var wijdatepager = (function (_super) {
            __extends(wijdatepager, _super);
            function wijdatepager() {
                _super.apply(this, arguments);
            }
            wijdatepager.prototype._setOption = function (key, value) {
                var prevSelectedDate = this.options.selectedDate, dateEqual = function (a, b) {
                    if (a && b && a.getTime && b.getTime) {
                        return a.getTime() === b.getTime();
                    } else {
                        return a === b;
                    }
                };
                _super.prototype._setOption.call(this, key, value);
                switch (key) {
                    case "culture":
                    case "cultureCalendar":
                        this.options[key] = value;
                        this._innerCulture = null;
                        this._resetCulture();
                        this._initBackground();
                        break;
                    case "selectedDate":
                        this.options.selectedDate = value;
                        this._initBackground();
                        if (!dateEqual(value, prevSelectedDate)) {
                            this._onSelectedDateChanged();
                        }
                        break;
                    case "viewType":
                        this.options.viewType = value;
                        this._resetPageDates();
                        this._initBackground();
                        break;
                    case "customViewOptions":
                        this.options.customViewOptions = value;
                        this._resetPageDates();
                        this._initBackground();
                        break;
                    case "nextTooltip":
                        this.element.find("." + incButtonClass).attr("title", value);
                        break;
                    case "prevTooltip":
                        this.element.find("." + decButtonClass).attr("title", value);
                        break;
                    case "firstDayOfWeek":
                        this.options.firstDayOfWeek = value;
                        if (this.options.viewType === "week") {
                            this._initBackground();
                        }
                        break;
                }
                return this;
            };

            wijdatepager.prototype._innerDisable = function () {
                _super.prototype._innerDisable.call(this);
                this._toggleDisableDatePager(true);
            };

            wijdatepager.prototype._innerEnable = function () {
                _super.prototype._innerEnable.call(this);
                this._toggleDisableDatePager(false);
            };

            wijdatepager.prototype._toggleDisableDatePager = function (disabled) {
                this.element.toggleClass(this.options.wijCSS.stateDisabled, disabled);
                if ($.mobile == null) {
                    this.element.find("." + decButtonClass).button("option", "disabled", disabled);
                    this.element.find("." + incButtonClass).button("option", "disabled", disabled);
                } else {
                    this.element.find("." + decButtonClass).toggleClass(this.options.wijCSS.stateDisabled, disabled);
                    this.element.find("." + incButtonClass).toggleClass(this.options.wijCSS.stateDisabled, disabled);
                }
            };

            ///	<summary>
            ///	Creates date pager DOM elements and binds interactive events.
            ///	</summary>
            wijdatepager.prototype._create = function () {
                var o = this.options, resizeHandler, decBtn, incBtn;

                // enable touch support:
                if (window.wijmoApplyWijTouchUtilEvents) {
                    $ = window.wijmoApplyWijTouchUtilEvents($);
                }

                if (!o.selectedDate) {
                    o.selectedDate = new Date();
                }
                this._nativeClass = this.element.attr("class");
                this._dtpagernamespacekey = "dtpager" + new Date().getTime();
                this.element.addClass(datePagerClass).addClass(o.wijCSS.wijdatepager).addClass(o.wijCSS.widget).addClass(o.wijCSS.helperClearFix);
                resizeHandler = $.proxy(this.invalidate, this);
                $(window).bind("resize." + this._dtpagernamespacekey, resizeHandler);
                if (this.element.disableSelection) {
                    this.element.disableSelection();
                }
                this.element.append($("<a></a>").addClass(decButtonClass).addClass(o.wijCSS.wijdatepagerDecButton).append($("<span>" + o.prevTooltip + "</span>"))).append($("<div></div>").addClass(containerClass).addClass(o.wijCSS.wijdatepagerContainer).addClass(o.wijCSS.content).append($("<div></div>").addClass(pagesClass).addClass(o.wijCSS.wijdatepagerPages))).append($("<a></a>").addClass(incButtonClass).addClass(o.wijCSS.wijdatepagerIncButton).append($("<span>" + o.nextTooltip + "</span>")));

                decBtn = this.element.find("." + decButtonClass);
                incBtn = this.element.find("." + incButtonClass);
                if ($.mobile == null) {
                    decBtn.button({
                        icons: {
                            primary: o.wijCSS.iconArrowLeft
                        }, text: false
                    });
                    incBtn.button({
                        icons: {
                            primary: o.wijCSS.iconArrowRight
                        }, text: false
                    });
                } else {
                    decBtn.html("");
                    decBtn.addClass(o.wijCSS.iconArrowLeft + " " + o.wijCSS.icon + " ui-btn");
                    incBtn.html("");
                    incBtn.addClass(o.wijCSS.iconArrowRight + " " + o.wijCSS.icon + " ui-btn");
                }

                decBtn.click($.proxy(this.goLeft, this));
                incBtn.click($.proxy(this.goRight, this));

                this._initBackground();

                _super.prototype._create.call(this);
            };

            /** Destroys the widget and resets the DOM element.*/
            wijdatepager.prototype.destroy = function () {
                var wijCSS = this.options.wijCSS;
                this.element.empty().removeAttribute("aria-disabled");
                this.element.attr("class", this._nativeClass ? this._nativeClass : "");
                $(window).unbind("." + this._dtpagernamespacekey);
                $(document).unbind("." + this._dtpagernamespacekey);
                _super.prototype.destroy.call(this);
            };

            /** Refreshes the widget layout.*/
            wijdatepager.prototype.refresh = function () {
                this.invalidate();
            };

            wijdatepager.prototype._getCustomViewUnit = function () {
                var o = this.options, timeUnit;
                if (!o.customViewOptions.unit) {
                    return "day";
                }
                timeUnit = o.customViewOptions.unit.toLowerCase();
                if ($.inArray(timeUnit, ["day", "week", "month", "year"])) {
                    return timeUnit;
                } else {
                    return "day";
                }
            };

            /** Redraws the widget layout.*/
            wijdatepager.prototype.invalidate = function () {
                var self = this, selectedPage, o = self.options, selectedDate = o.selectedDate, newIndex, container = self.element.find("." + containerClass), decBtn = self.element.find("." + decButtonClass), incBtn = self.element.find("." + incButtonClass), innerWidth = self.element.innerWidth(), pageDate = selectedDate, decBtnW = decBtn.is(":visible") ? decBtn.outerWidth(true) : 0, incBtnW = incBtn.is(":visible") ? incBtn.outerWidth(true) : 0, pagesBg, pageLabels, pageWidth, activeStates, activeLabelSelector, unitCount, i, unit = this._getCustomViewUnit(), dateClass;
                if (o.viewType.toLowerCase() === "custom") {
                    unitCount = o.customViewOptions.count || 1;

                    for (i = 0; i < unitCount; i++) {
                        switch (unit) {
                            case "day":
                                dateClass = self._getDateClass(self._addDays(selectedDate, -i));
                                break;
                            case "month":
                                dateClass = self._getDateClass(new Date(selectedDate.getFullYear(), selectedDate.getMonth() - i, 1));
                                break;
                            case "year":
                                dateClass = self._getDateClass(new Date(selectedDate.getFullYear() - i, 0, 1));
                                break;
                            default:
                                dateClass = self._getDateClass(pageDate);
                                break;
                        }
                        selectedPage = self.element.find("." + pageLabelClass + "." + dateClass);
                        if (selectedPage.length === 1) {
                            break;
                        }
                    }
                } else {
                    selectedPage = self.element.find("." + pageLabelClass + "." + self._getDateClass(pageDate));
                }

                if (selectedPage.length !== 1) {
                    selectedPage = $(self.element.find("." + pageLabelClass)[self._index]);
                } else {
                    newIndex = this.element.find("." + pageLabelClass).index(selectedPage);
                    this._index = newIndex;
                }

                activeLabelSelector = "." + pageLabelClass;
                activeStates = o.wijCSS.stateActive.split(" ");
                $.each(activeStates, function (i) {
                    activeLabelSelector += "." + activeStates[i];
                });
                self.element.find(activeLabelSelector).removeClass(o.wijCSS.stateActive);
                selectedPage.addClass(self.options.wijCSS.stateActive);
                container.css("left", decBtnW);
                self.element.removeClass(widthSmallestClass).removeClass(o.wijCSS.wijdatepagerWidthSmallest).removeClass(widthSmallClass).removeClass(o.wijCSS.wijdatepagerWidthSmall).removeClass(widthMediumClass).removeClass(o.wijCSS.wijdatepagerWidthMedium).removeClass(widthNormalClass).removeClass(o.wijCSS.wijdatepagerWidthNormal);
                if (innerWidth < 300) {
                    self.element.addClass(widthSmallestClass).addClass(o.wijCSS.wijdatepagerWidthSmallest);
                } else if (innerWidth < 475) {
                    self.element.addClass(widthSmallClass).addClass(o.wijCSS.wijdatepagerWidthSmall);
                } else if (innerWidth < 600) {
                    self.element.addClass(widthMediumClass).addClass(o.wijCSS.wijdatepagerWidthMedium);
                } else {
                    self.element.addClass(widthNormalClass).addClass(o.wijCSS.wijdatepagerWidthNormal);
                }
                container.outerWidth(innerWidth - decBtnW - incBtnW);

                //ie6/7 don't support display: table and display: table-cell,
                //so set width to each page label.
                if ($.browser.msie && parseInt($.browser.version, 10) <= 7) {
                    pagesBg = self.element.find("." + pagesClass);
                    pageLabels = pagesBg.find("." + pageLabelClass);
                    pageWidth = Math.round(pagesBg.width() / self._datesDef.length) - (pageLabels.outerWidth(true) - pageLabels.width());
                    pageLabels.width(pageWidth);
                }
            };

            /** Selects the previous date.
            * @param {Object} ev The event of firing the select previous date.
            */
            wijdatepager.prototype.goLeft = function (ev) {
                if (this._isDisabled()) {
                    return;
                }
                this._setSelectedIndex(this._index - 1, true);
                if (ev) {
                    ev.preventDefault();
                    return false;
                }
            };

            /** Selects the next date.*/
            wijdatepager.prototype.goRight = function () {
                if (this._isDisabled()) {
                    return;
                }
                this._setSelectedIndex(this._index + 1);
            };

            wijdatepager.prototype._getCulture = function (name) {
                if (!this._innerCulture) {
                    this._resetCulture(name);
                }
                return this._innerCulture;
            };
            wijdatepager.prototype._resetCulture = function (culture) {
                var cal = $.wijGetCulture(culture || this.options.culture, this.options.cultureCalendar);
                this._innerCulture = cal;
            };

            wijdatepager.prototype._isRTL = function () {
                return !!this._getCulture().isRTL;
            };

            wijdatepager.prototype._initBackground = function (animate, isRightToLeft) {
                var _this = this;
                if (typeof animate === "undefined") { animate = false; }
                if (typeof isRightToLeft === "undefined") { isRightToLeft = false; }
                var s, oldBg, newBg, pageLabels, newPageIndPos, self = this, o = self.options, pageWidth, pages = $("<div></div>");
                if (this._isInAnimate) {
                    return;
                }
                this._index = 0;
                this._datesDef = this._getDatesDefinition();
                this._min = 0;
                this._max = this._datesDef.length - 1;

                $.each(this._datesDef, function (i, dateDef) {
                    var page = $("<div>" + _this._datesDef[i].l + "</div>").addClass(pageLabelClass).addClass(o.wijCSS.wijdatepagerPageLabel).addClass(_this._getDateClass(dateDef.d));
                    if (i === 0) {
                        page.addClass(pageLabelFirstClass).addClass(o.wijCSS.wijdatepagerPageLabelFirst);
                    }
                    if (dateDef.range) {
                        page.addClass(pageRangeClass).addClass(o.wijCSS.wijdatepagerPageRange);
                    }
                    if (dateDef.header) {
                        page.addClass(pageHeaderClass).addClass(o.wijCSS.wijdatepagerPageHeader).addClass(o.wijCSS.stateHighlight);
                    }
                    if (i === _this._max) {
                        page.addClass(pageLabelLastClass).addClass(o.wijCSS.wijdatepagerPageLabelLast);
                    }
                    pages.append(page);
                });

                s = pages.html();
                newBg = this.element.find("." + pagesClass);
                if (animate) {
                    this._isInAnimate = true;

                    oldBg = newBg.clone(true);
                    newBg.html(s);

                    pageLabels = newBg.find("." + pageLabelClass);
                    if (!isRightToLeft) {
                        oldBg.insertBefore(newBg);
                        newPageIndPos = $(pageLabels[this._index]).offset().left;

                        newBg.css("opacity", 0).css("left", oldBg.outerWidth(true)).stop().animate({ left: "0px", opacity: 100 });
                        oldBg.stop().animate({
                            left: "-" + oldBg.outerWidth(true) + "px",
                            opacity: 0
                        }, function () {
                            oldBg.remove();
                            self._isInAnimate = false;
                            self.invalidate();
                        });
                    } else {
                        oldBg.insertAfter(newBg);
                        newPageIndPos = $(pageLabels[this._index]).offset().left;

                        newBg.css("opacity", 0).css("left", -oldBg.outerWidth(true)).stop().animate({ left: "0px", opacity: 100 });
                        oldBg.css("left", 0).stop().animate({ left: oldBg.outerWidth(true) + "px", opacity: 0 }, function () {
                            oldBg.remove();
                            self._isInAnimate = false;
                            self.invalidate();
                        });
                    }
                } else {
                    newBg.html(s);
                    this.invalidate();
                }
                pageLabels = newBg.find("." + pageLabelClass);
                pageLabels.hover($.proxy(this._pagelabelHover, this), $.proxy(this._pagelabelHout, this));

                pageLabels.bind("mousedown", $.proxy(this._pagelabelMouseDown, this));
                pageLabels.click($.proxy(function (e) {
                    var target = $(e.target), ind;
                    ind = this.element.find("." + pageLabelClass).index(target);
                    this._setSelectedIndex(ind);
                }, this));
            };
            wijdatepager.prototype._getDateClass = function (dt) {
                return "c1dt" + dt.getFullYear() + "_" + dt.getMonth() + "_" + dt.getDate();
            };
            wijdatepager.prototype._addDays = function (dt, num) {
                return new Date(dt.getFullYear(), dt.getMonth(), dt.getDate() + num);
            };

            wijdatepager.prototype._nextYears = function (dt, num) {
                return new Date(dt.getFullYear() + num, 0, 1);
            };

            wijdatepager.prototype._nextMonths = function (dt, num) {
                return new Date(dt.getFullYear(), dt.getMonth() + num, 1);
            };

            wijdatepager.prototype._getDatesDefinition = function () {
                var self = this, o = self.options, viewType = o.viewType.toLowerCase(), i, dt, curDt, nextDt, endDt, datesDef = [], customViewDayOffset, selectedDate = o.selectedDate, maxDateGroup = o.maxDateGroup || 6, datesPerGroup, endDateOfGroup, format, timeUnit, customCount = o.customViewOptions.count || 1;

                switch (viewType) {
                    case "week":
                        curDt = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), -6);
                        i = o.firstDayOfWeek - curDt.getDay();
                        if (Math.abs(i) > 6) {
                            i = curDt.getDay() - o.firstDayOfWeek;
                        }
                        curDt = self._addDays(curDt, i);
                        endDt = new Date(selectedDate.getFullYear(), selectedDate.getMonth() + 1, 7);
                        i = 0;
                        while (curDt <= endDt || curDt.getMonth() === selectedDate.getMonth()) {
                            nextDt = self._addDays(curDt, 7);
                            datesDef.push({
                                l: self._formatString(self.localizeString("weekViewLabelFormat", "{0:MMM dd}-{1:dd}"), curDt, self._addDays(curDt, 6)),
                                d: curDt,
                                d2: self._addDays(curDt, 6)
                            });
                            if (selectedDate >= curDt && selectedDate <= nextDt) {
                                self._index = i;
                            }
                            curDt = nextDt;
                            i += 1;
                        }
                        break;
                    case "month":
                        dt = new Date(selectedDate.getFullYear() - 1, 0, 1);
                        datesDef.push({
                            l: self._formatString(self.localizeString("monthViewYearLabelFormat", "{0:yyyy}"), dt),
                            d: dt,
                            range: true
                        });
                        dt = new Date(selectedDate.getFullYear(), 0, 1);
                        datesDef.push({
                            l: self._formatString(self.localizeString("monthViewYearLabelFormat", "{0:yyyy}"), dt),
                            d: dt,
                            header: true
                        });

                        for (i = 0; i < 12; i += 1) {
                            dt = new Date(selectedDate.getFullYear(), i, 1);
                            datesDef.push({
                                l: self._formatString(self.localizeString("monthViewLabelFormat", "{0:MMM}"), dt),
                                d: dt
                            });
                            nextDt = new Date(selectedDate.getFullYear(), i + 1, 1);
                            if (selectedDate >= dt && selectedDate <= nextDt) {
                                self._index = i + 2;
                            }
                        }
                        dt = new Date(selectedDate.getFullYear() + 1, 0, 1);
                        datesDef.push({
                            l: self._formatString(self.localizeString("monthViewYearLabelFormat", "{0:yyyy}"), dt),
                            d: dt,
                            range: true
                        });
                        break;
                    case "custom":
                        timeUnit = self._getCustomViewUnit();
                        datesPerGroup = (timeUnit === "week" ? 7 : 1) * customCount;

                        //make sure current date is in the middle of the slide.
                        curDt = self._getDateAfterAdjusting(-maxDateGroup * datesPerGroup / 2);
                        endDt = self._getDateAfterAdjusting(maxDateGroup * datesPerGroup / 2);
                        if (!self._shouldResetDates(curDt, endDt)) {
                            return self._datesDef;
                        }
                        i = 0;
                        while (curDt <= endDt) {
                            switch (timeUnit) {
                                case "week":
                                    customViewDayOffset = o.firstDayOfWeek - curDt.getDay();
                                    curDt = self._addDays(curDt, customViewDayOffset);
                                    endDt = self._addDays(endDt, customViewDayOffset);
                                case "day":
                                    nextDt = self._addDays(curDt, datesPerGroup);
                                    endDateOfGroup = self._addDays(curDt, datesPerGroup - 1);
                                    if (customCount === 1 && timeUnit === "day") {
                                        format = self.localizeString("customViewUnitSingleDayLabelFormat", "{0:MMM dd}");
                                    } else {
                                        if (curDt.getMonth() === endDateOfGroup.getMonth()) {
                                            format = self.localizeString("customViewUnitDayLabelFormat", "{0:MMM dd}-{1:dd}");
                                        } else {
                                            format = self.localizeString("customViewUnitDayLabelFormat2Months", "{0:MMM dd}-{1:MMM dd}");
                                        }
                                    }
                                    break;
                                case "month":
                                    nextDt = self._nextMonths(curDt, customCount);
                                    endDateOfGroup = self._nextMonths(curDt, customCount - 1);
                                    if (customCount === 1) {
                                        format = self.localizeString("customViewUnitSingleMonthLabelFormat", "{0:MMM}");
                                    } else {
                                        if (curDt.getFullYear() === endDateOfGroup.getFullYear()) {
                                            format = self.localizeString("customViewUnitMonthLabelFormat", "{0:MMM}-{1:MMM, yyyy}");
                                        } else {
                                            format = self.localizeString("customViewUnitMonthLabelFormat2Years", "{0:MMM yyyy}-{1:MMM yyyy}");
                                        }
                                    }
                                    break;
                                case "year":
                                    nextDt = self._nextYears(curDt, customCount);
                                    endDateOfGroup = self._nextYears(curDt, customCount - 1);
                                    if (customCount === 1) {
                                        format = self.localizeString("customViewUnitSingleYearLabelFormat", "{0:yyyy}");
                                    } else {
                                        format = self.localizeString("customViewUnitYearLabelFormat", "{0:yyyy}-{1:yyyy}");
                                    }
                                    break;
                            }

                            datesDef.push({
                                l: self._formatString(format, curDt, endDateOfGroup),
                                d: curDt,
                                d2: endDateOfGroup
                            });
                            if (selectedDate >= curDt && selectedDate <= nextDt) {
                                self._index = i;
                            }
                            curDt = nextDt;
                            i += 1;
                        }
                        self._resetPageDates(datesDef[0].d, datesDef[datesDef.length - 1].d);
                        break;
                    default:
                        //case "day":
                        dt = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), 0);
                        datesDef.push({
                            l: self._formatString(self.localizeString("dayViewMonthLabelFormat", "{0:MMM}"), dt),
                            d: dt,
                            range: true
                        });
                        dt = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), 1);
                        datesDef.push({
                            l: self._formatString(self.localizeString("dayViewMonthLabelFormat", "{0:MMM}"), dt),
                            d: dt, header: true
                        });

                        curDt = dt;
                        i = 2;
                        while (curDt.getMonth() === selectedDate.getMonth()) {
                            nextDt = new Date(curDt.getFullYear(), curDt.getMonth(), curDt.getDate() + 1);
                            datesDef.push({
                                l: self._formatString(self.localizeString("dayViewLabelFormat", "{0:d }"), curDt),
                                d: curDt
                            });
                            if (selectedDate >= curDt && selectedDate <= nextDt) {
                                self._index = i;
                            }
                            curDt = nextDt;
                            i += 1;
                        }

                        dt = new Date(selectedDate.getFullYear(), selectedDate.getMonth() + 1, 1);
                        datesDef.push({
                            l: self._formatString(self.localizeString("dayViewMonthLabelFormat", "{0:MMM}"), dt),
                            d: dt,
                            range: true
                        });
                        break;
                }
                return datesDef;
            };

            wijdatepager.prototype._getDateAfterAdjusting = function (dateOffset) {
                var self = this, o = self.options, selectedDate = o.selectedDate, year = selectedDate.getFullYear(), month = selectedDate.getMonth();

                switch (self._getCustomViewUnit()) {
                    case "day":
                    case "week":
                        return new Date(year, month, selectedDate.getDate() + dateOffset);
                    case "month":
                        return new Date(year, month + dateOffset, 1);
                    case "year":
                        return new Date(year + dateOffset, 0, 1);
                }
            };

            wijdatepager.prototype._resetPageDates = function (startDate, endDate) {
                this._startDate = startDate || null;
                this._endDate = endDate || null;
            };

            wijdatepager.prototype._shouldResetDates = function (startDate, endDate) {
                var self = this, o = self.options, selectedDate = o.selectedDate;
                if (!self._startDate || !self._endDate) {
                    self._resetPageDates(startDate, endDate);
                    return true;
                } else {
                    if (self._startDate < new Date(selectedDate.getFullYear(), selectedDate.getMonth(), selectedDate.getDate()) && self._endDate > new Date(selectedDate.getFullYear(), selectedDate.getMonth(), selectedDate.getDate())) {
                        return false;
                    }
                }
                self._resetPageDates(startDate, endDate);
                return true;
            };

            wijdatepager.prototype._setSelectedIndex = function (ind, skipHeader) {
                if (typeof skipHeader === "undefined") { skipHeader = false; }
                var o = this.options, pendingSelectedDate;
                if (this._isDisabled()) {
                    return;
                }
                if (ind >= this._min && ind <= this._max) {
                    if (this._dragActivated) {
                        this._showTooltip(ind);
                    }

                    if (this._index !== ind) {
                        if (this._datesDef[ind].header) {
                            if (skipHeader) {
                                ind = ind - 1;
                            } else {
                                return;
                            }
                        }
                        this._index = ind;
                        pendingSelectedDate = this._datesDef[ind].d;
                        o.selectedDate = pendingSelectedDate;

                        if (this._max > 2 && this._index === 0) {
                            this._initBackground(true, true);
                        } else if (this._index === this._max) {
                            if (o.viewType === "week") {
                                o.selectedDate = new Date(o.selectedDate.getFullYear(), o.selectedDate.getMonth(), o.selectedDate.getDate() + 7);
                            }
                            this._initBackground(true, false);
                            o.selectedDate = pendingSelectedDate;
                        } else {
                            this.invalidate();
                        }
                        this._onSelectedDateChanged();
                    }
                }
            };
            wijdatepager.prototype._onSelectedDateChanged = function () {
                var o = this.options;
                this._trigger("selectedDateChanged", null, { selectedDate: o.selectedDate });
            };
            wijdatepager.prototype._pagelabelHover = function (e) {
                var target = $(e.target), o = this.options;
                if (target.hasClass(pageHeaderClass)) {
                    return;
                }
                target.addClass(o.wijCSS.stateHover);
            };
            wijdatepager.prototype._showTooltip = function (ind) {
                var self = this, o = self.options, dateDef = self._datesDef[ind], viewType = o.viewType, s, target = this.element.find("." + pageLabelClass)[ind], timeUnit = self._getCustomViewUnit(), customCount = o.customViewOptions.count || 1;
                if (!self._tooltip) {
                    self._tooltip = $("<div></div>").addClass(tooltipClass).addClass(o.wijCSS.wijdatepagerTooltip).append($("<div></div>").addClass(tooltipInnerClass).addClass(o.wijCSS.wijdatepagerTooltipInner)).append($("<div></div>").addClass(triangleClass).addClass(o.wijCSS.wijdatepagerTriangle));
                    self.element.append(self._tooltip);
                    self._tooltip.wijpopup();
                }

                switch (viewType) {
                    case "week":
                        if (dateDef.d.getMonth() !== dateDef.d2.getMonth()) {
                            s = self._formatString(self.localizeString("weekViewTooltip2MonthesFormat", "{0:MMMM d} - {1:MMMM d, yyyy}"), dateDef.d, dateDef.d2);
                        } else {
                            s = self._formatString(self.localizeString("weekViewTooltipFormat", "{0:MMMM d} - {1:d, yyyy}"), dateDef.d, dateDef.d2);
                        }
                        break;
                    case "month":
                        s = self._formatString(self.localizeString("monthViewTooltipFormat", "{0:MMMM yyyy}"), dateDef.d);
                        break;
                    case "custom":
                        if (timeUnit === "day" || timeUnit === "week") {
                            if (customCount === 1) {
                                s = self._formatString(self.localizeString("customViewSingleDayTooltipFormat", "{0:MMMM d yyyy}"), dateDef.d);
                            } else {
                                if (dateDef.d.getMonth() !== dateDef.d2.getMonth()) {
                                    s = self._formatString(self.localizeString("customViewDayUnitTooltip2MonthesFormat", "{0:MMMM d} - {1:MMMM d, yyyy}"), dateDef.d, dateDef.d2);
                                } else {
                                    s = self._formatString(self.localizeString("customViewDayTooltipFormat", "{0:MMMM d} - {1:d, yyyy}"), dateDef.d, dateDef.d2);
                                }
                            }
                        } else if (timeUnit === "month") {
                            if (customCount === 1) {
                                s = self._formatString(self.localizeString("customViewSingleMonthTooltipFormat", "{0:MMMM yyyy}"), dateDef.d);
                            } else {
                                if (dateDef.d.getFullYear() !== dateDef.d2.getFullYear()) {
                                    s = self._formatString(self.localizeString("customViewMonthTooltip2YearsFormat", "{0:MMMM yyyy} - {1:MMMM yyyy}"), dateDef.d, dateDef.d2);
                                } else {
                                    s = self._formatString(self.localizeString("customViewMonthTooltipFormat", "{0:MMMM} - {1:MMMM, yyyy}"), dateDef.d, dateDef.d2);
                                }
                            }
                        } else if (timeUnit === "year") {
                            if (customCount === 1) {
                                s = self._formatString(self.localizeString("customViewSingleYearTooltipFormat", "{0:yyyy}"), dateDef.d);
                            } else {
                                s = self._formatString(self.localizeString("customViewYearTooltipFormat", "{0:yyyy} - {1:yyyy}"), dateDef.d, dateDef.d2);
                            }
                        }
                        break;
                    default:
                        //case "day":
                        s = this._formatString(self.localizeString("dayViewTooltipFormat", "{0:dddd, MMMM d, yyyy}"), dateDef.d);
                        break;
                }
                if ($.ui) {
                    //disable popup for mobile mode
                    self._tooltip.wijpopup("show", {
                        of: target,
                        my: "center bottom",
                        at: "center top",
                        offset: "-10 -10"
                    });

                    self._tooltip.find("." + tooltipInnerClass).html(s);
                }
            };
            wijdatepager.prototype._hideTooltip = function () {
                this._tooltip.wijpopup("hide");
            };
            wijdatepager.prototype._pagelabelHout = function (e) {
                $(e.target).removeClass(this.options.wijCSS.stateHover);
            };
            wijdatepager.prototype._pagelabelMouseDown = function (e) {
                this._dragActivated = false;
                if (this._isDisabled()) {
                    return;
                }
                e.preventDefault();
                var target = $(e.target), ind;
                if (target.hasClass(pageHeaderClass)) {
                    return;
                }
                ind = this.element.find("." + pageLabelClass).index(target);

                this._dragActivated = true;
                this._setSelectedIndex(ind);
                this._mouseDownTimeFix20555 = new Date().getTime();
                this._startClientX = e.pageX;
                this._startInd = ind;

                $(document).bind("mousemove." + this._dtpagernamespacekey, $.proxy(this._pageindicatorMouseMove, this));
                $(document).bind("mouseup." + this._dtpagernamespacekey, $.proxy(this._pageindicatorMouseUp, this));
            };

            wijdatepager.prototype._detectLeftButton = function (event) {
                if (event.originalEvent) {
                    event = event.originalEvent;
                }
                if ("buttons" in event) {
                    return event.buttons === 1;
                } else if ("which" in event) {
                    return event.which === 1;
                } else {
                    return event.button === 1;
                }
            };

            wijdatepager.prototype._pageindicatorMouseMove = function (e) {
                if (!this._detectLeftButton(e)) {
                    this._pageindicatorMouseUp();
                    return;
                }
                e.preventDefault();
                if (this._isInAnimate) {
                    return;
                }

                var startPage = this.element.find("." + pageLabelClass)[this._startInd], newPos, ind;
                if (!startPage) {
                    return;
                }
                newPos = startPage.offsetLeft + Math.round(startPage.offsetWidth / 2) + (e.pageX - this._startClientX);
                ind = this._findClosesPageIndexByPos(newPos);

                if (this._prevMoveInd === ind) {
                    // fix for [20534] case 1:
                    return;
                }
                this._prevMoveInd = ind;
                if ((this._mouseDownTimeFix20555 + 150) > new Date().getTime()) {
                    // fix for [20555]
                    return;
                }
                if (ind !== -1 && ind !== this._index) {
                    this._setSelectedIndex(ind);
                }
            };
            wijdatepager.prototype._pageindicatorMouseUp = function () {
                this._dragActivated = false;
                $(document).unbind("." + this._dtpagernamespacekey);
                this._hideTooltip();
            };
            wijdatepager.prototype._findClosesPageIndexByPos = function (pos) {
                var pagelabels = this.element.find("." + pagesClass).find("." + pageLabelClass), i;

                for (i = 0; i < pagelabels.length; i += 1) {
                    if ((pagelabels[i].offsetLeft) < pos && (pagelabels[i].offsetLeft + pagelabels[i].offsetWidth) > pos) {
                        return i;
                    }
                }
                return -1;
            };

            /** @ignore */
            wijdatepager.prototype.localizeString = function (key, defaultValue) {
                var o = this.options;
                if (o.localization && o.localization[key]) {
                    return o.localization[key];
                }
                return defaultValue;
            };

            wijdatepager.prototype._formatString = function (fmt, arg0, arg1, arg2) {
                var r, args = arguments, i, funcArgs, self = this;
                if (args.length <= 1) {
                    return Globalize.format(args);
                }
                if (typeof fmt === "string") {
                    if (typeof window[fmt] === "function") {
                        fmt = window[fmt];
                    }
                }
                if (typeof fmt === "function") {
                    funcArgs = [];
                    for (i = 1; i < args.length; i += 1) {
                        funcArgs[i - 1] = args[i];
                    }
                    return fmt.apply(this, funcArgs);
                }
                r = new RegExp("\\{(\\d+)(?:,([-+]?\\d+))?(?:\\:" + "([^(^}]+)(?:\\(((?:\\\\\\)|[^)])+)\\)){0,1}){0,1}\\}", "g");
                return fmt.replace(r, function (m, num, len, f, params) {
                    m = args[Number(num) + 1];
                    if (f) {
                        return Globalize.format(m, f, self._getCulture());
                    } else {
                        return m;
                    }
                });
            };
            return wijdatepager;
        })(wijmo.wijmoWidget);
        datepager.wijdatepager = wijdatepager;

        var wijdatepager_options = (function () {
            function wijdatepager_options() {
                this.wijCSS = {
                    wijdatepager: "",
                    wijdatepagerIncButton: "",
                    wijdatepagerDecButton: "",
                    wijdatepagerContainer: "",
                    wijdatepagerPages: "",
                    wijdatepagerPageLabel: "",
                    wijdatepagerPageLabelFirst: "",
                    wijdatepagerPageLabelLast: "",
                    wijdatepagerPageHeader: "",
                    wijdatepagerPageRange: "",
                    wijdatepagerTooltip: "",
                    wijdatepagerTooltipInner: "",
                    wijdatepagerTriangle: "",
                    wijdatepagerWidthSmallest: "",
                    wijdatepagerWidthSmall: "",
                    wijdatepagerWidthMedium: "",
                    wijdatepagerWidthNormal: ""
                };
                /** @ignore */
                this.wijMobileCSS = {
                    header: "ui-header ui-bar-a",
                    content: "ui-body ui-body-b",
                    stateDefault: "ui-btn ui-btn-b"
                };
                /** @ignore */
                this.initSelector = ":jqmData(role='wijdatepager')";
                /** Culture name, e.g. "de-DE".
                * @example
                * // This markup sets the culture to German:
                * $("#element").wijdatepager( { culture: "de-DE" } );
                */
                this.culture = "";
                /** A value that indicators the culture calendar to format the text.
                *  This option must work with culture option.*/
                this.cultureCalendar = "";
                /** Use the localization option in order to provide custom localization.
                * @remarks Default:
                *  {
                *  dayViewTooltipFormat: "{0:dddd, MMMM d, yyyy}",
                *  weekViewTooltipFormat: "{0:MMMM d} - {1:d, yyyy}",
                *  weekViewTooltip2MonthesFormat: "{0:MMMM d} - {1:MMMM d, yyyy}",
                *  monthViewTooltipFormat: "{0:MMMM yyyy}",
                *  customViewDayUnitTooltip2MonthesFormat: "{0:MMMM d} - {1:MMMM d, yyyy}",
                *  customViewSingleDayTooltipFormat: "{0:MMMM d yyyy}",
                *  customViewDayTooltipFormat: "{0:MMMM d} - {1:d, yyyy}",
                *  customViewMonthTooltip2YearsFormat: "{0:MMMM yyyy} - {1:MMMM yyyy}",
                *  customViewSingleMonthTooltipFormat: "{0:MMMM yyyy}",
                *  customViewMonthTooltipFormat: "{0:MMMM} - {1:MMMM, yyyy}",
                *  customViewSingleYearTooltipFormat: "{0:yyyy}",
                *  customViewYearTooltipFormat: "{0:yyyy} - {1:yyyy}",
                *  customViewUnitDayLabelFormat: "{0:MMM dd}-{1:dd}",
                *  customViewUnitSingleDayLabelFormat: "{0:MMM dd}",
                *  customViewUnitDayLabelFormat2Months: "{0:MMM dd}-{1:MMM dd}",
                *  customViewUnitMonthLabelFormat: "{0:MMM}-{1:MMM, yyyy}",
                *  customViewUnitSingleMonthLabelFormat: "{0:MMM}",
                *  customViewUnitMonthLabelFormat2Years: "{0:MMM yyyy}-{1:MMM yyyy}",
                *  customViewUnitSingleYearLabelFormat: "{0:yyyy}",
                *  customViewUnitYearLabelFormat: "{0:yyyy}-{1:yyyy}",
                *  dayViewLabelFormat": "{0:d }",
                *  dayViewMonthLabelFormat: "{0:MM}",
                *  weekViewLabelFormat: "{0:MMM dd}-{1:dd}",
                *  monthViewLabelFormat: "{0:MMM}",
                *  monthViewYearLabelFormat: "{0:yyyy}"
                *	}
                * @example
                * $("#datepager").wijdatepager(
                *					{
                *						localization: {
                *							weekViewTooltip2MonthesFormat: "{0:MMMM d} - {1:MMMM d}",
                *							dayViewTooltipFormat: "{0:dddd, MMMM d}"
                *						}
                *					});
                */
                this.localization = null;
                /** The first day of the week (from 0 to 6).  Sunday is 0, Monday is 1, and so on.*/
                this.firstDayOfWeek = 0;
                /** The count of date group displayed in the pager.
                * @type {Number}
                */
                this.maxDateGroup = 6;
                /** The selected date.
                * @type {Date}
                */
                this.selectedDate = null;
                /** The active view type.
                * @remarks Possible values are: day, week, month, custom.
                */
                this.viewType = "day";
                /** The options of custom view.
                * @type {Object}
                * @example $("#datepager").wijdatepager({
                *         customViewOptions: {
                *             unit: "day",
                *             count: 2
                *         }
                *     });
                * @remarks
                * The options of the custom view. options object fields:
                * unit - String, the time unit of custom view possible values are "day", "week", "month", "year";
                * count - number, the count of time span, depends on the unit;
                * Default:
                * {
                *     unit: "day",
                *     count: 1
                * }
                */
                this.customViewOptions = { unit: "day", count: 1 };
                /** Gets or sets the text for the 'next' button's ToolTip.
                */
                this.nextTooltip = "right";
                /** Gets or sets the text for the 'previous' button's ToolTip.
                */
                this.prevTooltip = "left";
                /** Occurs when the selectedDate option has been changed.
                * @event
                * @dataKey selectedDate The new selectedDate option value.
                */
                this.selectedDateChanged = null;
            }
            return wijdatepager_options;
        })();
        ;
        wijdatepager.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijdatepager_options());
        $.wijmo.registerWidget(widgetName, wijdatepager.prototype);
    })(wijmo.datepager || (wijmo.datepager = {}));
    var datepager = wijmo.datepager;
})(wijmo || (wijmo = {}));

;
/// <reference path="../Base/jquery.wijmo.widget.ts" />
/// <reference path="../external/declarations/globalize.d.ts" />
/// <reference path="../wijcalendar/jquery.wijmo.wijcalendar.ts" />
/// <reference path="../wijpopup/jquery.wijmo.wijpopup.ts" />
/// <reference path="../wijdialog/jquery.wijmo.wijdialog.ts" />
/// <reference path="../wijdatepager/jquery.wijmo.wijdatepager.ts" />
/// <reference path="../wijsuperpanel/jquery.wijmo.wijsuperpanel.ts" />
/// <reference path="../wijcheckbox/jquery.wijmo.wijcheckbox.ts" />
/// <reference path="../wijtextbox/jquery.wijmo.wijtextbox.ts" />
/// <reference path="../wijdropdown/jquery.wijmo.wijdropdown.ts" />
/// <reference path="../wijinput/jquery.wijmo.wijinputdate.ts" />
/// <reference path="../export/exportUtil.ts" />
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};

var wijmo;
(function (wijmo) {
    /*globals jQuery,$,window,alert,document,confirm,location,setTimeout, Globalize,
    amplify*/
    /*jslint white: false */
    /*jslint nomen: false*/
    /*jslint browser: true*/
    /*jslint continue: true*/
    /*jslint devel: true*/
    /*jslint forin: true*/
    /*jslint maxlen: 110*/
    /*
    * Depends:
    * jquery.ui.core.js
    * jquery.ui.widget.js
    * globalize.js
    * jquery.mousewheel.js
    * jquery.wijmo.wijutil.js
    * jquery.wijmo.wijcharex.js
    * jquery.wijmo.wijstringinfo.js
    * jquery.wijmo.wijinputcore.js
    * jquery.wijmo.wijinputdate.js
    * jquery.wijmo.wijinputnumber.js
    * jquery.wijmo.wijcalendar.js
    *   jquery.wijmo.wijdialog.js
    *   jquery.wijmo.wijcombobox.js
    * jquery.wijmo.wijdatepager.js
    Following dependencies are needed if you wish to enable built-in client side data-storage:
    *   amplify.core.js
    * amplify.store.js
    
    
    
    
    */
    /*
    block comments:
    // util methods:
    // format date/time:
    // public methods
    // _parseDateFromClass
    
    // Event object fields:
    ///     id - String, unique event id, this field generated automatically;
    ///     calendar - String, calendar id to which the event belongs;
    ///     subject - String, event title;
    ///     location - String, event location;
    ///     start - Date, start date/time;
    ///     end - Date, end date/time;
    ///     description - String, event description;
    ///     color - String, event color;
    ///     allday - Boolean, indicates all day event
    ///     tag - String, this field can be used to store custom information.
    
    ///     parentRecurrenceId - String, id of the event object that
    ///         defines the recurrence criteria for this event object.
    ///         If an event is recurring it represents an occurrence in the series that is
    ///         started and defined by a specific pattern event.
    ///         Use the getPatern method in order to obtain the pattern
    ///         of the current event. A pattern event can be recognized by its
    ///         recurrenceState field set to the "master" value.
    ///         The recurrence information defined by the pattern event
    ///         can be accessed  via the recurrencePattern field of the event.
    ///         If this event is a not member of a recurrence,
    ///         or is itself a root event, this field will be null.
    ///     recurrenceState - String, indicates the recurrence state of the event.
    ///         (possible values are "notRecurring"(or null), "master", "occurrence",
    ///         "exception", "removed")
    ///     recurrencePattern - Object, represents the recurrence attributes
    ///         of an event. Only master events can have this field
    ///         (recurrenceState is "master")
    ///         Object syntax:
    ///         parentRecurrenceId - String, id of the event object
    ///             which represents the master event for this
    ///             recurrencePattern object.
    ///         recurrenceType - String, determines the type of recurrence:
    ///             daily - the recurring event reoccurs on a daily basis.
    ///             workdays - the recurring event reoccurs every working day.
    ///             monthly - the recurring event reoccurs on a monthly basis.
    ///             monthlyNth - the recurring event reoccurs every N months.
    ///             weekly - the recurring event reoccurs on a weekly basis.
    ///             yearly - the recurring event reoccurs on an yearly basis.
    ///             yearlyNth - the recurring event reoccurs every N years.
    ///         interval - Number, specifies the interval between occurrences
    ///             of the recurrence.
    ///             The interval field works in conjunction with
    ///             the "recurrenceType" field to determine the cycle of the recurrence.
    ///             The maximum allowable value is 99 for weekly patterns and 999
    ///             for daily patterns.
    ///             The default value is 1.
    ///             For example, if the recurrenceType is set
    ///             to daily, and the "interval" is set to 3,
    ///             the recurrence will occur every third day.
    ///         startTime - Date, indicates the start time for the given
    ///             occurrence of the recurrence pattern.
    ///         endTime - Date, indicates the end time for the given
    ///             occurrence of the recurrence pattern.
    ///         patternStartDate - Date, indicates the start date of the
    ///             recurrence pattern.
    ///         patternEndDate - Date, indicates the end date of the
    ///             recurrence pattern.
    ///             This field is optional but must be coordinated
    ///             with other fields when setting up a recurrence pattern.
    ///             If this field or the "occurrences" field is set,
    ///             the pattern is considered to be finite, and the "noEndDate"
    ///             field is false.
    ///             If neither "patternEndDate" nor "occurrences" is set,
    ///             the pattern is considered infinite and "noEndDate" is true.
    ///             The "interval" field must be set before
    ///             setting "patternEndDate".
    ///         occurrences - Number, the number of occurrences for the
    ///             recurrence pattern. This field allows the definition of
    ///             a recurrence pattern that is only valid for the specified
    ///             number of subsequent occurrences.
    ///             For example, you can set this property to 10 for a formal
    ///             training  course that will be held on the next ten Thursday
    ///             evenings. The default value is 0. This field must be
    ///             coordinated with other fields when setting up a recurrence pattern.
    ///             If the "patternEndDate" field or the "occurrences" field
    ///             is set, the pattern is considered to be finite and the
    ///             "noEndDate" field is false.
    ///             If neither "patternEndDate" nor "occurrences" is set,
    ///             the pattern is considered infinite and "noEndDate" is true.
    ///         instance - String, determines the week in a month in which
    ///             the event will occur. This field is only valid for recurrences of
    ///             the "monthlyNth" and "yearlyNth" types and allows the definition
    ///             of a recurrence pattern that is only valid for the Nth occurrence,
    ///             such as "the 2nd Sunday in March" pattern.
    ///             The default value is "first".
    ///             Possible values are:
    ///                 first - the recurring event will occur on the specified
    ///                     day or days of the first week in the month.
    ///                 second - The recurring event will occur on the specified
    ///                     day or days of the second week in the month.
    ///                 third = - The recurring event will occur on the specified
    ///                     day or days of the third week in the month.
    ///                 fourth - The recurring event will occur on the specified
    ///                     day or days of the fourth week in the month.
    ///                 last - The recurring event will occur on the specified
    ///                     day or days of the last week in the month.
    ///         dayOfWeekMask - String, contains set of values representing the mask
    ///             for week days on which the recurring event occurs.
    ///             Monthly and yearly patterns are only valid for a single day.
    ///             The default value is "none".
    ///             When the "recurrenceType" field is set to "daily",
    ///             the "dayOfWeekMask" field can only be set to "everyDay";
    ///             setting the field to any other value will result in an exception.
    ///             When the "recurrenceType" field is set to
    ///             "workdays", the "dayOfWeekMask" field
    ///             can only be set to "workDays"; setting the field
    ///             to any other value will result in an exception.
    ///             When the "recurrenceType" field is set to
    ///             "weekly", the "dayOfWeekMask" field
    ///             cannot be set to "none"; doing so will result
    ///             in an exception being thrown.
    ///             When the recurrenceType" field is set to
    ///             "monthly" or "yearly" the "dayOfWeekMask" field is not applicable.
    ///             Possible values are:
    ///                 none - no specific value.
    ///                 sunday - specifies Sunday.
    ///                 monday - Specifies Monday.
    ///                 tuesday - Specifies Tuesday.
    ///                 wednesday - Specifies Wednesday.
    ///                 thursday - Specifies Thursday.
    ///                 friday - Specifies Friday.
    ///                 saturday - Specifies Saturday.
    ///                 weekendDays - Specifies Saturday and Sunday.
    ///                 workDays - Specifies work days (all days except weekend).
    ///                 everyDay - Specifies every day of the week.
    ///         dayOfMonth - Number, the number of the day in its respective month on which
    ///             each occurrence will occur. Applicable only when the recurrenceType
    ///             field is set to "monthly" or "yearly".
    ///             The default value is 1.
    ///         monthOfYear - Number, indicates which month of the year is valid
    ///             for the specified recurrence pattern. Can be a number from 1 to 12.
    ///             This field is only valid for recurrence patterns whose recurrenceType"
    ///             field is set to "yearlyNth" or "yearly".
    ///             The default value is 1.
    ///         noEndDate - Boolean, indicates if the recurrence pattern is endless.
    ///             The default value is True. This field must be coordinated with
    ///             other fields when setting up a recurrence pattern. If the patternEndDate field
    ///             or the occurrences field is set, the pattern is considered
    ///             to be finite and the "noEndDate" field is false.
    ///             If neither patternEndDate nor occurrences is set,
    ///             the pattern is considered infinite and "noEndDate" is true.
    ///         exceptions - Array, holds the list of event object ids that
    ///             define the exceptions to that series of events.
    ///             This field is read-only.
    ///         removedOccurrences - Array, holds the list of event object's ids
    ///             removed from that series of events.
    
    
    
    
    
    /// Calendar object fields:
    /// id - String, unique calendar id, this field generated automatically;
    /// name - String, calendar name;
    /// location - String, location field;
    /// description - String, calendar description;
    /// color - String, calendar color;
    /// tag - String, this field can be used to store custom information.
    */
    (function (evcal) {
        var $ = jQuery, widgetName = "wijevcal";

        /////////////// utils:
        function _toDayDate(dt) {
            return new Date(dt.getFullYear(), dt.getMonth(), dt.getDate());
        }
        function _generateGuid() {
            var result, i, j;
            result = "";
            for (j = 0; j < 32; j += 1) {
                if (j === 8 || j === 12 || j === 16 || j === 20) {
                    result = result + "-";
                }
                i = Math.floor(Math.random() * 16).toString(16).toUpperCase();
                result = result + i;
            }
            return result;
        }

        /////////////// abstract data layer implementation
        // (web sql database / amplify.store)
        var database, databaseName = "C1EventsCalendarDB", databaseVer = "1.1", isAmplifyStoreUsed = false, amplifyTables;

        function ensureTableCreated(tableName, fields, callback) {
            /*  ensureTableCreated("events",
            "(id TEXT PRIMARY KEY, calendar TEXT, subject TEXT, location TEXT, " +
            "start TIMESTAMP, end TIMESTAMP, description TEXT)");*/
            if (isAmplifyStoreUsed) {
                amplifyTables = amplify.store("wijevcal_tables1");
                if (!amplifyTables) {
                    amplifyTables = {};
                }

                //alert("isAmplifyStoreUsed?" + amplifyTables[tableName]);
                if (!amplifyTables[tableName]) {
                    amplifyTables[tableName] = { fields: fields };
                    amplify.store("wijevcal_tables1", amplifyTables);
                    amplify.store("wijevcal_tbl_" + tableName, {});
                }
                if (callback) {
                    callback();
                }
            } else if (database) {
                database.transaction(function (tx) {
                    tx.executeSql("SELECT COUNT(*) FROM " + tableName, [], function () {
                        if (callback) {
                            callback();
                        }
                    }, function (tx, error) {
                        tx.executeSql("CREATE TABLE " + tableName + " " + fields, [], callback, callback);
                    });
                });
            }
        }

        function executeSql(sqlCommand, params, successHandler, errorHandler) {
            /*
            executeSql("SELECT * FROM events", []
            
            executeSql("INSERT OR REPLACE INTO events " +
            "(id, calendar, subject, location, start, end, description) " +
            "VALUES(?,?,?,?,?,?,?);",
            [o.id, o.calendar, o.subject, o.location,
            o.start.getTime(), o.end.getTime(), o.description],
            
            */
            var data = { rowsAffected: 0, rows: new Array() }, o, i, selectRegexp, insertRegexp, deleteRegexp, match, tblName, tblDesc, tblData, k, paramsDesc, paramName, s, orConditions;
            if (!params) {
                params = [];
            }
            if (!data.rows["item"]) {
                data.rows["item"] = function (i) {
                    return this[i];
                };
            }
            if (isAmplifyStoreUsed) {
                try  {
                    selectRegexp = new RegExp("(SELECT) *(.*) *FROM (\\w+)");
                    insertRegexp = new RegExp("(INSERT OR REPLACE|INSERT) *(.*) *INTO *(\\w*) *\\(([\\w|,| ]*)\\)");
                    deleteRegexp = new RegExp("(DELETE) *(.*) *FROM (\\w+) *(\\w*)WHERE (\\w+)='*([^']+)");
                    if (sqlCommand.match(insertRegexp)) {
                        match = insertRegexp.exec(sqlCommand);
                        if (match && match.length > 1) {
                            tblName = match[3];
                            tblDesc = amplifyTables[tblName];
                            tblData = amplify.store("wijevcal_tbl_" + tblName);
                            if (tblData) {
                                paramsDesc = match[4].split(",");
                                o = {};
                                for (i = 0; i < paramsDesc.length; i += 1) {
                                    if (paramsDesc[i]) {
                                        if (i === 0) {
                                            //qq: this will work only when first
                                            //  field is unique, elaborate:
                                            tblData[params[i]] = o;
                                        }
                                        paramName = paramsDesc[i].replace(" ", "");
                                        o[paramName] = params[i];
                                    }
                                }
                            }
                            amplify.store("wijevcal_tbl_" + tblName, tblData);
                        }
                    } else if (sqlCommand.match(selectRegexp)) {
                        match = selectRegexp.exec(sqlCommand);
                        if (match && match.length > 1) {
                            tblName = match[3];
                            tblDesc = amplifyTables[tblName];
                            tblData = amplify.store("wijevcal_tbl_" + tblName);
                            if (tblData) {
                                s = sqlCommand.replace(selectRegexp, "");
                                if (s.toUpperCase().indexOf(" WHERE ") === 0) {
                                    // WHERE found
                                    s = s.substr(7);
                                    orConditions = s.split(" OR ");
                                    for (i = 0; i < orConditions.length; i += 1) {
                                        orConditions[i] = orConditions[i].split("=");
                                        s = orConditions[i][1];
                                        if (s.indexOf("'") === 0) {
                                            s = s.substring(1, s.length - 1);
                                            orConditions[i][1] = s;
                                        } else {
                                            //qq: elaborate other types
                                            orConditions[i][1] = parseFloat(s);
                                        }
                                    }
                                }
                                for (k in tblData) {
                                    if (tblData.hasOwnProperty(k)) {
                                        o = tblData[k];
                                        if (o) {
                                            if (orConditions) {
                                                for (i = 0; i < orConditions.length; i += 1) {
                                                    if (o[orConditions[i][0]] === orConditions[i][1]) {
                                                        data.rows.push(o);
                                                    }
                                                }
                                            } else {
                                                data.rows.push(o);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    } else if (sqlCommand.match(deleteRegexp)) {
                        match = deleteRegexp.exec(sqlCommand);

                        if (match && match.length > 1) {
                            tblName = match[3];
                            tblDesc = amplifyTables[tblName];
                            tblData = amplify.store("wijevcal_tbl_" + tblName);

                            // match[5] key name (e.g. id)
                            // match[6] key value (e.g. ASD-AS@--FSAFS$%-!)
                            if (tblData) {
                                // qq: test for calendars
                                if (tblData[match[6]]) {
                                    delete tblData[match[6]];
                                }
                            }
                            amplify.store("wijevcal_tbl_" + tblName, tblData);
                        }
                    }
                    if (successHandler) {
                        successHandler(data);
                    }
                } catch (ex1) {
                    if (errorHandler) {
                        errorHandler(ex1);
                    }
                }
            } else {
                if (!database) {
                    errorHandler("Local data storage not found.");
                    return;
                }
                database.transaction(function (tx) {
                    tx.executeSql(sqlCommand, params, function (tx, result) {
                        if (successHandler) {
                            successHandler(result);
                        }
                    }, function (tx, error) {
                        if (errorHandler) {
                            errorHandler(error.message);
                        }
                        return;
                    });
                });
            }
        }

        /////////////// <end of data layer
        /** @widget */
        var wijevcal = (function (_super) {
            __extends(wijevcal, _super);
            function wijevcal() {
                _super.apply(this, arguments);
                this._dynIdCounter = 0;
            }
            // handle option changes:
            wijevcal.prototype._setOption = function (key, value) {
                // when the setOption runs in chrome, because the web local storage is asynchronous,
                // when set the event data to the event calender, the init data from local storage
                // is getting the data, if this time set the value, the local storage data will override
                // the set value.
                // defined some deffered object
                var self = this, newDfd = $.when.apply(this, self._defferObjs), val;

                // when all deffered object has complete, fire the callbacks
                newDfd.always(function () {
                    self._setOptionCallbacks.fire();
                    self._setOptionCallbacks.empty();
                    self._defferObjs = [];
                });

                // if the deffered object is not complete, put the setOption method to the callback
                if (newDfd.state() === "pending") {
                    this._setOptionCallbacks.add(function () {
                        if ($.isPlainObject(value)) {
                            val = $.extend(true, {}, value);
                        } else if ($.isArray(value)) {
                            val = [].concat(value);
                        } else {
                            val = value;
                        }
                        self._setOptionInternal(key, val);
                    });
                } else {
                    this._setOptionInternal(key, value);
                }
            };

            wijevcal.prototype._setOptionInternal = function (key, value) {
                var self = this, o = self.options, culture, calendarCulture, toolsBar, viewIndex, viewType, view;
                switch (key) {
                    case "dataSource":
                        o.dataSource = value;
                        self._needLoadLocalStorage = false;
                        o.eventsData = [];
                        self._bindDataView();
                        break;
                    case "eventsData":
                        o.eventsData = value;
                        o.appointments = value; //remove deprecated appointments option?
                        self._needLoadLocalStorage = false;
                        self._onEventsDataChanged();
                        self._bindEvents();
                        break;
                    case "appointments":
                        o.eventsData = value;
                        o.appointments = value; //remove deprecated appointments option?
                        self._needLoadLocalStorage = false;
                        self._onEventsDataChanged();
                        self._bindEvents();
                        break;
                    case "localization":
                        self._setLocalization(value);
                        break;
                    case "culture":
                    case "cultureCalendar":
                        o[key] = value;
                        self._innerCulture = null;
                        self._resetCulture();
                        self.element.find(".wijmo-wijdatepager").wijdatepager("option", key, value);
                        if (self._editEventDialog) {
                            self._editEventDialog.find(".wijmo-wijinput-date").wijinputdate("option", key, value);
                        }
                        self.element.find(".wijmo-wijcalendar").wijcalendar("option", key, value);
                        self._redrawActiveView(); // fix for 23766
                        break;
                    case "calendar":
                        self.element.find(".wijmo-wijcalendar").wijcalendar("option", value);
                        self._redrawActiveView();
                        break;
                    case "disabled":
                        if (o.disabled !== value) {
                            o.disabled = value;
                            self._ensureDisabled();
                        }
                        break;
                    case "enableLogs":
                        o.enableLogs = value;
                        self._initLogPanel();
                        break;
                    case "selectedDate":
                        if (value) {
                            value = _toDayDate(value);
                            if (o.selectedDates[0].getTime() !== value.getTime()) {
                                o.selectedDates[0] = value;
                                self._onSelectedDatesChanged();
                            }
                        }
                        return;
                    case "selectedDates":
                        if (value) {
                            o.selectedDates = value;
                            self._onSelectedDatesChanged();
                        }
                        return;
                    case "statusBarVisible":
                        o.statusBarVisible = value;
                        self._initStatusbar();
                        self.invalidate();
                        return;
                    case "headerBarVisible":
                        o.headerBarVisible = value;
                        self._initHeaderbar();
                        self.invalidate();
                        return;
                    case "navigationBarVisible":
                        o.navigationBarVisible = value;
                        self._initNavigationbar();
                        self.invalidate();
                        return;
                    case "rightPaneVisible":
                        o.rightPaneVisible = value;
                        self._initRightPane();
                        self.invalidate();
                        return;
                    case "timeInterval":
                    case "timeIntervalHeight":
                    case "timeRulerInterval":
                    case "timeRulerFormat":
                        if (o[key] !== value) {
                            o[key] = value;
                            self._redrawActiveView();
                        }
                        break;
                    case "firstDayOfWeek":
                        if (o[key] !== value) {
                            o[key] = value;
                            self._redrawActiveView();

                            //set the calendar's first day of week.
                            culture = self._getCulture();
                            if (culture && culture.calendar) {
                                culture.calendar.firstDay = value;

                                calendarCulture = self.element.find(".wijmo-wijcalendar").data("wijmo-wijcalendar");
                                if (calendarCulture && calendarCulture._getCulture && calendarCulture.refresh) {
                                    calendarCulture._getCulture().calendar.firstDay = value;
                                    calendarCulture.refresh();
                                }
                            }
                        }
                        break;
                    case "viewType":
                        if (o.viewType !== value) {
                            o.viewType = value;
                            self._updateSelectedDates();
                        }
                        break;
                    case "views":
                        if (o.views !== value) {
                            if (!value || value.length === 0) {
                                o.views = ["day"];
                            } else {
                                o.views = value;
                            }
                            self._unBindToolsBarEvent();
                            toolsBar = self.element.find(".wijmo-wijev-headerbar .wijmo-wijev-tools");
                            toolsBar.empty();
                            toolsBar.append(self._getToolsButtonMarkup());
                            viewIndex = self._getCurrentViewIndex();
                            view = o.views[viewIndex];
                            viewType = $.isPlainObject(view) ? view.name : view;
                            if (o.viewType !== viewType) {
                                o.viewType = viewType;
                                self._updateSelectedDates();
                            }
                            toolsBar.find("input:eq(" + viewIndex + ")")[0]["checked"] = true;
                            self._setToolsBar();
                            self.invalidate();
                        }
                        break;
                    case "ensureEventDialogOnBody":
                        if (o.ensureEventDialogOnBody !== !!value && self._editEventDialog) {
                            self._updateEditEventDialog(!!value);
                        }
                        break;
                    default:
                        break;
                }

                $.wijmo.widget.prototype._setOption.apply(self, arguments);
            };

            wijevcal.prototype._updateEditEventDialog = function (ensureEventDialogOnBody) {
                var self = this;
                if (!self._editEventDialog) {
                    return;
                }
                if (ensureEventDialogOnBody) {
                    $("body").append(self._editEventDialog);
                } else {
                    self.element.append(self._editEventDialog);
                }
            };

            wijevcal.prototype._updateSelectedDates = function () {
                var self = this, o = this.options;
                if (o.viewType.toLowerCase() === "day" || o.viewType.toLowerCase() === "list") {
                    o.selectedDates = [o.selectedDate];
                }
                self._onViewTypeChanged();
            };

            wijevcal.prototype._setLocalization = function (value) {
                this._destroyInternal();
                this.options.localization = value;
                this._create();
                this._init();
            };

            wijevcal.prototype._ensureDisabled = function () {
                var o = this.options;
                if (this._isDisabled()) {
                    this.element.addClass(o.wijCSS.stateDisabled);
                    try  {
                        this.element.find(".wijmo-wijcalendar").wijcalendar("option", "disabled", true);
                        this.element.find(".wijmo-wijsuperpanel").wijsuperpanel("option", "disabled", true);
                        this.element.find(".wijmo-wijdatepager").wijdatepager("option", "disabled", true);

                        if ($().buttonset) {
                            this.element.find(".ui-buttonset").buttonset("option", "disabled", true);
                        }
                        this.element.find(".wijmo-wijev-today.ui-button").button("option", "disabled", true);
                        //this.element.find(".ui-button.ui-widget").button("option", "disabled", true);
                    } catch (ex) {
                        this.log(ex, "error");
                        //fix for:
                        //Error: cannot call methods on button prior to initialization; attempted to call method 'option'
                    }
                    this._unbindEvents();
                } else {
                    this.element.removeClass(o.wijCSS.stateDisabled);

                    try  {
                        this.element.find(".wijmo-wijcalendar").wijcalendar("option", "disabled", false);
                        this.element.find(".wijmo-wijsuperpanel").wijsuperpanel("option", "disabled", false);
                        this.element.find(".wijmo-wijdatepager").wijdatepager("option", "disabled", false);
                        if ($().buttonset) {
                            this.element.find(".ui-buttonset").buttonset("option", "disabled", false);
                        }
                        this.element.find(".wijmo-wijev-today.ui-button").button("option", "disabled", false);
                        //this.element.find(".ui-button").button("option", "disabled", false);
                    } catch (ex) {
                        this.log(ex, "error");
                        //fix for:
                        //Error: cannot call methods on button prior to initialization; attempted to call method 'option'
                    }
                    this._bindEvents();
                    this._updateTitleText();
                }
            };

            wijevcal.prototype._isCustomView = function (viewIndex) {
                var self = this, index = viewIndex || self._getCurrentViewIndex();
                return index < 0 ? false : $.isPlainObject(self.options.views[index]);
            };

            wijevcal.prototype._resetSuperPanelScrollPosition = function (superPanel) {
                superPanel.each(function (index, ele) {
                    var scrollPanel = $(ele);
                    if (scrollPanel.data("wijmoWijsuperpanel")) {
                        scrollPanel.wijsuperpanel("option", "vScroller").scrollValue = 0;
                        scrollPanel.wijsuperpanel("option", "hScroller").scrollValue = 0;
                    }
                });
            };

            wijevcal.prototype._onViewTypeChanged = function () {
                var self = this, o = self.options, viewIndex = self._getCurrentViewIndex(), isCustomView = self._isCustomView(viewIndex), superPanel = this.element.find(".wijmo-wijev-panel");
                if (superPanel) {
                    self._resetSuperPanelScrollPosition(superPanel);
                }
                self._renderActiveView();
                self._updateTitleText();
                self._resetHeaderContainer();
                self._trigger("viewTypeChanged", null, self.options.viewType);
                self.element.find(".wijmo-wijev-datepager").wijdatepager("option", "viewType", isCustomView ? "custom" : self.options.viewType);
                if (isCustomView) {
                    self.element.find(".wijmo-wijev-datepager").wijdatepager("option", "customViewOptions", o.views[viewIndex]);
                }
            };

            wijevcal.prototype._onSelectedDatesChanged = function () {
                var self = this, o = self.options;
                o.selectedDate = o.selectedDates[0];
                self.element.find(".wijmo-wijev-datepager").wijdatepager("option", "selectedDate", o.selectedDate);
                self._trigger("selectedDatesChanged", null, { selectedDates: o.selectedDates });
                self._renderActiveView();
                self._updateTitleText();
                self._updateHeaderPosition(); //To ensure that header's position is correct when selected dates changed.
            };

            wijevcal.prototype._updateHeaderPosition = function () {
                var self = this, data = { afterPosition: { left: 0 } }, scrollPanel = self.element.find(".wijmo-wijev-scrollpanel"), scrollValue = scrollPanel.wijsuperpanel("option", "hScroller").scrollValue;
                data.afterPosition.left = -scrollPanel.wijsuperpanel("scrollValueToPx", scrollValue, "h");
                self._scrolling(null, data);
            };

            wijevcal.prototype._updateHeaderTitleText = function () {
                var self = this, o = self.options, fmt = o.titleFormat, viewStart = o.selectedDates[0], viewEnd = o.selectedDates[o.selectedDates.length - 1], viewIndex = self._getCurrentViewIndex(), isCustomView = self._isCustomView(viewIndex), viewType, viewStartNonDayView = new Date(o.selectedDate.getFullYear(), o.selectedDate.getMonth(), 1);
                if (isCustomView) {
                    viewType = "custom";
                } else {
                    viewType = o.viewType;
                }

                if (viewType === "month") {
                    viewStart = viewStartNonDayView;
                    viewEnd = self._addMonths(viewStart, 1);
                    viewEnd = self._addDays(viewEnd, -1);
                }

                if (fmt[viewType]) {
                    fmt = fmt[viewType];
                } else if (fmt[viewType] === false) {
                    self.element.find(".wijmo-wijev-view .wijmo-wijev-header-title").hide();
                    return;
                } else {
                    fmt = fmt.toString();
                }
                if (o.viewType === "list") {
                    viewEnd = self._addDays(viewStart, 14);
                } else if (isCustomView) {
                    switch (self._getCustomViewUnit()) {
                        case "month":
                            viewStart = viewStartNonDayView;
                            viewEnd = self._addMonths(viewStart, (o.views[viewIndex].count || 1) - 1);
                            break;
                        case "year":
                            viewStart = viewStartNonDayView;
                            viewEnd = self._addYears(viewStart, (o.views[viewIndex].count || 1) - 1);
                            break;
                    }
                }
                self.element.find(".wijmo-wijev-view .wijmo-wijev-header-title").show().html(self._formatString(fmt, viewStart, viewEnd));
            };
            wijevcal.prototype._updateTitleText = function () {
                var self = this, o = self.options, viewStart = o.selectedDates[0], viewEnd = o.selectedDates[o.selectedDates.length - 1], todayDate = new Date(), isTodayShown = false;
                isTodayShown = self._compareDayDates(viewStart, todayDate) === 0 || (viewStart < todayDate && self._addDays(viewEnd, 1) > todayDate);
                if ($.mobile == null) {
                    self.element.find(".wijmo-wijev-navigationbar .wijmo-wijev-today").button("option", "disabled", isTodayShown);
                }
                self._updateHeaderTitleText();
            };

            /** Get the localized string by key
            * @param {string} key The key of the localized string.
            * @param {string} defaultValue The default value of the localized string.
            * @returns {string} The localized string.
            */
            wijevcal.prototype.localizeString = function (key, defaultValue) {
                var o = this.options;
                if (o.localization && o.localization[key]) {
                    return o.localization[key];
                }
                return defaultValue;
                //("buttonToday", "today")
            };

            wijevcal.prototype._create = function () {
                // enable touch support:
                if (window.wijmoApplyWijTouchUtilEvents) {
                    $ = window.wijmoApplyWijTouchUtilEvents($);
                }

                var self = this, newViews, navigationbar, toolsBar, o = self.options, _isCustomView = self._isCustomView();

                self._defferObjs = [];
                self._chromeLoadDataDeffer = $.Deferred();
                self._defferObjs.push(self._chromeLoadDataDeffer);
                self._setOptionCallbacks = $.Callbacks("once");
                self._needLoadLocalStorage = true;
                if ((self.options.appointments && self.options.appointments.length) || (self.options.eventsData && self.options.eventsData.length)) {
                    self._needLoadLocalStorage = false;
                }

                // Add for parse date options for jUICE. D.H
                if ($.isFunction(window["wijmoASPNetParseOptions"])) {
                    window["wijmoASPNetParseOptions"](self.options);
                }

                // fix problem with array options:
                if (!o.colors) {
                    o.colors = [
                        "red", "darkorchid", "green",
                        "blue", "cornflowerblue", "yellow", "bronze"
                    ];
                }
                if (!self.wijevcalnamespacekey) {
                    self.wijevcalnamespacekey = "wijevcal" + new Date().getTime();
                }
                if (!self.element[0].id) {
                    self.element[0].id = "wijevcal_dynid_" + new Date().getTime();
                }
                self._uidPref = self.element[0].id + "evcdynid";
                self.element.addClass("wijmo-wijevcal wijmo-wijev " + o.wijCSS.widget + " " + o.wijCSS.helperReset + " " + o.wijCSS.stateDefault);

                newViews = (!!o.views && o.views.length > 0) ? self._viewsToLower(o.views) : ["day"];
                if (self._getCurrentViewIndex() < 0) {
                    o.viewType = self._isCustomView(0) ? newViews[0].name : newViews[0];
                }

                // ui-helper-clearfix ui-corner-all
                //<fieldset data-role="controlgroup" data-type="horizontal" >
                //$("<div class=\"wijmo-wijev-headerbar ui-widget-header ui-corner-top\">" +
                $("<div class=\"wijmo-wijev-headerbar " + o.wijCSS.header + " " + o.wijCSS.cornerTop + "\">" + "<fieldset class=\"wijmo-wijev-tools\">" + self._getToolsButtonMarkup() + "</fieldset>" + "</div>").appendTo(self.element);

                $("<div class=\"wijmo-wijev-view-container\">" + "<div class=\"wijmo-wijev-leftpane wijmo-wijev-viewdetails " + o.wijCSS.content + " wijmo-wijev-day-details\">" + "<div class=\"wijmo-wijev-leftpane-inner\">" + "<div class=\"wijmo-wijev-daycalendar\"></div>" + "<div class=\"wijmo-wijev-monthday-container\">" + "<div class=\"wijmo-wijev-monthday-label\">...</div>" + "<div class=\"wijmo-wijev-fulldate-label\">" + self.localizeString("activityLoading", "Loading...") + "</div>" + "<div class=\"wijmo-wijev-year-label\">...</div>" + "</div>" + "<div class=\"wijmo-wijev-agenda-container " + o.wijCSS.content + " " + o.wijCSS.cornerAll + " " + o.wijCSS.helperClearFix + "\"></div>" + "</div>" + "</div>" + "<div class=\"wijmo-wijev-leftpane wijmo-wijev-viewdetails " + o.wijCSS.content + " wijmo-wijev-list-details\">" + "<div class=\"wijmo-wijev-leftpane-inner\">" + "<div class=\"wijmo-wijev-agenda-container " + o.wijCSS.content + " " + o.wijCSS.cornerAll + " " + o.wijCSS.helperClearFix + "\">&nbsp;" + "</div>" + "</div>" + "</div>" + "<div class=\"wijmo-wijev-rightpane\">" + "&nbsp;</div>" + "</div>").appendTo(self.element);

                $("<div class=\"wijmo-wijev-loading-modal-frame\"></div>" + "<div class=\"wijmo-wijev-loading\">" + "<div class=\"wijmo-wijev-loading-text\">" + self.localizeString("activityLoading", "Loading...") + "</div></div>").appendTo(self.element);

                $("<div class=\"wijmo-wijev-navigationbar " + o.wijCSS.header + " " + o.wijCSS.cornerBottom + " " + o.wijCSS.helperClearFix + "\">" + "<a class=\"wijmo-wijev-today\">" + self.localizeString("buttonToday", "today") + "</a>" + "<div class=\"wijmo-wijev-datepager\">" + "</div>" + "</div>").appendTo(self.element);

                //
                //$("<div class=\"wijmo-wijev-statusbar ui-widget-header ui-corner-bottom\">" +
                $("<div class=\"wijmo-wijev-statusbar " + o.wijCSS.header + " " + o.wijCSS.cornerBottom + "\">" + "</div>").appendTo(self.element);

                navigationbar = self.element.find(".wijmo-wijev-navigationbar");

                if ($.mobile != null) {
                    navigationbar.find(".wijmo-wijev-today").addClass("ui-btn ui-btn-corner-all").click($.proxy(self._onTodayClick, self));
                } else {
                    navigationbar.find(".wijmo-wijev-today").button({
                        text: self.localizeString("buttonToday", "today")
                    }).click($.proxy(self._onTodayClick, self));
                }

                self._setToolsBar();

                self.element.find(".wijmo-wijev-datepager").wijdatepager({
                    customViewOptions: _isCustomView ? o.views[self._getCurrentViewIndex()] : {},
                    selectedDate: o.selectedDate,
                    localization: o.datePagerLocalization,
                    culture: o.culture,
                    cultureCalendar: o.cultureCalendar,
                    viewType: _isCustomView ? "custom" : o.viewType,
                    nextTooltip: self.localizeString("navigatorBarNextTooltip", "right"),
                    prevTooltip: self.localizeString("navigatorBarPrevTooltip", "left"),
                    firstDayOfWeek: o.firstDayOfWeek,
                    selectedDateChanged: $.proxy(function (e, args) {
                        self.goToDate(args.selectedDate);
                    }, self)
                });

                // Fix case #41050
                if (self.element.wijAddVisibilityObserver) {
                    self.element.wijAddVisibilityObserver(function () {
                        if (self.element.wijRemoveVisibilityObserver) {
                            self.element.wijRemoveVisibilityObserver();
                        }
                        self._redrawActiveView();
                    }, "wijevcal");
                }

                //
                self.showLoadingLabel();

                _super.prototype._create.call(this);
            };

            wijevcal.prototype._setToolsBar = function () {
                var self = this, toolsBar = self.element.find(".wijmo-wijev-headerbar .wijmo-wijev-tools"), o = self.options;
                if ($.mobile == null) {
                    toolsBar.find(".wijmo-wijev-day").button().button("widget").addClass(o.wijCSS.stateDefault);
                    toolsBar.find(".wijmo-wijev-week").button().button("widget").addClass(o.wijCSS.stateDefault);
                    toolsBar.find(".wijmo-wijev-month").button().button("widget").addClass(o.wijCSS.stateDefault);
                    toolsBar.find(".wijmo-wijev-list").button().button("widget").addClass(o.wijCSS.stateDefault);
                    $.each(toolsBar.find(".wijmo-wijev-custom"), function (index, item) {
                        $(item).button().button("widget").addClass(o.wijCSS.stateDefault);
                    });
                    toolsBar.buttonset();
                } else {
                    toolsBar.attr("data-role", "controlgroup");
                    toolsBar.attr("data-type", "horizontal");

                    //toolsBar.attr("data-mini", "true");
                    toolsBar.parent().trigger("create");
                    toolsBar.controlgroup("refresh");
                }
                self._bindToolsBarEvent();
            };

            wijevcal.prototype._bindToolsBarEvent = function () {
                var self = this, toolsBar = self.element.find(".wijmo-wijev-headerbar .wijmo-wijev-tools"), o = self.options;
                toolsBar.find(".wijmo-wijev-day").click($.proxy(self._onDayViewClick, self));
                toolsBar.find(".wijmo-wijev-week").click($.proxy(self._onWeekViewClick, self));
                toolsBar.find(".wijmo-wijev-month").click($.proxy(self._onMonthViewClick, self));
                toolsBar.find(".wijmo-wijev-list").click($.proxy(self._onListViewClick, self));
                toolsBar.find(".wijmo-wijev-custom").click($.proxy(self._onCustomViewClick, self));
            };

            wijevcal.prototype._unBindToolsBarEvent = function () {
                var self = this, toolsBar = self.element.find(".wijmo-wijev-headerbar .wijmo-wijev-tools"), o = self.options;
                toolsBar.find(".wijmo-wijev-day").unbind("click");
                toolsBar.find(".wijmo-wijev-week").unbind("click");
                toolsBar.find(".wijmo-wijev-month").unbind("click");
                toolsBar.find(".wijmo-wijev-list").unbind("click");
                toolsBar.find(".wijmo-wijev-custom").unbind("click");
            };

            wijevcal.prototype._viewsToLower = function (views) {
                var newViews = [];
                $.each(views, function (i, view) {
                    newViews.push(typeof view === "string" ? view.toLowerCase() : view);
                });
                return newViews;
            };

            wijevcal.prototype._getToolsButtonMarkup = function () {
                var self = this, o = self.options, lowerCaseViews = self._viewsToLower(o.views), localizedTitle, toolsButtonMarkup = "", viewName, inputId;

                $.each(lowerCaseViews, function (index, view) {
                    var isViewValidate = false;
                    if ($.isPlainObject(view)) {
                        localizedTitle = self.localizeString("customView", view.name || "Custom");
                        viewName = "custom";
                        inputId = "custom" + view.name;
                        isViewValidate = true;
                    } else {
                        inputId = viewName = view;
                        isViewValidate = true;
                        switch (view) {
                            case "day":
                                localizedTitle = self.localizeString("buttonDayView", "Day");
                                break;
                            case "week":
                                localizedTitle = self.localizeString("buttonWeekView", "Week");
                                break;
                            case "month":
                                localizedTitle = self.localizeString("buttonMonthView", "Month");
                                break;
                            case "list":
                                localizedTitle = self.localizeString("buttonListView", "List");
                                break;
                            default:
                                isViewValidate = false;
                                break;
                        }
                    }
                    if (isViewValidate) {
                        toolsButtonMarkup += "<input id=\"" + self._uidPref + "_" + inputId + "btn\" name=\"viewselection\"" + " type=\"radio\" class=\"wijmo-wijev-" + viewName + "\" value='" + index + "' />" + "<label for=\"" + self._uidPref + "_" + inputId + "btn\">" + localizedTitle + "</label>";
                    }
                });

                return toolsButtonMarkup;
            };

            /** @ignore*/
            wijevcal.prototype.showLoadingLabel = function (text, isModal) {
                if (text === false) {
                    this.element.find(".wijmo-wijev-loading-text").hide();
                } else {
                    this.element.find(".wijmo-wijev-loading-text").show();
                    if (!text) {
                        text = this.localizeString("activityLoading", "Loading...");
                    }
                }
                if (isModal === undefined || isModal === true) {
                    this.element.find(".wijmo-wijev-loading-modal-frame").show();
                }
                this.element.find(".wijmo-wijev-loading").show();
                this.element.find(".wijmo-wijev-loading-text").html(text);
            };

            /** hide the loading label*/
            wijevcal.prototype.hideLoadingLabel = function () {
                this.element.find(".wijmo-wijev-loading-modal-frame").hide();
                this.element.find(".wijmo-wijev-loading").hide();
            };

            /* initialization code > */
            wijevcal.prototype._init = function () {
                var o = this.options;
                if (o.selectedDates && o.selectedDates.length > 0) {
                    o.selectedDate = o.selectedDates[0] = _toDayDate(o.selectedDates[0]);
                } else if (o.selectedDate) {
                    o.selectedDate = _toDayDate(o.selectedDate);
                    if (!o.selectedDates) {
                        o.selectedDates = [];
                    }
                    o.selectedDates[0] = o.selectedDate;
                } else {
                    o.selectedDate = _toDayDate(new Date());
                    o.selectedDates = [o.selectedDate];
                }

                if (this._isDisabled()) {
                    this.element.addClass(o.wijCSS.stateDisabled);
                }

                this._initHeaderbar();

                this._initNavigationbar();

                this._initStatusbar();

                this._initRightPane();

                if (o.fullScreen) {
                    this._onFullScreenModeChanged(o.fullScreen);
                }
                this._initLogPanel();

                this._initLocalDataStorage(); // _loadData called here
                this.element.ajaxError(jQuery.proxy(this._onAjaxError, this));
                $(window).bind("resize." + this.wijevcalnamespacekey, $.proxy(this._onWindowResize, this));
                this._renderActiveView(); // invalidate called here

                //this._bindEvents();this._updateTitleText(); called here:
                this._bindDataView();
            };
            wijevcal.prototype._onFullScreenModeChanged = function (isFullscreen) {
                //qq:todo fullscreenmode
            };

            // wijdataview implementation
            wijevcal.prototype._isDataViewLoaded = function (dv) {
                return dv && (dv.isLoaded() || (dv.count() > 0));
            };

            wijevcal.prototype._isDataview = function (dv) {
                if (dv && typeof (dv) === "object" && !$.isArray(dv)) {
                    return true;
                }
            };

            wijevcal.prototype._getDataViewInst = function () {
                return this.element.data("wijdataview");
            };

            wijevcal.prototype._bindDataView = function () {
                var o = this.options, dataSource = o.dataSource, dataSource, self = this;

                if (!dataSource && this._getDataViewInst()) {
                    dataSource = this._getDataViewInst();
                    dataSource = o.dataSource = dataSource;
                }

                if (dataSource && this._isDataview(dataSource)) {
                    if (this._isDataViewLoaded(dataSource)) {
                        this._dataView = dataSource;
                        this._setOption("eventsData", dataSource.toArray());
                    } else {
                        dataSource.element.bind("dataloaded", function () {
                            self._dataView = dataSource;
                            self._setOption("eventsData", dataSource.toArray());
                        });
                        /*
                        //qq:?
                        .bind("datachange", function (e, args) {
                        if (args && args.length && args[0].changeType !== "reset") {
                        self.dataList = dataSource.dataView.toArray();
                        self._bindData();
                        self.redraw();
                        }
                        });*/
                    }
                } else {
                    this._dataView = null;
                }
                /*
                qq:?
                if (!self._needloaded) {
                self._bindData();
                }*/
            };

            wijevcal.prototype._initLocalDataStorage = function () {
                try  {
                    isAmplifyStoreUsed = false;
                    if (window["amplify"] && window["amplify"].store) {
                        try  {
                            amplifyTables = amplify.store("wijevcal_tables1");
                            isAmplifyStoreUsed = true;
                            this.log("Using amplify.store for the local data storage");
                        } catch (amplex) {
                            this.log("amplify.store exception:" + amplex);

                            // attempt to load data using web service or custom methods
                            this._loadData();
                            return;
                        }
                        //amplify.store("key", "test-1")
                    } else if (window["openDatabase"]) {
                        try  {
                            database = window["openDatabase"](databaseName, databaseVer, "Wijmo Events Calendar Offline DB", 200000);
                        } catch (ex) {
                            this.log("web sql database error: " + ex);

                            // attempt to load data using web service or custom methods
                            this._loadData();
                            return;
                        }
                        if (!database) {
                            this.log("Failed to open the database on disk." + " This is probably because the version was bad or" + " there is not enough space left in this domain's quota");

                            // attempt to load data using web service or custom methods
                            this._loadData();
                            return;
                        }
                        this.log("Using Web SQL Database for the local data storage.");
                    } else {
                        this.log(this.localizeString("logCouldntOpenLocalStorage", "Couldn't open built-in local data storage." + " Please, add amplify.store references."));

                        // attempt to load data using web service or custom methods
                        this._loadData();
                        return;
                    }

                    // Create tables:
                    ensureTableCreated("calendars", "(id TEXT PRIMARY KEY, name TEXT, location TEXT, description TEXT, " + "color TEXT, tag TEXT)");

                    var tableDeffered = $.Deferred(), self = this;
                    this._defferObjs.push(tableDeffered);

                    ensureTableCreated("events", "(id TEXT PRIMARY KEY, calendar TEXT, subject TEXT, location TEXT, " + "start TIMESTAMP, end TIMESTAMP, description TEXT, color TEXT, " + "allday INTEGER, properties TEXT, tag TEXT)", function () {
                        self._loadData();
                        tableDeffered.resolve();
                    });
                    //();
                    /*
                    TEXT
                    NUMERIC
                    INTEGER
                    REAL
                    NONE
                    */
                } catch (err) {
                    this.log("local datastorage initialization error:" + err);
                }
                /* << end of local data storage initialization */
            };
            wijevcal.prototype._initStatusbar = function () {
                var statusbar = this.element.find(".wijmo-wijev-statusbar");
                if (!this.options.statusBarVisible) {
                    statusbar.hide();
                    return;
                } else {
                    statusbar.css("float", "left");
                    statusbar.show();
                }

                if (!this.statusbarEventsAdded) {
                    this.statusbarEventsAdded = true;
                }
            };
            wijevcal.prototype._initHeaderbar = function () {
                var headerbar = this.element.find(".wijmo-wijev-headerbar");
                if (!this.options.headerBarVisible) {
                    headerbar.hide();
                    return;
                } else {
                    headerbar.show();
                }
            };
            wijevcal.prototype._initNavigationbar = function () {
                var navigationbar = this.element.find(".wijmo-wijev-navigationbar");
                if (!this.options.navigationBarVisible) {
                    navigationbar.hide();
                    return;
                } else {
                    navigationbar.show();
                }
            };

            //
            wijevcal.prototype._initRightPane = function () {
                var rightpane = this.element.find(".wijmo-wijev-rightpane");
                if (!this.options.rightPaneVisible) {
                    rightpane.hide();
                    return;
                } else {
                    rightpane.show();
                }
            };
            wijevcal.prototype._initLogPanel = function () {
                if (this.options.enableLogs) {
                    this._createLogPanel();
                    this.log = this._log;
                } else {
                    if (this.logDialog) {
                        this.logDialog.wijdialog("close");
                    }
                    this.log = function () {
                    };
                }
            };

            /* < end of initialization code*/
            wijevcal.prototype._handleServerError = function (answer) {
                if (answer && answer.toString().indexOf("error:") === 0) {
                    this.status(answer.toString(), "error");
                    return true;
                }
                return false;
            };
            wijevcal.prototype._loadData = function () {
                var o = this.options, self = this, i, count, cal, appt, calendarsById, eventsDataById, query, loadCalendarsCallback, loadEventsCallback, errorCallback, calendarDeffered, eventDeffered, needLoadEventsData;

                //successCallback
                this.showLoadingLabel();

                // these codes has an issue in chrome.
                errorCallback = function (e) {
                    // fixed an issue that if the can't support the local storage and not set the dataStorage, webServiceUrl,
                    // when user set the eventsData in the option, the widget will not show the events data.
                    if (e === "Local data storage not found.") {
                        needLoadEventsData = true;
                    }
                    self.hideLoadingLabel();
                };

                o.calendars = [];
                calendarsById = this._calendarsById = {};

                loadCalendarsCallback = function (calendars) {
                    if (!o.calendars) {
                        o.calendars = [];
                    }
                    if (!calendars) {
                        return;
                    }
                    if (typeof calendars === "string") {
                        if (self._handleServerError(calendars)) {
                            errorCallback(calendars);
                            return;
                        }
                        try  {
                            calendars = self._jsonParse(calendars);
                        } catch (ex) {
                            self.status("Unable to parse received calendars data. " + ex, "error");

                            return;
                        }
                    }
                    if (calendars.calendars && calendars.calendars.length) {
                        calendars = calendars.calendars;
                    }
                    for (i = 0; i < calendars.length; i += 1) {
                        cal = self._cloneObj(calendars[i]);
                        cal.prevData = self._cloneObj(cal);
                        o.calendars.push(cal);
                        calendarsById[cal.id] = cal;
                    }
                    self._onCalendarsChanged();
                };

                if (o.dataStorage.loadCalendars) {
                    o.dataStorage.loadCalendars(loadCalendarsCallback, errorCallback);
                } else if (o.webServiceUrl) {
                    $.getJSON(o.webServiceUrl + "?clientId=" + this.element[0].id + "&command=loadCalendars" + "&calendars=" + o.calendars, loadCalendarsCallback);
                } else {
                    executeSql("SELECT * FROM calendars", [], function (data) {
                        for (i = 0, count = data.rows.length; i < count; i += 1) {
                            cal = self._cloneObj(data.rows.item(i));
                            cal.prevData = self._cloneObj(cal);
                            o.calendars.push(cal);
                            calendarsById[cal.id] = cal;
                        }
                        self._onCalendarsChanged();
                    }, errorCallback);
                }
                if (this._dataView) {
                    o.eventsData = this._dataView.toArray();
                } else {
                    //if init set the event data, when run it browser, the data will be cleared by the below code
                    //o.eventsData = [];
                }
                if (!this._eventsDataById) {
                    eventsDataById = this._eventsDataById = {};
                } else {
                    eventsDataById = this._eventsDataById;
                }

                if (!o.eventsData) {
                    o.eventsData = [];
                }

                loadEventsCallback = function (events) {
                    if (!events) {
                        return;
                    }
                    if (typeof events === "string") {
                        if (self._handleServerError(events)) {
                            errorCallback(events);

                            return;
                        }
                        try  {
                            events = self._jsonParse(events);
                        } catch (ex) {
                            self.log("Unable to parse received calendars data. " + ex);

                            return;
                        }
                    }
                    if (events.events && events.events.length) {
                        events = events.events;
                    }
                    for (i = 0; i < events.length; i += 1) {
                        if (!eventsDataById[events[i].id]) {
                            appt = self._readEventData(events[i]);
                            self._storeEventWithSort(appt);
                        }
                    }
                    self._onEventsDataChanged();
                    self._onInitialized();
                };

                if (o.dataStorage.loadEvents) {
                    o.dataStorage.loadEvents(o.visibleCalendars, loadEventsCallback, errorCallback);
                    self._chromeLoadDataDeffer.resolve();
                } else if (o.webServiceUrl) {
                    $.ajax({
                        url: o.webServiceUrl + "?clientId=" + this.element[0].id + "&command=loadEvents&timestamp=" + new Date().getTime(),
                        dataType: "text",
                        /*dataType: "json",*/
                        cache: false,
                        contentType: "application/json; charset=utf-8",
                        type: "POST",
                        //data: "jsonData=" +
                        //this._jsonStringify({ visibleCalendars: o.visibleCalendars }),
                        success: loadEventsCallback,
                        error: errorCallback
                    });
                    self._chromeLoadDataDeffer.resolve();
                } else {
                    if (this._dataView) {
                        this._onInitialized();
                        return;
                    }
                    query = "SELECT * FROM events";

                    //Append "where" condition only if visibleCalendars array is not empty.
                    if (o.visibleCalendars.length > 0) {
                        query += " where ";
                        for (i = 0; i < o.visibleCalendars.length; i += 1) {
                            if (i > 0) {
                                query += " OR ";
                            }
                            query += "calendar='" + o.visibleCalendars[i] + "'";
                        }
                    }
                    executeSql(query, [], function (data) {
                        if (self._needLoadLocalStorage) {
                            o.eventsData = [];
                            for (i = 0, count = data.rows.length; i < count; i += 1) {
                                appt = self._readEventData(data.rows.item(i));
                                self._storeEventWithSort(appt);
                            }
                        }
                        self._onEventsDataChanged();
                        self._onInitialized();
                        self._chromeLoadDataDeffer.resolve();
                    }, function () {
                        errorCallback.apply(this, arguments);

                        // if can't get the data from local storage, init the event by the option's data.
                        if (needLoadEventsData) {
                            self._onEventsDataChanged();
                            self._onInitialized();
                        }
                        self._chromeLoadDataDeffer.resolve();
                    });
                }
            };
            wijevcal.prototype._onInitialized = function () {
                this._ensureDisabled();
                this.hideLoadingLabel();
                this._trigger("initialized");
            };
            wijevcal.prototype._readEventData = function (data) {
                var appt = this._cloneObj(data);
                appt.start = new Date(appt["start"]);
                appt.end = new Date(appt["end"]);
                if (typeof appt.allday === "string") {
                    if (appt["allday"] === "false") {
                        appt.allday = false;
                    }
                    if (appt["allday"] === "true") {
                        appt.allday = true;
                    }
                }
                if (appt.start.getTime() >= appt.end.getTime()) {
                    // duration can not be 0.
                    appt.end = this._addMinutes(appt.start, this.options.timeInterval);
                }
                this._deSerializeProperties(appt["properties"], appt);
                appt.prevData = this._cloneObj(appt);
                return appt;
            };
            wijevcal.prototype._prepareEventsForView = function () {
                this._eventsView = this.getOccurrences();
            };

            wijevcal.prototype._cloneObj = function (o1) {
                var o2 = {}, k;
                for (k in o1) {
                    if (o1.hasOwnProperty(k)) {
                        o2[k] = o1[k];
                    }
                }
                return o2;
            };

            wijevcal.prototype._onDayViewClick = function () {
                var o = this.options;
                if (this._isDisabled()) {
                    return;
                }
                if (o.viewType !== "day") {
                    o.viewType = "day";
                    this._onViewTypeChanged();
                }
                o.selectedDates = [o.selectedDate];
                this._onSelectedDatesChanged();
            };

            wijevcal.prototype._onCustomViewClick = function (event) {
                var self = this, o = self.options, startDate, dayCount, i, customViewOptions;
                if (self._isDisabled()) {
                    return;
                }

                customViewOptions = o.views[$(event.target).val()] || { name: "Custom", unit: "day", count: 1 };
                if (o.viewType !== customViewOptions.name) {
                    o.viewType = customViewOptions.name;
                    self._onViewTypeChanged();
                }
                startDate = o.selectedDate;
                dayCount = customViewOptions.count || 1;
                switch (self._getCustomViewUnit()) {
                    case "week":
                        self._addSelectedDatesForWeekView(dayCount);
                        break;
                    case "day":
                        o.selectedDates = [];
                        for (i = 0; i < dayCount; i++) {
                            o.selectedDates.push(self._addDays(startDate, i));
                        }
                        self._onSelectedDatesChanged();
                        break;
                }
            };

            wijevcal.prototype._addSelectedDatesForWeekView = function (dayCount) {
                if (typeof dayCount === "undefined") { dayCount = 1; }
                var self = this, o = self.options, startDt, dt, i, startDate = o.selectedDate;
                i = o.firstDayOfWeek - startDate.getDay();
                if (Math.abs(i) > 6) {
                    i = startDate.getDay() - o.firstDayOfWeek;
                }
                startDate = self._addDays(startDate, i);
                o.selectedDates = [];
                for (i = 0; i < 7 * (dayCount || 1); i += 1) {
                    o.selectedDates.push(self._addDays(startDate, i));
                }
                self._onSelectedDatesChanged();
            };

            wijevcal.prototype._onWeekViewClick = function () {
                var self = this, o = self.options, dt, i;
                if (self._isDisabled()) {
                    return;
                }
                if (o.viewType !== "week") {
                    o.viewType = "week";
                    self._onViewTypeChanged();
                }
                self._addSelectedDatesForWeekView();
            };
            wijevcal.prototype._onMonthViewClick = function () {
                var o = this.options;
                if (this._isDisabled()) {
                    return;
                }
                if (o.viewType !== "month") {
                    o.viewType = "month";
                    this._onViewTypeChanged();
                }
            };
            wijevcal.prototype._onListViewClick = function () {
                var o = this.options;
                if (this._isDisabled()) {
                    return;
                }
                if (o.viewType !== "list") {
                    o.viewType = "list";
                    this._onViewTypeChanged();
                }
                o.selectedDates = [o.selectedDate];
                this._onSelectedDatesChanged();
            };

            // UI behavior
            /* dialogs */
            wijevcal.prototype._ensureEditCalendarDialogCreated = function () {
                var o = this.options, dialogContent, buttonsHash = {};
                if (!this._editCalendarDialog) {
                    dialogContent = o.editCalendarTemplate;
                    if (!dialogContent) {
                        dialogContent = "<p><label>" + this.localizeString("labelCalendarName", "Calendar name") + "</label>" + "<input type=\"text\" class=\"wijmo-wijev-name\" aria-label=\"Name\" value=\"\"> " + "<div class=\"wijmo-wijev-color-button\">" + "<div class=\"wijmo-wijev-color ui-wijmo-wijev-event-color-default\">&nbsp;</div>" + "</div>" + "</p>" + "<p><label>" + this.localizeString("labelLocation", "Location") + "</label>" + "<input type=\"text\" class=\"wijmo-wijev-location\" aria-label=\"Location\" value=\"\"></p>" + "<p><label>" + this.localizeString("labelDescription", "Description") + "</label><textarea class=\"wijmo-wijev-description\" aria-label=\"Description\"/></p>";
                    }
                    this._editCalendarDialog = $("<div class=\"wijmo-wijev-editcalendar-dialog\">" + dialogContent + "</div>");
                    this.element.append(this._editCalendarDialog);

                    buttonsHash[this.localizeString("buttonSave", "Save")] = $.proxy(function () {
                        try  {
                            var cal = this._validateAndReadCalendarDialogFields(this._editCalendarDialog);
                            if (cal.prevData) {
                                this.updateCalendar(cal);
                            } else {
                                this.addCalendar(cal);
                            }
                            this._editCalendarDialog.wijdialog("close");
                        } catch (ex) {
                            alert(ex);
                        }
                    }, this);
                    this._editCalendarDialog.wijdialog({
                        autoOpen: true,
                        height: 340,
                        width: 440,
                        modal: true,
                        title: this.localizeString("titleEditCalendar", "Edit calendar"),
                        buttons: buttonsHash,
                        captionButtons: {
                            pin: { visible: false },
                            refresh: { visible: false },
                            toggle: { visible: false },
                            minimize: { visible: false },
                            maximize: { visible: false }
                        }
                    });

                    this._editCalendarDialog.find(".wijmo-wijev-name, .wijmo-wijev-location, .wijmo-wijev-description").wijtextbox();

                    //
                    this._editCalendarDialog.find(".wijmo-wijev-color-button").button({
                        icons: { primary: o.wijCSS.iconArrowDown }
                    }).click($.proxy(this._onColorButtonClick, { dlg: this._editCalendarDialog, self: this }));
                }
            };
            wijevcal.prototype._ensureEditEventDialogCreated = function () {
                var o = this.options, dialogTemplate, isInputDropdownClosing = false, dateChangedByClicking = false;
                if (!this._editEventDialog) {
                    dialogTemplate = this.options.editEventDialogTemplate;
                    if (!dialogTemplate) {
                        dialogTemplate = "<div class=\"" + "wijmo-wijev-event-dialog " + this.options.wijCSS.content + " " + o.wijCSS.cornerAll + "\">" + "<ul class=\"wijmo-wijev-brief-content\">" + "<li><label>" + this.localizeString("labelName", "name") + "</label>" + "<input type=\"text\" name=\"subject\" class=\"wijmo-wijev-subject\" aria-label=\"Subject\" value=\"\">" + "<div class=\"wijmo-wijev-color-button\">" + "<div class=\"wijmo-wijev-color ui-wijmo-wijev-event-color-default\">&nbsp;</div>" + "</div>" + "</li>" + "<li><label for=\"" + this._uidPref + "_alldaybtn\">" + this.localizeString("labelAllDay", "all-day") + "</label>" + "<input type=\"checkbox\" class=\"wijmo-wijev-allday\" id=\"" + this._uidPref + "_alldaybtn\" />" + "</li>" + "<li><label>" + this.localizeString("labelStarts", "Starts") + "</label>" + "<input type=\"text\" class=\"wijmo-wijev-start\" value=\"\">" + "<input type=\"text\" class=\"wijmo-wijev-start-time\" value=\"\">" + "</li>" + "<li><label>" + this.localizeString("labelEnds", "Ends") + "</label>" + "<input type=\"text\" class=\"wijmo-wijev-end\" value=\"\">" + "<input type=\"text\" class=\"wijmo-wijev-end-time\" value=\"\">" + "</li>" + "</ul>" + "<ul class=\"wijmo-wijev-detailed-content " + o.wijCSS.cornerAll + "\">" + "<li><label>" + this.localizeString("labelLocation", "Location") + "</label>" + "<input type=\"text\" class=\"wijmo-wijev-location\" aria-label=\"Location\" value=\"\"></li>" + "<li><label>" + this.localizeString("labelRepeat", "Repeat") + "</label>" + "<select class=\"wijmo-wijev-repeat\">" + "<option value=\"none\">" + this.localizeString("repeatNone", "None") + "</option>" + "<option value=\"daily\">" + this.localizeString("repeatDaily", "Every Day") + "</option>" + "<option value=\"workdays\">" + this.localizeString("repeatWorkDays", "Work days") + "</option>" + "<option value=\"weekly\">" + this.localizeString("repeatWeekly", "Every Week") + "</option>" + "<option value=\"monthly\">" + this.localizeString("repeatMonthly", "Every Month") + "</option>" + "<option value=\"yearly\">" + this.localizeString("repeatYearly", "Every Year") + "</option>" + "</select></li>" + "<li><label>" + this.localizeString("labelCalendar", "Calendar") + "</label>" + "<select class=\"wijmo-wijev-calendar\"></select></li>" + "<li class=\"wijmo-wijev-description-item\"><label>" + this.localizeString("labelDescription", "Description") + "</label>" + "<textarea class=\"wijmo-wijev-description\" aria-label=\"Description\" /></li>" + "</ul>" + "<div class=\"footer\">" + "<a href=\"#\" class=\"wijmo-wijev-delete\">" + this.localizeString("buttonDelete", "Delete") + "</a>" + "<a href=\"#\" class=\"wijmo-wijev-save\">" + this.localizeString("buttonOK", "OK") + "</a>" + "<a href=\"#\" class=\"wijmo-wijev-cancel\">" + this.localizeString("buttonCancel", "Cancel") + "</a>" + "</div>" + "<div class=\"wijmo-wijev-angle\"></div>" + "</div>";
                    }

                    this._editEventDialog = $(dialogTemplate);
                    this._updateEditEventDialog(o.ensureEventDialogOnBody);

                    //color
                    this._initEventDialogButton(this._editEventDialog.find(".wijmo-wijev-color-button"), $.proxy(this._onColorButtonClick, { dlg: this._editEventDialog, self: this }), { icons: { primary: o.wijCSS.iconArrowDown } });

                    /*
                    this._editEventDialog.find(".wijmo-wijev-color-arrow").button({
                    icons: { primary: "ui-icon-triangle-1-s" },
                    text: false
                    }).click($.proxy(this._onColorButtonClick, this)).parent().buttonset();
                    */
                    //delete
                    this._initEventDialogButton(this._editEventDialog.find(".wijmo-wijev-delete"), $.proxy(function (ev) {
                        this.deleteEvent(this._editEventDialog.appt);
                        this._editEventDialog.wijpopup("hide");
                        ev.preventDefault();
                        return false;
                    }, this));

                    //close
                    this._initEventDialogButton(this._editEventDialog.find(".wijmo-wijev-cancel"), $.proxy(function (ev) {
                        this._editEventDialog.wijpopup("hide");
                        ev.preventDefault();
                        return false;
                    }, this));
                    this._editEventDialog.find(".wijmo-wijev-start").width(114).wijinputdate({
                        culture: this.options.culture,
                        cultureCalendar: this.options.cultureCalendar,
                        titleFormat: this.localizeString("calendarTitleFormat", "MMMM yyyy"),
                        toolTipFormat: this.localizeString("calendarToolTipFormat", "dddd, MMMM dd, yyyy"),
                        nextTooltip: this.localizeString("calendarNextTooltip", "Next"),
                        prevTooltip: this.localizeString("calendarPrevTooltip", "Previous"),
                        showDropDownButton: true,
                        dateFormat: "d",
                        dropDownOpen: function (e, data) {
                            isInputDropdownClosing = false;
                        },
                        dropDownClose: function (e, data) {
                            isInputDropdownClosing = true;
                            $(document).one("mouseup", function () {
                                isInputDropdownClosing = false;
                            });
                        },
                        dateChanged: $.proxy(function (e, args) {
                            if (isInputDropdownClosing) {
                                dateChangedByClicking = true;
                                $(document).one("mouseup", function () {
                                    dateChangedByClicking = false;
                                });
                            }
                            var endDt = this._editEventDialog.find(".wijmo-wijev-end").wijinputdate("option", "date");
                            if (args.date > endDt) {
                                this._editEventDialog.find(".wijmo-wijev-end").wijinputdate("option", "date", args.date);
                            }
                        }, this)
                    });
                    this._editEventDialog.find(".wijmo-wijev-start-time").width(80).wijinputdate({
                        culture: this.options.culture,
                        cultureCalendar: this.options.cultureCalendar,
                        titleFormat: this.localizeString("calendarTitleFormat", "MMMM yyyy"),
                        toolTipFormat: this.localizeString("calendarToolTipFormat", "dddd, MMMM dd, yyyy"),
                        nextTooltip: this.localizeString("calendarNextTooltip", "Next"),
                        prevTooltip: this.localizeString("calendarPrevTooltip", "Previous"),
                        showDropDownButton: false,
                        dateFormat: "t",
                        dateChanged: $.proxy(function (e, args) {
                            if (!args.date)
                                return;

                            var endDt = this._editEventDialog.find(".wijmo-wijev-end-time").wijinputdate("option", "date"), startDate = this._editEventDialog.find(".wijmo-wijev-start").wijinputdate("option", "date");

                            if (!startDate)
                                return;

                            if (args.date.getDate() !== startDate.getDate()) {
                                args.date.setDate(startDate.getDate());
                                this._editEventDialog.find(".wijmo-wijev-start-time").wijinputdate("option", "date", args.date);
                            }
                            if (args.date > endDt) {
                                this._editEventDialog.find(".wijmo-wijev-end-time").wijinputdate("option", "date", args.date);
                            }
                        }, this)
                    });
                    this._editEventDialog.find(".wijmo-wijev-end").width(114).wijinputdate({
                        culture: this.options.culture,
                        cultureCalendar: this.options.cultureCalendar,
                        titleFormat: this.localizeString("calendarTitleFormat", "MMMM yyyy"),
                        toolTipFormat: this.localizeString("calendarToolTipFormat", "dddd, MMMM dd, yyyy"),
                        nextTooltip: this.localizeString("calendarNextTooltip", "Next"),
                        prevTooltip: this.localizeString("calendarPrevTooltip", "Previous"),
                        showDropDownButton: true,
                        dateFormat: "d",
                        dropDownOpen: function (e, data) {
                            isInputDropdownClosing = false;
                        },
                        dropDownClose: function (e, data) {
                            isInputDropdownClosing = true;
                            $(document).one("mouseup", function () {
                                isInputDropdownClosing = false;
                            });
                        },
                        dateChanged: $.proxy(function (e, args) {
                            if (isInputDropdownClosing) {
                                dateChangedByClicking = true;
                                $(document).one("mouseup", function () {
                                    dateChangedByClicking = false;
                                });
                            }
                            var startDt = this._editEventDialog.find(".wijmo-wijev-start").wijinputdate("option", "date");
                            if (args.date < startDt) {
                                this._editEventDialog.find(".wijmo-wijev-start").wijinputdate("option", "date", args.date);
                            }
                        }, this)
                    });
                    this._editEventDialog.find(".wijmo-wijev-end-time").width(80).wijinputdate({
                        culture: this.options.culture,
                        cultureCalendar: this.options.cultureCalendar,
                        titleFormat: this.localizeString("calendarTitleFormat", "MMMM yyyy"),
                        toolTipFormat: this.localizeString("calendarToolTipFormat", "dddd, MMMM dd, yyyy"),
                        nextTooltip: this.localizeString("calendarNextTooltip", "Next"),
                        prevTooltip: this.localizeString("calendarPrevTooltip", "Previous"),
                        showDropDownButton: false,
                        dateFormat: "t"
                    });
                    this._editEventDialog.find(".wijmo-wijev-allday").wijcheckbox().change($.proxy(this._eventDialogEnsureTimePartState, this));

                    this._editEventDialog.find(".wijmo-wijev-subject,.wijmo-wijev-location,.wijmo-wijev-description").wijtextbox();

                    // save:
                    this._initEventDialogButton(this._editEventDialog.find(".wijmo-wijev-save"), $.proxy(function (e) {
                        try  {
                            var appt = this._validateAndReadApptDialogFields(this._editEventDialog);
                            if (appt.prevData) {
                                this.updateEvent(appt);
                            } else {
                                this.addEvent(appt);
                            }
                            this._editEventDialog.wijpopup("hide");
                            e.preventDefault();
                            return false;
                        } catch (ex) {
                            alert(ex);
                        }
                    }, this));

                    //////////
                    this._editEventDialog.wijpopup({
                        autoHide: true,
                        hiding: $.proxy(function (e) {
                            if (dateChangedByClicking) {
                                dateChangedByClicking = false;
                                return false;
                            }
                            if (this._colorMenu) {
                                this._colorMenu.wijpopup("hide");
                            }
                            this.element.find(".wijmo-wijev-dayview .ui-selected").removeClass("ui-selected");
                        }, this),
                        shown: $.proxy(function (e) {
                            var self = this, superPanelUnFocus = $.browser.msie ? true : false;
                            if (!this._dropDownInitialized) {
                                // fix for wijdropdown,
                                // create widget when select element is shown.
                                this._editEventDialog.find(".wijmo-wijev-calendar").wijdropdown({ "unfocus": superPanelUnFocus }).bind("change", $.proxy(self._updateEventColor, this));
                                this._updateEventColor();
                                this._editEventDialog.find(".wijmo-wijev-repeat").wijdropdown({ "unfocus": superPanelUnFocus }).bind("change", function (e) {
                                    var repeat = this.value, appt = self._editEventDialog.appt;
                                    switch (repeat) {
                                        case "none":
                                            appt.recurrenceState = null;
                                            appt.recurrencePattern = null;
                                            break;
                                        case "daily":
                                            appt.recurrenceState = "master";
                                            appt.recurrencePattern = {
                                                parentRecurrenceId: appt.id,
                                                recurrenceType: "daily"
                                            };
                                            break;
                                        case "workdays":
                                            appt.recurrenceState = "master";
                                            appt.recurrencePattern = {
                                                parentRecurrenceId: appt.id,
                                                recurrenceType: "workdays"
                                            };
                                            break;
                                        case "weekly":
                                            appt.recurrenceState = "master";
                                            appt.recurrencePattern = {
                                                parentRecurrenceId: appt.id,
                                                recurrenceType: "weekly"
                                            };
                                            break;
                                        case "monthly":
                                            appt.recurrenceState = "master";
                                            appt.recurrencePattern = {
                                                parentRecurrenceId: appt.id,
                                                recurrenceType: "monthly"
                                            };
                                            break;
                                        case "yearly":
                                            appt.recurrenceState = "master";
                                            appt.recurrencePattern = {
                                                parentRecurrenceId: appt.id,
                                                recurrenceType: "yearly"
                                            };
                                            break;
                                        case "custom":
                                            alert("show custom recurrence pattern.");
                                            break;
                                    }
                                });
                                this._dropDownInitialized = true;
                            } else {
                                // refresh wijdropdown only when select element is shown.
                                this._editEventDialog.find(".wijmo-wijev-calendar").wijdropdown("refresh");
                                this._editEventDialog.find(".wijmo-wijev-repeat").wijdropdown("refresh");
                            }
                            this._onEditEventDialogShown(this._editEventDialog, this._editEventDialog.appt);
                            this._editEventDialog.find(".wijmo-wijev-subject").focus();
                            this._updateEditEventPopupCallout();
                        }, this)
                    });
                }
            };

            wijevcal.prototype._updateEventColor = function () {
                var self = this, calEle = self._editEventDialog.find(".wijmo-wijev-calendar").data("wijmo-wijdropdown"), cal;
                cal = (calEle && calEle._value) ? self._calendarsById[calEle._value] : null;

                if (cal && cal.color) {
                    self._addColorClass(self._editEventDialog.find(".wijmo-wijev-color"), cal.color);
                } else {
                    if (self._editEventDialog.appt && self._editEventDialog.appt.color) {
                        self._addColorClass(self._editEventDialog.find(".wijmo-wijev-color"), self._editEventDialog.appt.color);
                    }
                }
            };

            wijevcal.prototype._initEventDialogButton = function (element, proxyHandler, buttonOptions) {
                if ($.mobile == null) {
                    element.button(buttonOptions).click(proxyHandler);
                } else {
                    element.addClass("ui-btn").click(proxyHandler);
                }
            };

            wijevcal.prototype._updateEditEventPopupCallout = function () {
                if (this._editEventDialog && this._editEventDialog._arrowTarget) {
                    var dlg = this._editEventDialog, target = $(dlg._arrowTarget), targetOffset = target.offset(), dlgOffset = dlg.offset(), verticalPos;
                    if (targetOffset.left === dlgOffset.left) {
                        // fix for 33872
                        dlg.removeClass("wijmo-wijev-rightangle").removeClass("wijmo-wijev-leftangle");
                    } else if (targetOffset.left < dlgOffset.left) {
                        dlg.removeClass("wijmo-wijev-rightangle").addClass("wijmo-wijev-leftangle");
                    } else {
                        dlg.removeClass("wijmo-wijev-leftangle").addClass("wijmo-wijev-rightangle");
                    }
                    verticalPos = Math.round(targetOffset.top - dlgOffset.top + target.outerHeight(true) / 2);
                    this._editEventDialog.find(".wijmo-wijev-angle").css("top", verticalPos);
                }
            };

            wijevcal.prototype._onColorButtonClick = function () {
                var self = this["self"], dlg = this["dlg"], i, o = self.options, colors = o.colors, s = "";
                if (colors && colors.length > 0) {
                    for (i = 0; i < colors.length; i += 1) {
                        s += "<span class=\"wijmo-wijev-listcolor wijmo-wijev-event-color-" + colors[i] + "\">&nbsp;</span>";
                    }
                }

                if (!self._colorMenu) {
                    self._colorMenu = $("<div class=\"wijmo-wijev-color-menu " + o.wijCSS.content + " " + o.wijCSS.cornerAll + "\"></div>");
                    dlg.append(self._colorMenu);
                    self._colorMenu.wijpopup({ autoHide: true /*qq*/  });
                } else {
                    if (self._colorMenu.parent()[0] !== dlg[0]) {
                        self._colorMenu.detach();
                        dlg.append(self._colorMenu);
                    }
                }

                self._colorMenu.html(s);
                self._colorMenu.find(".wijmo-wijev-listcolor").click($.proxy(function (e) {
                    this._addColorClass(dlg.find(".wijmo-wijev-color"), this._readColorFromClass($(e.target), "default"));
                    self._colorMenu.wijpopup("hide");
                }, self));

                self._colorMenu.wijpopup("show", {
                    of: dlg.find(".wijmo-wijev-color-button"),
                    my: "left top",
                    at: "left bottom"
                });
            };

            wijevcal.prototype._validateAndReadCalendarDialogFields = function (dlg) {
                var cal = dlg.cal || {};
                cal.name = dlg.find(".wijmo-wijev-name").val();
                cal.location = dlg.find(".wijmo-wijev-location").val();
                cal.description = dlg.find(".wijmo-wijev-description").val();
                cal.color = this._readColorFromClass(dlg.find(".wijmo-wijev-color"), cal.color || "default");
                if (!cal.name) {
                    throw "Calendar name can not be empty";
                }
                return cal;
            };
            wijevcal.prototype._validateAndReadApptDialogFields = function (dlg) {
                var appt = dlg.appt, startDate, endDate, startTime, endTime, recurrencePattern;
                startDate = _toDayDate(dlg.find(".wijmo-wijev-start").wijinputdate("option", "date"));
                endDate = _toDayDate(dlg.find(".wijmo-wijev-end").wijinputdate("option", "date"));
                startTime = dlg.find(".wijmo-wijev-start-time").wijinputdate("option", "date");
                endTime = dlg.find(".wijmo-wijev-end-time").wijinputdate("option", "date");
                var startTimeNumber = (startTime.getHours() * 60 + startTime.getMinutes()) * 60 + startTime.getSeconds();
                var endTimeNumber = (endTime.getHours() * 60 + endTime.getMinutes()) * 60 + endTime.getSeconds();

                if (startDate.getTime() === endDate.getTime() && startTimeNumber > endTimeNumber) {
                    throw this.localizeString("messageEndOccursBeforeStart", "The end date you entered occurs before the start date.");
                }
                appt.subject = dlg.find(".wijmo-wijev-subject").val();
                appt.location = dlg.find(".wijmo-wijev-location").val();
                appt.start = startDate;
                appt.end = endDate;

                if (dlg.find(".wijmo-wijev-allday").length > 0) {
                    appt.allday = dlg.find(".wijmo-wijev-allday")[0].checked;
                }
                if (!appt.allday) {
                    appt.start = new Date(appt.start.getFullYear(), appt.start.getMonth(), appt.start.getDate(), startTime.getHours(), startTime.getMinutes(), startTime.getSeconds());

                    appt.end = new Date(appt.end.getFullYear(), appt.end.getMonth(), appt.end.getDate(), endTime.getHours(), endTime.getMinutes(), endTime.getSeconds());
                } else {
                    if (appt.start.getTime() >= appt.end.getTime()) {
                        // duration can not be 0.
                        // fix for [22972] Newly created allday events are not
                        // visible for all views except list view until page refresh:
                        appt.end = this._addMinutes(appt.start, this.options.timeInterval);
                    }
                }

                appt.calendar = dlg.find(".wijmo-wijev-calendar").val();
                appt.description = dlg.find(".wijmo-wijev-description").val();
                appt.color = this._readColorFromClass(dlg.find(".wijmo-wijev-color"), appt.color);

                // update recurrence pattern fields:
                recurrencePattern = appt.recurrencePattern;
                if (recurrencePattern && appt.recurrenceState === "master") {
                    // fix for 22970:
                    recurrencePattern.startTime = appt.start;
                    recurrencePattern.endTime = appt.end;
                    recurrencePattern.patternStartDate = appt.start;
                }
                return appt;
            };

            wijevcal.prototype._bindApptToDialog = function (appt) {
                if (!appt) {
                    return;
                }
                var dlg = this._editEventDialog, cal, color;
                dlg.appt = appt;
                dlg.find(".wijmo-wijev-subject").val(appt.subject || "");
                dlg.find(".wijmo-wijev-location").val(appt.location || "");

                try  {
                    dlg.find(".wijmo-wijev-start").wijinputdate("option", "date", appt.start);
                    dlg.find(".wijmo-wijev-start-time").wijinputdate("option", "date", appt.start);
                    dlg.find(".wijmo-wijev-end").wijinputdate("option", "date", appt.end);
                    dlg.find(".wijmo-wijev-end-time").wijinputdate("option", "date", appt.end);
                } catch (ex) {
                    alert("[e0001a] wijinputdate/wijtextselection firefox error\n" + ex);
                }
                if (dlg.find(".wijmo-wijev-allday").length > 0) {
                    dlg.find(".wijmo-wijev-allday")[0].checked = appt.allday;
                }
                dlg.find(".wijmo-wijev-allday").wijcheckbox("refresh");
                this._fillCalendarsSelect(dlg.find(".wijmo-wijev-calendar"), appt.calendar);

                this._loadRepeatValue(appt, dlg.find(".wijmo-wijev-repeat"));

                dlg.find(".wijmo-wijev-description").val(appt.description || "");

                if (!appt.prevData) {
                    dlg.find(".wijmo-wijev-delete").hide();
                } else {
                    dlg.find(".wijmo-wijev-delete").show();
                }
                if (dlg.find(".wijmo-wijev-calendar").length > 0) {
                    cal = this._calendarsById[dlg.find(".wijmo-wijev-calendar")[0].value];
                }
                color = appt.color;
                if (!color && cal && cal.color) {
                    color = cal.color;
                }
                this._addColorClass(dlg.find(".wijmo-wijev-color"), color);
                this._eventDialogEnsureTimePartState();
            };
            wijevcal.prototype._onEditEventDialogShown = function (dlg, appt) {
                // fix for jquery-ui-1.9pre problem
                // (cannot call methods on wijdropdown prior to initialization)
                if (appt.recurrenceState === "exception") {
                    dlg.find(".wijmo-wijev-repeat").wijdropdown("option", "disabled", true);
                } else {
                    dlg.find(".wijmo-wijev-repeat").wijdropdown("option", "disabled", false);
                }
            };
            wijevcal.prototype._eventDialogEnsureTimePartState = function () {
                var dlg = this._editEventDialog;
                if (dlg.find(".wijmo-wijev-allday").length > 0) {
                    if (dlg.find(".wijmo-wijev-allday")[0].checked) {
                        dlg.find(".wijmo-wijev-start-time").wijinputdate("option", "disabled", true);
                        dlg.find(".wijmo-wijev-end-time").wijinputdate("option", "disabled", true);
                    } else {
                        dlg.find(".wijmo-wijev-start-time").wijinputdate("option", "disabled", false);
                        dlg.find(".wijmo-wijev-end-time").wijinputdate("option", "disabled", false);
                    }
                }
            };
            wijevcal.prototype._loadRepeatValue = function (appt, repeatSelect) {
                var repeatVal = "none";
                if (appt.recurrencePattern) {
                    switch (appt.recurrencePattern.recurrenceType) {
                        case "daily":
                            repeatVal = "daily";
                            break;
                        case "workdays":
                            repeatVal = "workdays";
                            break;
                        case "weekly":
                            repeatVal = "weekly";
                            break;
                        case "monthly":
                            repeatVal = "monthly";
                            break;
                        case "yearly":
                            repeatVal = "yearly";
                            break;
                        default:
                            repeatVal = "custom";
                            break;
                    }
                }
                repeatSelect.val(repeatVal);
            };
            wijevcal.prototype._addColorClass = function (el, color) {
                var colorClass, regexp = new RegExp("wijmo-wijev-event-color-(\\w+)\\s*");
                if (el.length > 0) {
                    colorClass = el[0].className;
                    el[0].className = colorClass.replace(regexp, "");
                    el.addClass("wijmo-wijev-event-color-" + (color || "default"));
                }
            };
            wijevcal.prototype._readColorFromClass = function (el, defaultColor) {
                var regexp = new RegExp("wijmo-wijev-event-color-(\\w+)\\s*"), match;
                if (el.length > 0) {
                    match = regexp.exec(el[0].className);
                    if (match && match.length > 1) {
                        return match[1];
                    }
                }

                return defaultColor;
            };

            wijevcal.prototype._fillCalendarsSelect = function ($select, selectedVal) {
                // Internally, defaultCalendars option is set only for extender & control, it is undefined for wijmo.
                // For wijmo, calendar dropdown is populated with "Default" item by default.
                // For extender & control, calendar dropdown is populated with localized "Default", "Home", "Work" items by default.
                var s = "", o = this.options, i, j, found, calendars = o.calendars.slice(0), defaultCalendars = typeof (o.defaultCalendars) === "undefined" ? new Array("Default") : o.defaultCalendars;
                if (defaultCalendars && defaultCalendars.length > 0) {
                    for (i = 0; i < defaultCalendars.length; i += 1) {
                        found = false;
                        for (j = 0; j < calendars.length; j += 1) {
                            if (calendars[j].name === defaultCalendars[i]) {
                                found = true;
                            }
                        }
                        if (!found) {
                            calendars.push({
                                id: defaultCalendars[i],
                                name: defaultCalendars[i]
                            });
                        }
                    }
                }
                if (calendars.length === 0) {
                    $select.html("");
                    return;
                }
                for (i = 0; i < calendars.length; i += 1) {
                    // fix the issue 149639
                    if (o.visibleCalendars.length !== 0 && $.inArray(calendars[i].name, o.visibleCalendars) == -1) {
                        continue;
                    }

                    s += "<option value=\"" + calendars[i].id + "\">" + calendars[i].name + "</option>";
                }
                $select.html(s).val(typeof (selectedVal) === "undefined" ? calendars[0].id : selectedVal);
            };

            wijevcal.prototype._bindCalendarToDialog = function (cal) {
                if (!cal) {
                    return;
                }
                var dlg = this._editCalendarDialog;
                dlg.cal = cal;
                dlg.find(".wijmo-wijev-name").val(cal.name || "");
                dlg.find(".wijmo-wijev-location").val(cal.location || "");
                dlg.find(".wijmo-wijev-description").val(cal.description || "");
                this._addColorClass(dlg.find(".wijmo-wijev-color"), cal.color);
            };

            /*--------*/
            wijevcal.prototype._onTodayClick = function () {
                if (this._isDisabled()) {
                    return;
                }
                this.goToday();
                return false;
            };

            // <--
            wijevcal.prototype._bindEvents = function () {
                var self = this, el = self.element;
                if (!self._eventsAttached) {
                    $(self.element).on("click." + self.wijevcalnamespacekey, ".wijmo-wijev-appointment", $.proxy(self._onAppointmentClick, self));

                    /*this.element.find(".wijmo-wijev-appointment")
                    .live("click." + this.wijevcalnamespacekey,
                    $.proxy(this._onAppointmentClick, this));*/
                    $(el).on("mousedown." + self.wijevcalnamespacekey, ".wijmo-wijev-dayview .wijmo-wijev-appointment", $.proxy(self._onDayViewAppointmentMouseDown, self));
                    $(el).on("mousedown." + self.wijevcalnamespacekey, ".wijmo-wijev-monthview .wijmo-wijev-appointment", $.proxy(self._onMonthViewAppointmentMouseDown, self));

                    $(el).on("click." + self.wijevcalnamespacekey, ".wijmo-wijev-dayview .wijmo-wijev-timeinterval", $.proxy(self._onDayViewTimeIntervalClick, self));
                    $(el).on("click." + self.wijevcalnamespacekey, ".wijmo-wijev-dayview .wijmo-wijev-allday-cell", $.proxy(self._onDayViewAllDayCellClick, self));

                    $(el).on("click." + self.wijevcalnamespacekey, ".wijmo-wijev-monthview .wijmo-wijev-monthcellheader", $.proxy(self._onMonthViewDayLabelClick, self));
                    $(el).on("click." + self.wijevcalnamespacekey, ".wijmo-wijev-monthview .wijmo-wijev-monthcell-showmore", $.proxy(self._onMonthViewDayLabelClick, self));
                    $(el).on("click." + self.wijevcalnamespacekey, ".wijmo-wijev-weekview .wijmo-wijev-daylabel", $.proxy(self._onMonthViewDayLabelClick, self));
                    $(el).on("click." + self.wijevcalnamespacekey, ".wijmo-wijev-customview .wijmo-wijev-daylabel", $.proxy(self._onMonthViewDayLabelClick, self));
                    $(el).on("click." + self.wijevcalnamespacekey, ".wijmo-wijev-yearview .wijmo-wijev-yearcellheader", $.proxy(self._onYearViewDayLabelClick, self));
                    $(el).on("click." + self.wijevcalnamespacekey, ".wijmo-wijev-monthview .wijmo-wijev-monthcell", $.proxy(self._onMonthViewCellClick, self));
                    $(el).on("click." + self.wijevcalnamespacekey, ".wijmo-wijev-yearview .wijmo-wijev-yearcell", $.proxy(self._onYearViewCellClick, self));

                    self._eventsAttached = true;
                }
            };

            wijevcal.prototype._unbindEvents = function () {
                if (this._eventsAttached) {
                    $(this.element).off("mousedown." + this.wijevcalnamespacekey);
                    $(this.element).off("click." + this.wijevcalnamespacekey);

                    /*
                    $(this.element).off("click." + this.wijevcalnamespacekey, ".wijmo-wijev-appointment");
                    $(this.element).off("mousedown." + this.wijevcalnamespacekey, ".wijmo-wijev-dayview .wijmo-wijev-daycolumn .wijmo-wijev-appointment");
                    $(this.element).off("click." + this.wijevcalnamespacekey, ".wijmo-wijev-dayview .wijmo-wijev-dayheadercolumn .wijmo-wijev-daylabel");
                    $(this.element).off("click." + this.wijevcalnamespacekey, ".wijmo-wijev-dayview .wijmo-wijev-timeinterval");
                    $(this.element).off("click." + this.wijevcalnamespacekey, ".wijmo-wijev-dayview .wijmo-wijev-allday-cell");
                    $(this.element).off("click." + this.wijevcalnamespacekey, ".wijmo-wijev-monthview .wijmo-wijev-monthcellheader");
                    $(this.element).off("click." + this.wijevcalnamespacekey, ".wijmo-wijev-monthview .wijmo-wijev-monthcell-showmore");
                    $(this.element).off("click." + this.wijevcalnamespacekey, ".wijmo-wijev-weekview .wijmo-wijev-daylabel");
                    $(this.element).off("click." + this.wijevcalnamespacekey, ".wijmo-wijev-monthview .wijmo-wijev-monthcell");
                    */
                    this._eventsAttached = false;
                }
            };

            /**
            * Removes the wijevcal functionality completely. This returns the element to its pre-init state.
            */
            wijevcal.prototype.destroy = function () {
                this._destroyInternal();
                $.wijmo.widget.prototype.destroy.apply(this, arguments);
            };

            wijevcal.prototype._destroyInternal = function () {
                var self = this, o = self.options;
                self.element.removeClass("wijmo-wijev wijmo-wijevcal " + o.wijCSS.widget + " " + o.wijCSS.helperReset);
                $(window).unbind("resize." + self.wijevcalnamespacekey);

                self._unBindToolsBarEvent();
                self._unbindEvents();
                self.element.empty();
                self.wijevcalnamespacekey = null;
                self._uidPref = null;
                self._isUpdating = null;
                self._resolveDayApptConflictsTimeout = null;
                self._pendingRedrawActiveView = null;
                self._listViewDetailsInit = null;
                self._dayViewDetailsInit = null;
                self._eventsAttached = null;
                self.statusbarEventsAdded = null;
                self._dataView = null;
                self._eventsView = null;
                self._eventsDataById = null;
                self._calendarsById = null;
                self._dayViewCache = null;
                self._templateDayColumn = null;
                self._templateDayHeader = null;
                self._dayViewScrollToEvent = null;
                self._maxAllDayEventCount = null;
                self._dayColumnsToResolve = null;
                self._dayColumnResolveIdx = null;
                self.logDialog = null;
                self.logPanel = null;
                self._editCalendarDialog = null;
                if (self._editEventDialog && o.ensureEventDialogOnBody) {
                    self._editEventDialog.remove();
                }
                self._editEventDialog = null;

                self._renderAgendaEventsTimeoutId = null;
                self.__targetAppt = null;
                self._isApptResize = null;
                self.__startApptH = null;
                self.__startApptY = null;
                self.__startClientY = null;
                self._apptDragResizeFlag = null;
                self._apptMovedFlag = null;
                self._movedFromTimeInervalApptElem = null;
                self.__targetApptChanged = null;
                self._defferObjs = null;
                self._setOptionCallbacks = null;
                self._chromeLoadDataDeffer = null;
                $.wijmo.wijevcal.prototype.options.eventsData = [];
            };

            // public methods
            /**
            * Exports the EventsCalendar in a graphic format.
            * The export method only works when wijmo.exporter.eventscalendarExport's reference is on the page.
            * @remarks Default exported file type is png, possible types are: jpg, png, gif, bmp, tiff, pdf.
            * @param {string|Object} exportSettings
            * 1.The name of the exported file.
            * 2.Settings of exporting, should be conformed to wijmo.exporter.IEventsCalendarExportSettings
            * @param {?string} type The type of the exported file.
            * @param {?string} serviceUrl The export service url.
            * @param {?string} pdfSettings The setting of pdf.
            * @param {?string} exportMethod with different mode,
            * 1. "Content" Sending EventsCalendar markup to the service for exporting.
            * 2. "Options" Sending EventsCalendar widget options to the service for exporting.
            * @example
            * $("#evcal").wijevcal("exportEventsCalendar", "eventscalendar", "png");
            */
            wijevcal.prototype.exportEventsCalendar = function (exportSettings, type, pdfSettings, serviceUrl, exportMethod) {
            };

            /**
            * Deletes the existing calendar from the current data source.
            * @example $("#wijevcal").wijevcal("deleteCalendar", "My calendar");
            * @param {object} o Calendar id, name or calendar object.
            * @param {function} successCallback Function that will be called when calendar is deleted.
            * @param {function} errorCallback Function that will be called when calendar can not be deleted.(e.g. due to data source or memory problems).
            */
            wijevcal.prototype.deleteCalendar = function (o, successCallback, errorCallback) {
                var i, calendars = this.options.calendars, id = o.id || o, found = false, deleteCalendarCallback, deleteCalendarErrorCallback, k, self = this;
                for (i = 0; i < calendars.length; i += 1) {
                    if (calendars[i].id === id) {
                        found = true;
                        o = calendars[i];
                        if (!this._trigger("beforeDeleteCalendar", null, { data: o })) {
                            return false;
                        }
                        delete this._calendarsById[o.id];
                        calendars.splice(i, 1);
                        break;
                    }
                }
                if (!found) {
                    for (i = 0; i < calendars.length; i += 1) {
                        if (calendars[i].name === id) {
                            found = true;
                            o = calendars[i];
                            if (!this._trigger("beforeDeleteCalendar", null, { data: o })) {
                                return false;
                            }
                            delete this._calendarsById[o.id];
                            calendars.splice(i, 1);
                            break;
                        }
                    }
                }
                if (!found) {
                    this.status("Calendar with id/name '" + id + "' not found.");
                    return false;
                }
                this.showLoadingLabel(this.localizeString("activityDeletingCalendar", "Deleting calendar..."));
                deleteCalendarCallback = function (sqlResult) {
                    self.status("Calendar '" + o.name + "' deleted.");
                    self._onCalendarsChanged();
                    self.hideLoadingLabel();
                    if (successCallback) {
                        successCallback(sqlResult);
                    }
                };

                deleteCalendarErrorCallback = function (e) {
                    self.status("Unable to delete calendar '" + o.name + "': " + e);
                    self.hideLoadingLabel();
                    if (errorCallback) {
                        errorCallback(e);
                    }
                };
                if (this.options.dataStorage.deleteCalendar) {
                    this.options.dataStorage.deleteCalendar(o, deleteCalendarCallback, deleteCalendarErrorCallback);
                } else if (this.options.webServiceUrl) {
                    try  {
                        k = this._jsonStringify(o);
                    } catch (ex) {
                        this.status("Unable to prepare calendar data for server. " + ex, "error");
                        deleteCalendarErrorCallback("Unable to prepare calendar data for server. " + ex);
                        return;
                    }
                    $.ajax({
                        url: this.options.webServiceUrl + "?clientId=" + this.element[0].id + "&command=deleteCalendar&timestamp=" + new Date().getTime(),
                        dataType: "text",
                        contentType: "application/json; charset=utf-8",
                        type: "POST",
                        data: "jsonData=" + k,
                        success: deleteCalendarCallback,
                        error: deleteCalendarErrorCallback
                    });
                } else {
                    executeSql("DELETE FROM calendars " + "WHERE id='" + o.id + "'", [], deleteCalendarCallback, deleteCalendarErrorCallback);
                }
            };

            /**
            * Adds a new calendar.
            * @example
            * $("#wijevcal").wijevcal("addCalendar", {
            * name: "My calendar",
            * location: "Home",
            * description: "Some description",
            * color: "lime"
            * });
            * @param {object} o
            * Calendar object.
            * Calendar object fields:
            *   id - String, unique calendar id, this field generated automatically;
            *   name - String, calendar name;
            *   location - String, location field;
            *   description - String, calendar description;
            *   color - String, calendar color;
            *   tag - String, this field can be used to store custom information.
            * @param {function} successCallback Function that will be called when calendar is added.
            * @param {function} errorCallback Function that will be called when calendar can not be added.(e.g. due to data source or memory problems).
            */
            wijevcal.prototype.addCalendar = function (o, successCallback, errorCallback) {
                var addCalendarCallback, k, addCalendarErrorCallback, self = this, isExist = false;
                if (!this._trigger("beforeAddCalendar", null, { data: o, prevData: o.prevData || {} })) {
                    if (o.prevData) {
                        for (k in o.prevData) {
                            if (o.prevData.hasOwnProperty(k)) {
                                o[k] = o.prevData[k];
                            }
                        }
                    }
                    return false;
                }
                if (!o.id) {
                    if (!this._dynIdCounter) {
                        this._dynIdCounter = 0;
                    }
                    this._dynIdCounter += 1;
                    o.id = "dynid" + this._dynIdCounter + "ts" + new Date().getTime();
                }

                //prevent to add an exist name calenadr
                $.each(self.options.calendars, function (i, cal) {
                    if (o.name === cal.name) {
                        isExist = true;
                        return false;
                    }
                });
                if (isExist) {
                    return;
                }

                this.showLoadingLabel(this.localizeString("activityCreatingCalendar", "Creating calendar..."));
                addCalendarCallback = function (sqlResult) {
                    if (self._handleServerError(sqlResult)) {
                        addCalendarErrorCallback(sqlResult);
                        return;
                    }
                    self._readUpdatedServerDataIfAny(sqlResult, o);
                    if (!self._calendarsById[o.id]) {
                        self.options.calendars.push(o);
                        self._calendarsById[o.id] = o;
                        self.status("Calendar '" + o.name + "' added.");
                    } else {
                        self.status("Calendar '" + o.name + "' added.");
                    }
                    o.prevData = self._cloneObj(o);
                    self._onCalendarsChanged();
                    self.hideLoadingLabel();
                    if (successCallback) {
                        successCallback(sqlResult);
                    }
                };
                addCalendarErrorCallback = function (e) {
                    self.status("Unable to add calendar '" + o.name + "': " + e);
                    self.hideLoadingLabel();
                    if (errorCallback) {
                        errorCallback(e);
                    }
                };
                if (this.options.dataStorage.addCalendar) {
                    this.options.dataStorage.addCalendar(o, addCalendarCallback, addCalendarErrorCallback);
                } else if (this.options.webServiceUrl) {
                    try  {
                        k = this._jsonStringify(o);
                    } catch (ex) {
                        this.status("Unable prepare calendar data for server." + ex, "error");
                        addCalendarErrorCallback("Unable to prepare calendar data for server." + ex);
                        return;
                    }
                    $.ajax({
                        url: this.options.webServiceUrl + "?clientId=" + this.element[0].id + "&command=addCalendar&timestamp=" + new Date().getTime(),
                        dataType: "text",
                        contentType: "application/json; charset=utf-8",
                        type: "POST",
                        data: "jsonData=" + k,
                        success: addCalendarCallback,
                        error: addCalendarErrorCallback
                    });
                } else {
                    executeSql("INSERT OR REPLACE INTO calendars " + "(id, name, location, description, color, tag) " + "VALUES(?,?,?,?,?,?);", [
                        o.id, o.name, o.location, o.description,
                        o.color, o.tag], addCalendarCallback, addCalendarErrorCallback);
                }
            };

            /**
            * Updates the existing calendar.
            * @example
            * $("#wijevcal").wijevcal("updateCalendar", {
            * name: "My calendar",
            * location: "Home",
            * description: "Some description",
            * color: "lime"
            * });
            * @param {object} o
            * Calendar object.
            * Calendar object fields:
            *   id - String, unique calendar id, this field generated automatically;
            *   name - String, calendar name;
            *    location - String, location field;
            *   description - String, calendar description;
            *   color - String, calendar color;
            *   tag - String, this field can be used to store custom information.
            * @param {function} successCallback Function that will be called when calendar is updated.
            * @param {function} errorCallback Function that will be called when calendar can not be updated.(e.g. due to data source or memory problems).
            */
            wijevcal.prototype.updateCalendar = function (o, successCallback, errorCallback) {
                var updateCalendarCallback, k, updateCalendarErrorCallback, self = this;
                if (!this._trigger("beforeUpdateCalendar", null, { data: o, prevData: o.prevData || {} })) {
                    if (o.prevData) {
                        for (k in o.prevData) {
                            if (o.prevData.hasOwnProperty(k)) {
                                o[k] = o.prevData[k];
                            }
                        }
                    }
                    return false;
                }
                if (!o.id) {
                    if (!this._dynIdCounter) {
                        this._dynIdCounter = 0;
                    }
                    this._dynIdCounter += 1;
                    o.id = "dynid" + this._dynIdCounter + "ts" + new Date().getTime();
                }
                this.showLoadingLabel(this.localizeString("activityUpdatingCalendar", "Updating calendar..."));
                updateCalendarCallback = function (sqlResult) {
                    var isExists = false, visibleCalendars = self.options.visibleCalendars;

                    if (self._handleServerError(sqlResult)) {
                        updateCalendarErrorCallback(sqlResult);
                        return;
                    }
                    self._readUpdatedServerDataIfAny(sqlResult, o);
                    if (!self._calendarsById[o.id]) {
                        //prevent to add an exist name calendar in calendars.
                        $.each(self.options.calendars, function (i, cal) {
                            if (o.name === cal.name) {
                                isExists = true;
                                return false;
                            }
                        });
                        if (!isExists) {
                            self.options.calendars.push(o);
                            self._calendarsById[o.id] = o;
                            self.status("Calendar '" + o.name + "' added.");
                        }
                    } else {
                        //when update the calendar, if this calendar is in visible calendars, we need to update the visibleCalendars array.
                        $.each(visibleCalendars, function (i, visibleCalendar) {
                            if (visibleCalendar === o.prevData.name) {
                                visibleCalendars[i] = o.name;
                                return false;
                            }
                        });
                        self.status("Calendar '" + o.name + "' updated.");
                    }
                    o.prevData = self._cloneObj(o);
                    self._onCalendarsChanged();
                    self.hideLoadingLabel();
                    if (successCallback) {
                        successCallback(sqlResult);
                    }
                };
                updateCalendarErrorCallback = function (e) {
                    self.status("Unable to update calendar '" + o.name + "': " + e);
                    self.hideLoadingLabel();
                    if (errorCallback) {
                        errorCallback(e);
                    }
                };
                if (this.options.dataStorage.updateCalendar) {
                    this.options.dataStorage.updateCalendar(o, updateCalendarCallback, updateCalendarErrorCallback);
                } else if (this.options.webServiceUrl) {
                    try  {
                        k = this._jsonStringify(o);
                    } catch (ex) {
                        this.status("Unable prepare calendar data for server. " + ex, "error");
                        updateCalendarErrorCallback("Unable to prepare calendar data for server. " + ex);
                        return;
                    }
                    $.ajax({
                        url: this.options.webServiceUrl + "?clientId=" + this.element[0].id + "&command=updateCalendar&timestamp=" + new Date().getTime(),
                        dataType: "text",
                        contentType: "application/json; charset=utf-8",
                        type: "POST",
                        data: "jsonData=" + k,
                        success: updateCalendarCallback,
                        error: updateCalendarErrorCallback
                    });
                } else {
                    executeSql("INSERT OR REPLACE INTO calendars " + "(id, name, location, description, color, tag) " + "VALUES(?,?,?,?,?,?);", [
                        o.id, o.name, o.location, o.description,
                        o.color, o.tag], updateCalendarCallback, updateCalendarErrorCallback);
                }
            };

            // for call public method in localstorage
            wijevcal.prototype._initEventData = function (o) {
                return $.extend({
                    allday: false,
                    location: null,
                    subject: null,
                    description: null,
                    color: null,
                    tag: null
                }, o);
            };

            /**
            * Adds a new event.
            * @example
            *   $("#wijevcal").wijevcal("addEvent", {
            *       start: new Date(2011, 4, 2, 0, 32),
            *       end: new Date(2011, 4, 2, 0, 50),
            *       subject: "Subject" });
            * @param {object} o
            *   Event object.
            *   Event object fields:
            *   id - String, unique event id, this field generated automatically;
            *   calendar - String, calendar id to which the event belongs;
            *   subject - String, event title;
            *   location - String, event location;
            *   start - Date, start date/time;
            *   end - Date, end date/time;
            *   description - String, event description;
            *   color - String, event color;
            *   allday - Boolean, indicates all day event
            *   tag - String, this field can be used to store custom information.
            * @param {function} successCallback Function that will be called when event is added.
            * @param {function} errorCallback Function that will be called when event can not be added.(e.g. due to data source or memory problems).
            */
            wijevcal.prototype.addEvent = function (o, successCallback, errorCallback) {
                var addEventCallback, addEventErrorCallback, k, self = this;
                if (!this._trigger("beforeAddEvent", null, { data: o, prevData: o.prevData || {} })) {
                    if (o.prevData) {
                        for (k in o.prevData) {
                            if (o.prevData.hasOwnProperty(k)) {
                                o[k] = o.prevData[k];
                            }
                        }
                    }
                    return false;
                }

                if (!o.id) {
                    if (!this._dynIdCounter) {
                        this._dynIdCounter = 0;
                    }
                    this._dynIdCounter += 1;
                    o.id = _generateGuid(); // "dynid" + this._dynIdCounter + "ts" + new Date().getTime();
                }
                if (!o.calendar) {
                    o.calendar = "Default";
                }

                this.showLoadingLabel(this.localizeString("activityCreatingEvent", "Creating event..."));

                addEventErrorCallback = function (e) {
                    self.hideLoadingLabel();
                    self.status("Unable to add event '" + o.subject + "': " + e, "error");
                    if (o.prevData) {
                        for (k in o.prevData) {
                            if (o.prevData.hasOwnProperty(k)) {
                                o[k] = o.prevData[k];
                            }
                        }
                    }
                    if (errorCallback) {
                        errorCallback(e);
                    }
                };

                addEventCallback = function (result) {
                    if (self._handleServerError(result)) {
                        addEventErrorCallback(result);
                        return;
                    }
                    self._readUpdatedServerDataIfAny(result, o);
                    if (!self._eventsDataById[o.id] || o.recurrenceState === "exception") {
                        self._storeEventWithSort(o);
                        self.status("Event '" + o.subject + "' added.");
                    } else {
                        self.status("Event '" + o.subject + "' added.");
                    }
                    o.prevData = self._cloneObj(o);
                    self._onEventsDataChanged();
                    self.hideLoadingLabel();
                    if (successCallback) {
                        successCallback(result);
                    }
                };

                if (this.options.dataStorage.addEvent) {
                    this.options.dataStorage.addEvent(o, addEventCallback, addEventErrorCallback);
                } else if (this.options.webServiceUrl) {
                    try  {
                        k = this._jsonStringify(o);
                    } catch (ex) {
                        this.status("Unable prepare event data for server. " + ex, "error");
                        addEventErrorCallback("Unable to prepare event data for server. " + ex);
                        return;
                    }
                    $.ajax({
                        url: this.options.webServiceUrl + "?clientId=" + this.element[0].id + "&command=addEvent&timestamp=" + new Date().getTime(),
                        dataType: "text",
                        contentType: "application/json; charset=utf-8",
                        type: "POST",
                        data: "jsonData=" + k,
                        success: addEventCallback,
                        error: addEventErrorCallback
                    });
                } else {
                    // init the options for call widget public method.
                    o = self._initEventData(o);

                    // if not reference the amplify and the browser is not support local storage. just added
                    if (!isAmplifyStoreUsed && !window["openDatabase"]) {
                        addEventCallback.call(this, {
                            rowsAffected: 0, rows: [o]
                        });
                        return;
                    }
                    executeSql("INSERT OR REPLACE INTO events " + "(id, calendar, subject, location, start, end," + " description, color, allday, properties, tag) " + "VALUES(?,?,?,?,?,?,?,?,?,?,?);", [
                        o.id, o.calendar, o.subject, o.location,
                        o.start.getTime(), o.end.getTime(), o.description,
                        o.color, o.allday, this._serializeProperties(o), o.tag], addEventCallback, addEventErrorCallback);
                }
            };

            wijevcal.prototype._storeEventWithSort = function (o) {
                // fix for
                // [19618] [C1EventsCalendar] Request to provide sorting behavior
                // in C1EventsCalendar with all view types:
                var apps = this.options.eventsData, i, c, calendarFound;
                this._eventsDataById[o.id] = o;
                if (!apps) {
                    return;
                }
                if (this.options.visibleCalendars.length !== 0) {
                    if (o.calendar === null) {
                        return;
                    }
                    calendarFound = $.grep(this.options.calendars, function (obj) {
                        return obj.id === o.calendar;
                    });
                    if (calendarFound.length > 0 && $.inArray(calendarFound[0].name, this.options.visibleCalendars) < 0) {
                        return;
                    }
                }
                for (i = 0, c = apps.length; i < c; i += 1) {
                    if (apps[i].start > o.start) {
                        apps.splice(i, 0, o);
                        return;
                    } else if (apps[i].start.getTime() === o.start.getTime()) {
                        if (apps[i].subject > o.subject) {
                            apps.splice(i, 0, o);
                            return;
                        }
                    }
                }
                apps.push(o);
            };

            wijevcal.prototype._readUpdatedServerDataIfAny = function (result, o) {
                var k = null, j;
                if (typeof result === "string" && result.indexOf("update:") === 0) {
                    result = result.toString().substr("update:".length);
                    try  {
                        k = this._jsonParse(result);
                    } catch (ex) {
                        this.status("Unable to read updated server data. " + ex, "warning");
                    }
                    if (k) {
                        for (j in k) {
                            if (k[j]) {
                                o[j] = k[j];
                                /*
                                if (k.hasOwnProperty(j)) {
                                o[j] = k[j];
                                }*/
                            }
                        }
                    }
                }
            };

            /**
            * Updates the existing event.
            * @example
            *   $("#wijevcal").wijevcal("updateEvent", {
            *       start: new Date(2011, 4, 2, 0, 32),
            *       end: new Date(2011, 4, 2, 0, 50),
            *       subject: "Subject" });
            * @param {object} o
            *   Event object.
            *   Event object fields:
            *       id - String, unique event id, this field generated automatically;
            *       calendar - String, calendar id to which the event belongs;
            *       subject - String, event title;
            *       location - String, event location;
            *       start - Date, start date/time;
            *       end - Date, end date/time;
            *       description - String, event description;
            *       color - String, event color;
            *       allday - Boolean, indicates all day event
            *       tag - String, this field can be used to store custom information.
            * @param {function} successCallback Function that will be called when event is updated.
            * @param {function} errorCallback Function that will be called when event can not be updated.(e.g. due to data source or memory problems).
            */
            wijevcal.prototype.updateEvent = function (o, successCallback, errorCallback) {
                var updateEventCallback, updateEventErrorCallback, k, self = this, deleteEventCallback;

                if (!this._trigger("beforeUpdateEvent", null, { data: o, prevData: o.prevData || {} })) {
                    if (o.prevData) {
                        for (k in o.prevData) {
                            if (o.prevData.hasOwnProperty(k) && k !== "id") {
                                o[k] = o.prevData[k];
                            }
                        }
                        o.prevData = this._cloneObj(o);
                    }
                    this._updateAppointmentVisual(o);
                    return false;
                }

                if (!o.calendar) {
                    o.calendar = "Default";
                }
                this.showLoadingLabel(this.localizeString("activityUpdatingEvent", "Updating event..."));

                updateEventErrorCallback = function (e) {
                    self.hideLoadingLabel();
                    self.status("Unable to update event '" + o.subject + "': " + e, "error");
                    if (o.prevData) {
                        for (k in o.prevData) {
                            if (o.prevData.hasOwnProperty(k)) {
                                o[k] = o.prevData[k];
                            }
                        }
                    }
                    self._updateAppointmentVisual(o);
                    if (errorCallback) {
                        errorCallback(e);
                    }
                };

                deleteEventCallback = function (result) {
                    var newEvent = $.extend(true, {}, o, { recurrenceState: "exception" });

                    //add the event with a new guid.
                    delete newEvent.id;
                    self.addEvent(newEvent, successCallback, errorCallback);
                };

                if (!o.id) {
                    updateEventErrorCallback("id is empty");
                    return;
                }

                if (o.recurrenceState === "occurrence") {
                    if (!this._eventsDataById[o.parentRecurrenceId]) {
                        updateEventErrorCallback("Unable to find master event for event with id:" + o.id);
                        return;
                    }
                    this.log(this._formatString("[updateEvent->addEvent] recurrenceState for event {0} changed to 'exception'.", o.id));

                    //remove the event from the master event and add a new event with the same content.
                    return this.deleteEvent(o.id, deleteEventCallback, null);
                }

                updateEventCallback = function (result) {
                    if (self._handleServerError(result)) {
                        updateEventErrorCallback(result);
                        return;
                    }
                    self._readUpdatedServerDataIfAny(result, o);
                    if (!self._eventsDataById[o.id]) {
                        self._storeEventWithSort(o);
                        self.status("Event '" + o.subject + "' added.");
                    } else {
                        $.extend(self._eventsDataById[o.id], o);

                        if (o.recurrenceState === "master") {
                            self._updateEventsData(o, successCallback, errorCallback);
                        }

                        self.status("Event '" + o.subject + "' updated.");
                    }
                    o.prevData = self._cloneObj(o);
                    self._onEventsDataChanged();

                    self.hideLoadingLabel();
                    if (successCallback) {
                        successCallback(result);
                    }
                };

                if (this.options.dataStorage.updateEvent) {
                    this.options.dataStorage.updateEvent(o, updateEventCallback, updateEventErrorCallback);
                } else if (this.options.webServiceUrl) {
                    try  {
                        k = this._jsonStringify(o);
                    } catch (ex) {
                        this.status("Unable prepare event data for server. " + ex, "error");
                        updateEventErrorCallback("Unable to prepare event data for server. " + ex);
                        return;
                    }
                    $.ajax({
                        url: this.options.webServiceUrl + "?clientId=" + this.element[0].id + "&command=updateEvent&timestamp=" + new Date().getTime(),
                        dataType: "text",
                        contentType: "application/json; charset=utf-8",
                        type: "POST",
                        data: "jsonData=" + k,
                        success: updateEventCallback,
                        error: updateEventErrorCallback
                    });
                } else {
                    // init the default value for localstorage.
                    o = self._initEventData(o);

                    // if not reference the amplify and the browser is not support local storage. just added
                    if (!isAmplifyStoreUsed && !window["openDatabase"]) {
                        updateEventCallback.call(this, {
                            rowsAffected: 0, rows: [o]
                        });
                        return;
                    }
                    executeSql("INSERT OR REPLACE INTO events " + "(id, calendar, subject, location, start, end," + " description, color, allday, properties, tag) " + "VALUES(?,?,?,?,?,?,?,?,?,?,?);", [
                        o.id, o.calendar, o.subject, o.location,
                        o.start.getTime(), o.end.getTime(), o.description,
                        o.color, o.allday, this._serializeProperties(o), o.tag], updateEventCallback, updateEventErrorCallback);
                }
            };

            //Add event into options.eventsData and remove it from recurrencePattern.
            wijevcal.prototype._updateEventsData = function (eventData, successCallback, errorCallback) {
                var i, parentData, self = this, exist = false, eventsData = self.options.eventsData, parentId = eventData.parentRecurrenceId;

                for (i = 0; i < eventsData.length; i++) {
                    if (eventsData[i].id === eventData.id) {
                        exist = true;
                        break;
                    }
                }

                if (!exist) {
                    eventsData.push(eventData);
                }

                if (parentId) {
                    parentData = self._eventsDataById[parentId];
                    if (parentData) {
                        if (!parentData.recurrencePattern.removedOccurrences) {
                            parentData.recurrencePattern.removedOccurrences = [];
                        }
                        parentData.recurrencePattern.removedOccurrences.push(eventData.id);
                        self.updateEvent(parentData, successCallback, errorCallback);
                    }
                }
            };

            wijevcal.prototype._serializeProperties = function (appt) {
                var s = "", props = {};
                props.parentRecurrenceId = appt.parentRecurrenceId;
                props.recurrenceState = appt.recurrenceState;
                props.recurrencePattern = appt.recurrencePattern;
                props.color = appt.color;
                props.allday = appt.allday;

                try  {
                    s = this._jsonStringify(props);
                } catch (ex) {
                    this.status("Unable save additional event properties. " + ex, "error");
                }
                return s;
            };

            wijevcal.prototype._deSerializeProperties = function (s, appt) {
                var props = {}, pattern;
                if (s) {
                    if (typeof s === "string") {
                        try  {
                            props = this._jsonParse(s);
                        } catch (ex) {
                            this.status("Unable to load additional event properties. " + ex, "error");
                            return;
                        }
                    } else {
                        props = s;
                    }

                    if (props.parentRecurrenceId) {
                        appt.parentRecurrenceId = props.parentRecurrenceId;
                    }
                    if (props.recurrenceState) {
                        appt.recurrenceState = props.recurrenceState;
                    }
                    if (props.recurrencePattern) {
                        appt.recurrencePattern = props.recurrencePattern;
                    }
                    if (props.color) {
                        appt.color = props.color;
                    }
                    if (props.allday) {
                        appt.allday = props.allday;
                    }
                }
                if (appt && appt.recurrencePattern) {
                    // ensure recurrencePattern date properties loaded correctly:
                    pattern = appt.recurrencePattern;
                    pattern.patternStartDate = pattern.patternStartDate ? new Date(pattern.patternStartDate) : pattern.patternStartDate;
                    pattern.startTime = pattern.startTime ? new Date(pattern.startTime) : pattern.startTime;
                    pattern.endTime = pattern.endTime ? new Date(pattern.endTime) : pattern.endTime;

                    // duration can not be 0.
                    if (pattern.startTime.getTime() >= pattern.endTime.getTime()) {
                        pattern.endTime = this._addMinutes(pattern.startTime, this.options.timeInterval);
                    }
                }
            };
            wijevcal.prototype._jsonStringify = function (o) {
                var s;
                if (window["__JSONC1"]) {
                    s = window["__JSONC1"].stringify(o);
                } else if (window["JSON"]) {
                    s = JSON.stringify(o);
                } else {
                    throw "JSON not found.";
                }
                return s;
            };
            wijevcal.prototype._jsonParse = function (s) {
                var o, reISO, reMsAjax;
                if (window["__JSONC1"]) {
                    o = window["__JSONC1"].parse(s);
                } else if (window["JSON"]) {
                    reISO = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/;
                    reMsAjax = /^\/Date\((d|-|.*)\)\/$/;
                    o = window["JSON"].parse(s, function (key, value) {
                        if (typeof value === 'string') {
                            var a = reISO.exec(value), b;
                            if (a) {
                                return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], +a[5], +a[6]));
                            }
                            a = reMsAjax.exec(value);
                            if (a) {
                                b = a[1].split(/[-,.]/);
                                return new Date(+b[0]);
                            }
                        }
                        return value;
                    });
                } else {
                    throw "JSON variable not found.";
                }
                return o;
            };

            /**
            * Retrieves the array which contains
            * the full list of Event objects in the specified time interval.
            * Note, this method will create instances of the Event
            * object for recurring events.
            * @param {Date} start The Date value which specifies
            * the start date and time of the interval.
            * @param {Date} end The Date value which specifies
            * the end date and time of the interval.
            * @returns {array} events array
            */
            wijevcal.prototype.getOccurrences = function (start, end) {
                var o = this.options, appts = o.eventsData, appt, occurrenceAppt, exceptionAppt, pattern, dayOfWeekMask, i, j, icnt, jcnt, maxOccurrenceCount = 100, patternStart, patternStartTime, patternEndTime, eventsArr = [], exceptionsArr = [], removedArr = [], occurrenceHash = {};
                if (!this._eventsDataById) {
                    this._eventsDataById = {};
                }
                if (appts) {
                    for (i = 0, icnt = appts.length; i < icnt; i += 1) {
                        appt = appts[i];

                        this._eventsDataById[appt.id] = appt;
                        if (appt.recurrenceState === "master") {
                            pattern = appt.recurrencePattern;
                            if (pattern.removedOccurrences) {
                                removedArr = removedArr.concat(pattern.removedOccurrences);
                            }

                            // populate pattern:
                            jcnt = pattern.occurrences || maxOccurrenceCount;
                            patternStart = pattern.patternStartDate || appt.start;
                            patternStartTime = pattern.startTime || appt.start;
                            patternEndTime = pattern.endTime || appt.end;
                            dayOfWeekMask = (pattern.dayOfWeekMask || "none").toLocaleLowerCase();

                            switch (pattern.recurrenceType) {
                                case "daily":
                                    for (j = 0; j < jcnt; j += 1) {
                                        occurrenceAppt = this._cloneObj(appt);
                                        occurrenceAppt.parentRecurrenceId = appt.id;
                                        occurrenceAppt.recurrenceState = "occurrence";

                                        occurrenceAppt.start = this._setTime(this._addDays(patternStart, j), patternStartTime);
                                        occurrenceAppt.end = this._setTime(occurrenceAppt.start, patternEndTime, patternStartTime);
                                        occurrenceAppt.recurrencePattern = null;
                                        if (this._testIsEventInTimeInterval(occurrenceAppt, start, end)) {
                                            occurrenceAppt.id = this._formatString("{0}_OCCR_{1:yyyy_MM_dd}", appt.id, occurrenceAppt.start);
                                            occurrenceHash[occurrenceAppt.id] = occurrenceAppt;
                                        }
                                    }
                                    break;
                                case "workdays":
                                    for (j = 0; j < jcnt; j += 1) {
                                        occurrenceAppt = this._cloneObj(appt);
                                        occurrenceAppt.parentRecurrenceId = appt.id;
                                        occurrenceAppt.recurrenceState = "occurrence";
                                        occurrenceAppt.start = this._setTime(this._addDays(patternStart, j), patternStartTime);

                                        //getDay() : Sunday is 0, Monday is 1, and so on.
                                        if (occurrenceAppt.start.getDay() === 0 || occurrenceAppt.start.getDay() === 6) {
                                            continue;
                                        }
                                        occurrenceAppt.end = this._setTime(occurrenceAppt.start, patternEndTime, patternStartTime);
                                        occurrenceAppt.recurrencePattern = null;
                                        if (this._testIsEventInTimeInterval(occurrenceAppt, start, end)) {
                                            occurrenceAppt.id = this._formatString("{0}_OCCR_{1:yyyy_MM_dd}", appt.id, occurrenceAppt.start);
                                            occurrenceHash[occurrenceAppt.id] = occurrenceAppt;
                                        }
                                    }
                                    break;
                                case "weekly":
                                    if (dayOfWeekMask !== "none") {
                                        this._getOccurrenceWeekly(appt, dayOfWeekMask, jcnt, start, end, patternStart, patternStartTime, patternEndTime, occurrenceHash);
                                    } else {
                                        for (j = 0; j < jcnt; j += 1) {
                                            occurrenceAppt = this._cloneObj(appt);
                                            occurrenceAppt.parentRecurrenceId = appt.id;
                                            occurrenceAppt.recurrenceState = "occurrence";
                                            occurrenceAppt.start = this._setTime(this._addDays(patternStart, j * 7), patternStartTime);
                                            occurrenceAppt.end = this._setTime(occurrenceAppt.start, patternEndTime, patternStartTime);
                                            occurrenceAppt.recurrencePattern = null;
                                            if (this._testIsEventInTimeInterval(occurrenceAppt, start, end)) {
                                                occurrenceAppt.id = this._formatString("{0}_OCCR_{1:yyyy_MM_dd}", appt.id, occurrenceAppt.start);
                                                occurrenceHash[occurrenceAppt.id] = occurrenceAppt;
                                            }
                                        }
                                    }
                                    break;
                                case "monthly":
                                    for (j = 0; j < jcnt; j += 1) {
                                        occurrenceAppt = this._cloneObj(appt);
                                        occurrenceAppt.parentRecurrenceId = appt.id;
                                        occurrenceAppt.recurrenceState = "occurrence";

                                        occurrenceAppt.start = this._setTime(new Date(patternStart), patternStartTime);
                                        occurrenceAppt.start.setMonth(occurrenceAppt.start.getMonth() + j);
                                        occurrenceAppt.end = this._setTime(occurrenceAppt.start, patternEndTime, patternStartTime);
                                        occurrenceAppt.recurrencePattern = null;
                                        if (this._testIsEventInTimeInterval(occurrenceAppt, start, end)) {
                                            occurrenceAppt.id = this._formatString("{0}_OCCR_{1:yyyy_MM_dd}", appt.id, occurrenceAppt.start);
                                            occurrenceHash[occurrenceAppt.id] = occurrenceAppt;
                                        }
                                    }
                                    break;
                                case "yearly":
                                    for (j = 0; j < jcnt; j += 1) {
                                        occurrenceAppt = this._cloneObj(appt);
                                        occurrenceAppt.parentRecurrenceId = appt.id;
                                        occurrenceAppt.recurrenceState = "occurrence";

                                        occurrenceAppt.start = this._setTime(new Date(patternStart), patternStartTime);
                                        occurrenceAppt.start.setYear(occurrenceAppt.start.getFullYear() + j);
                                        occurrenceAppt.end = this._setTime(occurrenceAppt.start, patternEndTime, patternStartTime);
                                        occurrenceAppt.recurrencePattern = null;
                                        if (this._testIsEventInTimeInterval(occurrenceAppt, start, end)) {
                                            occurrenceAppt.id = this._formatString("{0}_OCCR_{1:yyyy_MM_dd}", appt.id, occurrenceAppt.start);
                                            occurrenceHash[occurrenceAppt.id] = occurrenceAppt;
                                        }
                                    }
                                    break;
                                case "monthlyNth":
                                    break;
                                case "yearlyNth":
                                    break;
                            }
                        } else {
                            if (this._testIsEventInTimeInterval(appt, start, end)) {
                                if (appt.recurrenceState === "exception") {
                                    exceptionsArr.push(appt);
                                } else {
                                    if (appt.recurrenceState === "removed") {
                                        removedArr.push(appt.id);
                                        this.log("[warning] Seems we found removed event inside events storage, id:" + appt.id);
                                    } else {
                                        eventsArr.push(appt);
                                    }
                                }
                            }
                        }
                    }
                }

                for (i = 0, icnt = exceptionsArr.length; i < icnt; i += 1) {
                    exceptionAppt = exceptionsArr[i];
                    if (occurrenceHash[exceptionAppt.id]) {
                        delete occurrenceHash[exceptionAppt.id];
                    }
                    eventsArr.push(exceptionAppt);
                    this._eventsDataById[exceptionAppt.id] = exceptionAppt;
                }
                for (i = 0, icnt = removedArr.length; i < icnt; i += 1) {
                    if (occurrenceHash[removedArr[i]]) {
                        delete occurrenceHash[removedArr[i]];
                    }
                }
                for (i in occurrenceHash) {
                    occurrenceAppt = occurrenceHash[i];
                    occurrenceAppt.prevData = this._cloneObj(occurrenceAppt);
                    eventsArr.push(occurrenceAppt);
                    this._eventsDataById[occurrenceAppt.id] = occurrenceAppt;
                }

                //eventsArr.push(occurrenceAppt);
                //this._eventsDataById[occurrenceAppt.id] = occurrenceAppt;
                return eventsArr;
            };

            wijevcal.prototype._getOccurrenceWeekly = function (appt, dayOfWeekMask, jcnt, start, end, patternStart, patternStartTime, patternEndTime, occurrenceHash) {
                var self = this, j, occurrenceAppt, days = dayOfWeekMask.split(","), dayNums = [], dayOfWeek = {
                    "sunday": 0,
                    "monday": 1,
                    "tuesday": 2,
                    "wednesday": 3,
                    "thursday": 4,
                    "friday": 5,
                    "saturday": 6
                };

                $.each(days, function (index, item) {
                    switch (item) {
                        case "weekenddays":
                            dayNums.push(0, 6);
                            break;
                        case "workdays":
                            dayNums.push(1, 2, 3, 4, 5);
                            break;
                        case "everyday":
                            dayNums.push(0, 1, 2, 3, 4, 5, 6);
                            break;
                        default:
                            dayNums.push(dayOfWeek[item]);
                    }
                });

                for (j = 0; j < jcnt; j++) {
                    occurrenceAppt = self._cloneObj(appt);
                    occurrenceAppt.parentRecurrenceId = appt.id;
                    occurrenceAppt.recurrenceState = "occurrence";
                    occurrenceAppt.start = self._setTime(self._addDays(patternStart, j), patternStartTime);

                    //getDay() : Sunday is 0, Monday is 1, and so on.
                    if (dayNums.indexOf(occurrenceAppt.start.getDay()) === -1) {
                        continue;
                    }

                    occurrenceAppt.end = self._setTime(occurrenceAppt.start, patternEndTime, patternStartTime);
                    occurrenceAppt.recurrencePattern = null;

                    if (self._testIsEventInTimeInterval(occurrenceAppt, start, end)) {
                        occurrenceAppt.id = self._formatString("{0}_OCCR_{1:yyyy_MM_dd}", appt.id, occurrenceAppt.start);
                        occurrenceHash[occurrenceAppt.id] = occurrenceAppt;
                    }
                }
            };

            wijevcal.prototype._testIsEventInTimeInterval = function (appt, start, end) {
                if (!start || !end) {
                    return true;
                }
                if (appt.start < end && appt.end > start) {
                    return true;
                }
                return false;
            };

            /**
            * Deletes the event.
            * @example
            * $("#wijevcal").wijevcal("deleteEvent", eventId);
            * @param {number} id
            * Event object or event id.
            * @param {function} successCallback Function that will be called when event is deleted.
            * @param {function} errorCallback Function that will be called when event can not be deleted.(e.g. due to data source or memory problems).
            */
            wijevcal.prototype.deleteEvent = function (id, successCallback, errorCallback) {
                if (id.id) {
                    id = id.id;
                }
                var o = this._eventsDataById[id], i, appts, deleteEventCallback, deleteEventErrorCallback, self = this, k, masterAppt;
                if (!this._trigger("beforeDeleteEvent", null, { data: o })) {
                    return false;
                }
                this.showLoadingLabel(this.localizeString("activityDeletingEvent", "Deleting event..."));

                deleteEventErrorCallback = function (e) {
                    self.status("Unable to delete event '" + (o ? o.subject : "undefined") + "': " + e);
                    self.hideLoadingLabel();
                    if (errorCallback) {
                        errorCallback(e);
                    }
                };

                if (o.recurrenceState === "exception" || o.recurrenceState === "occurrence") {
                    masterAppt = this._eventsDataById[o.parentRecurrenceId];
                    if (masterAppt && masterAppt.recurrencePattern) {
                        this.log(this._formatString("[deleteEvent] removing {0} with id {1}. Updating master event with id {2}", o.recurrenceState, o.id, masterAppt.id));

                        if (!masterAppt.recurrencePattern.removedOccurrences) {
                            masterAppt.recurrencePattern.removedOccurrences = [];
                        }
                        masterAppt.recurrencePattern.removedOccurrences.push(o.id);
                        this.updateEvent(masterAppt, successCallback, errorCallback);
                        if (o.recurrenceState === "occurrence") {
                            this.log("No need to delete occurrence from store. Master event should be updated.");
                            return;
                        }
                    } else {
                        if (o.recurrenceState === "exception") {
                            //allow delete exception from events storage.
                        } else {
                            deleteEventErrorCallback("Unable to find master event with id " + o.parentRecurrenceId);
                            return false;
                        }
                    }
                }
                if (o.recurrenceState === "master") {
                    //qq: delete all exceptions from events storage, as well?
                }
                deleteEventCallback = function (result) {
                    if (self._handleServerError(result)) {
                        deleteEventErrorCallback(result);
                        return;
                    }
                    if (self._eventsDataById[o.id]) {
                        appts = self.options.eventsData;
                        if (appts) {
                            for (i = 0; i < appts.length; i = i + 1) {
                                if (appts[i].id === id) {
                                    appts.splice(i, 1);
                                }
                            }
                        }
                        delete self._eventsDataById[o.id];
                        self.status("Event '" + o.subject + "' deleted.");
                    } else {
                        self.status("Event '" + o.subject + "' deleted.");
                    }
                    o.prevData = self._cloneObj(o);
                    self._onEventsDataChanged();
                    self.hideLoadingLabel();
                    if (successCallback) {
                        successCallback(result);
                    }
                };

                if (this.options.dataStorage.deleteEvent) {
                    this.options.dataStorage.deleteEvent(o, deleteEventCallback, deleteEventErrorCallback);
                } else if (this.options.webServiceUrl) {
                    try  {
                        k = this._jsonStringify(o);
                    } catch (ex) {
                        this.status("Unable prepare event data for server. " + ex, "error");
                        deleteEventErrorCallback("Unable prepare event data for server. " + ex);
                        return;
                    }
                    $.ajax({
                        url: this.options.webServiceUrl + "?clientId=" + this.element[0].id + "&command=deleteEvent&timestamp=" + new Date().getTime(),
                        dataType: "text",
                        contentType: "application/json; charset=utf-8",
                        type: "POST",
                        data: "jsonData=" + k,
                        success: deleteEventCallback,
                        error: deleteEventErrorCallback
                    });
                } else {
                    // if not reference the amplify and the browser is not support local storage. just added
                    if (!isAmplifyStoreUsed && !window["openDatabase"]) {
                        deleteEventCallback.call(this, {
                            rowsAffected: 0, rows: [o]
                        });
                        return;
                    }
                    executeSql("DELETE FROM events WHERE id='" + id + "'", [], deleteEventCallback, deleteEventErrorCallback);
                }
            };

            /**
            * Use beginUpdate and endUpdate when making a large number of changes
            * to widget options.
            * @example
            * $("#wijevcal").wijevcal("beginUpdate");
            * $("#wijevcal").wijevcal("option", "timeInterval", 10);
            *   $("#wijevcal").wijevcal("option", "timeRulerInterval", 20);
            * $("#wijevcal").wijevcal("endUpdate");
            */
            wijevcal.prototype.beginUpdate = function () {
                this._isUpdating = true;
                this.showLoadingLabel("Updating...");
            };

            /**
            * Use beginUpdate and endUpdate when making a large number of changes
            * to widget options.
            * @example
            * $("#wijevcal").wijevcal("beginUpdate");
            * $("#wijevcal").wijevcal("option", "timeInterval", 10);
            * $("#wijevcal").wijevcal("option", "timeRulerInterval", 20);
            * $("#wijevcal").wijevcal("endUpdate");
            */
            wijevcal.prototype.endUpdate = function () {
                this._isUpdating = false;
                if (this._pendingRedrawActiveView) {
                    this._redrawActiveView();
                }
                this.hideLoadingLabel();
            };

            /**
            * Navigates to the event given by the parameter id.
            * @example
            * $("#wijevcal").wijevcal("goToEvent",
            *   "apptid_dynid1ts1320322142549");
            * @param {object} id Event object or event id.
            */
            wijevcal.prototype.goToEvent = function (id) {
                if (id.id) {
                    id = id.id;
                }
                var o = this.options, visual, superpanelEle, appt = this.findEventById(id);
                switch (o.viewType) {
                    case "day":
                    case "week":
                    case "list":
                        visual = this.element.find(".wijmo-wijev-dayview .wijmo-wijev-daycolumn ." + this._eventIdToCssClass(id));
                        if (visual.length > 0) {
                            superpanelEle = visual.parents(".wijmo-wijev-scrollpanel");
                            if (superpanelEle.length > 0) {
                                superpanelEle.wijsuperpanel("scrollChildIntoView", visual);
                            }
                        } else {
                            this._dayViewScrollToEvent = appt;
                            this.goToDate(appt.start);
                        }
                        break;
                    case "month":
                        this.goToDate(appt.start);
                        break;
                }
            };

            /**
            * Tests to see if event duration is more or equals to one day.
            * @example
            * var isAllDay = $("#wijevcal").wijevcal("isAllDayEvent",
            *   "apptid_dynid1ts1320322142549");
            * @param {object} id Event object or event id.
            * @returns {boolean} if event duration is more or equals to one day, return true
            */
            wijevcal.prototype.isAllDayEvent = function (id) {
                var appt = id;
                if (!id.id) {
                    appt = this.findEventById(id);
                }
                if (appt.allday) {
                    if ((appt.end.getTime() - appt.start.getTime()) / (1000 * 60 * 60 * 24) >= 1) {
                        return true;
                    }
                    return true;
                }
                return false;
            };

            /**
            * Navigates to the date given by parameter dt.
            * @example
            * $("#wijevcal").wijevcal("goToDate", new Date());
            * @param {Date} dt Javascript date.
            */
            wijevcal.prototype.goToDate = function (dt) {
                dt = _toDayDate(dt);
                var self = this, o = self.options, weekDay = dt.getDay(), i, daysCor, dUTC, sdUTC, sd0, selectedDates = o.selectedDates, viewIndex = self._getCurrentViewIndex(), viewType, dayCountInWeek, isCustomView = self._isCustomView(viewIndex);
                if (selectedDates && selectedDates.length > 0) {
                    if (this._isContainsDayDate(selectedDates, dt)) {
                        return;
                    } else {
                        // fixed 35356 by Daniel.He, caused by "Pacific Daylight Time" 1h offset.
                        // convert to UTC time dUTC, sdUTC,
                        sd0 = selectedDates[0];
                        dUTC = Date.UTC(dt.getFullYear(), dt.getMonth(), dt.getDate());
                        sdUTC = Date.UTC(sd0.getFullYear(), sd0.getMonth(), sd0.getDate());
                        daysCor = (dUTC - sdUTC) / 86400000;
                        if (isCustomView) {
                            viewType = o.views[viewIndex].unit;
                        } else {
                            viewType = o.viewType;
                        }
                        if (viewType.toLowerCase() === "week") {
                            dayCountInWeek = (isCustomView ? o.views[viewIndex].count : 1) * 7;
                            daysCor = Math.floor(daysCor / dayCountInWeek) * dayCountInWeek;
                        }
                        for (i = 0; i < selectedDates.length; i += 1) {
                            selectedDates[i] = this._addDays(selectedDates[i], daysCor);
                        }
                        this._onSelectedDatesChanged();
                    }
                } else {
                    o.selectedDates = [dt];
                    this._onSelectedDatesChanged();
                }
            };

            /**
            * Scrolls view to time given by parameter time.
            * @example
            * $("#wijevcal").wijevcal("goToTime", new Date());
            * @param {Date} time Javascript date.
            */
            wijevcal.prototype.goToTime = function (time) {
                var firstTimeInervalCell = this.element.find(".wijmo-wijev-daycolumn .wijmo-wijev-timeinterval:first-child"), lastTimeInervalCell = this.element.find(".wijmo-wijev-daycolumn .wijmo-wijev-timeinterval:last"), ys = firstTimeInervalCell.position().top, ye = lastTimeInervalCell.position().top + lastTimeInervalCell.height(), yt, tt, te;
                te = 24 * 60 * 60;
                tt = time.getHours() * 60 * 60 + time.getMinutes() * 60;

                yt = (ye - ys) * tt / te + ys;
                this.element.find(".wijmo-wijev-scrollpanel").wijsuperpanel("vScrollTo", yt);
            };

            /**
            * Navigates to today's date.
            * @example
            * $("#wijevcal").wijevcal("goToday");
            */
            wijevcal.prototype.goToday = function () {
                this.goToDate(new Date());
            };

            wijevcal.prototype._navigatingDatePager = function (goLeft) {
                var self = this, offset = goLeft ? -1 : 1, o = self.options, viewType, timeCnt = 1, view, selectedDate = o.selectedDates[0], viewIndex = self._getCurrentViewIndex();
                if (self._isCustomView(viewIndex)) {
                    view = o.views[viewIndex];
                    viewType = view.unit;
                    timeCnt = view.count;
                } else {
                    viewType = o.viewType;
                }
                switch (viewType) {
                    case "week":
                        offset *= 7;
                    case "list":
                    case "day":
                        self.goToDate(self._addDays(selectedDate, offset * timeCnt));
                        break;
                    case "month":
                        self.goToDate(self._addMonths(selectedDate, offset * timeCnt));
                        break;
                    case "year":
                        self.goToDate(self._addYears(selectedDate, offset * timeCnt));
                        break;
                }
            };

            /**
            * Navigates to the previous date.
            * @example
            * $("#wijevcal").wijevcal("goLeft");
            */
            wijevcal.prototype.goLeft = function () {
                this._navigatingDatePager(true);
            };

            /**
            * Navigates to the next date.
            * @example
            * $("#wijevcal").wijevcal("goRight");
            */
            wijevcal.prototype.goRight = function () {
                this._navigatingDatePager(false);
            };

            /**
            * Invalidates the entire surface of the control
            * and causes the control to be redrawn.
            */
            wijevcal.prototype.refresh = function () {
                this.invalidate();
            };

            /**
            * Invalidates the entire surface of the control
            * and causes the control to be redrawn.
            */
            wijevcal.prototype.invalidate = function () {
                var self = this, o = self.options, viewType = self._getCurrentViewType();
                switch (viewType) {
                    case "list":
                    case "day":
                    case "week":
                        this._invalidateDayView();
                        break;
                    case "month":
                        this._invalidateMonthView();
                        break;
                    case "year":
                        this._invalidateYearView();
                        break;
                    default:
                        break;
                }
            };

            //Get current selected view .
            wijevcal.prototype._getCurrentViewType = function () {
                var self = this, o = self.options, viewIndex = self._getCurrentViewIndex(), view = o.views[viewIndex], viewType = $.isPlainObject(view) ? self._getCustomViewUnit() : view;
                return viewType.toLowerCase();
            };

            /**
            * Call this method in order to display built-in "edit calendar" dialog box.
            * @example
            * Display dialog for a new calendar:
            * $("#wijevcal").wijevcal("showEditCalendarDialog", null);
            * @param {object} calendar
            * Calendar object or calendar name.
            * Calendar object fields:
            *   id - String, unique calendar id, this field generated automatically;
            *   name - String, calendar name;
            *   location - String, location field;
            *   description - String, calendar description;
            *   color - String, calendar color;
            *   tag - String, this field can be used to store custom information.
            */
            wijevcal.prototype.showEditCalendarDialog = function (calendar) {
                var o = this.options, calendars = o.calendars, i;
                if (!calendar) {
                    calendar = { name: "", description: "", location: "", color: "" };
                } else if (!calendar.name) {
                    for (i = 0; i < calendars.length; i += 1) {
                        if (calendars[i].name === calendar) {
                            calendar = calendars[i];
                            break;
                        }
                    }
                }
                this._ensureEditCalendarDialogCreated();
                this._bindCalendarToDialog(calendar);
                this._editCalendarDialog.wijdialog("open");
            };

            /**
            * Call this method in order to display built-in "edit event" dialog box.
            * @example
            * Display dialog for a new event:
            * $("#wijevcal").wijevcal("showEditEventDialog", null);
            * @param {object} calendar
            * Event object.
            * Event object fields:
            *   id - String, unique event id, this field generated automatically;
            *   calendar - String, calendar id to which the event belongs;
            *   subject - String, event title;
            *   location - String, event location;
            *   start - Date, start date/time;
            *   end - Date, end date/time;
            *   description - String, event description;
            *   color - String, event color;
            *   allday - Boolean, indicates all day event
            *   tag - String, this field can be used to store custom information.
            * @param {object} offsetElement
            * Optional.
            * DOM element which will be used to calculate dialog position.
            */
            wijevcal.prototype.showEditEventDialog = function (appt, offsetElement, e) {
                var o = this.options, masterAppt, parentColumn, startdt, popupWijdget, position, isMonthCell, targetCell = offsetElement ? $(offsetElement) : (e ? $(e.target) : null);

                this._ensureEditEventDialogCreated();
                this.element.find(".wijmo-wijev-dayview .ui-selected").removeClass("ui-selected");

                if (targetCell && targetCell.hasClass("wijmo-wijev-daylabel")) {
                    targetCell = targetCell.parent(".wijmo-wijev-allday-cell");
                }
                if (!appt) {
                    appt = { subject: this.localizeString("textNewEvent", "New event") };
                    appt.isNewEvent = true;
                    if (targetCell && targetCell.length > 0) {
                        this._editEventDialog._arrowTarget = targetCell;
                        targetCell.addClass("ui-selected");

                        parentColumn = targetCell.parent(".wijmo-wijev-daycolumn");
                        if (parentColumn.length < 1) {
                            parentColumn = targetCell.parent(".wijmo-wijev-dayheadercolumn");
                        }
                        parentColumn = parentColumn[0];

                        //wijmo-wijev-allday-cell
                        if (targetCell.hasClass("wijmo-wijev-allday-cell")) {
                            appt.allday = true;
                        } else if (targetCell.hasClass("wijmo-wijev-monthcellcontainer")) {
                            parentColumn = targetCell[0];
                            appt.allday = true;
                        } else if (targetCell.hasClass("wijmo-wijev-yearcellcontainer")) {
                            parentColumn = targetCell[0];
                            appt.allday = false;
                            isMonthCell = true;
                        } else {
                            appt.allday = false;
                        }

                        if (parentColumn) {
                            startdt = this._parseDateFromClass(parentColumn.className, appt.allday ? null : targetCell[0].className);

                            appt.start = startdt;
                            if (appt.allday) {
                                appt.end = this._addMinutes(appt.start, 60 * 24);
                            } else {
                                appt.end = this._addMinutes(appt.start, o.timeInterval);
                            }
                            if (isMonthCell) {
                                appt.end = this._addDays(appt.start, (new Date(appt.start.getFullYear(), appt.start.getMonth() + 1, 0)).getDate() - 1);
                            }
                        }
                    } else {
                        appt.start = new Date(o.selectedDates[0]);
                        appt.end = this._addMinutes(appt.start, o.timeInterval);
                    }
                } else {
                    this._editEventDialog._arrowTarget = targetCell;
                    if (!appt.prevData) {
                        appt.prevData = this._cloneObj(o);
                    }
                    if (appt.recurrenceState === "occurrence") {
                        masterAppt = this._eventsDataById[appt.parentRecurrenceId];
                        if (window.confirm(this._formatString(this.localizeString("promptOpenOccurrenceFormat", "{2}  is recurring event. Do you want to open only this occurrence?"), appt.start, appt.end, appt.subject, appt.location))) {
                            // edit exception: set inside addEvent/updateEvent method
                            //appt.recurrenceState = "exception";
                        } else {
                            // edit master event:
                            appt = masterAppt;
                        }
                    }
                    /*
                    if (appt.recurrenceState === "exception") {
                    //alert("Exception found:" + appt.id);
                    }*/
                }
                if (this._trigger("beforeEditEventDialogShow", null, { data: appt, targetCell: targetCell })) {
                    position = {
                        of: targetCell,
                        my: "left center",
                        at: "right center",
                        offset: (targetCell && e ? Math.round(e.offsetX - targetCell.width()) : 10) + " 0",
                        collision: "fit"
                    };
                    this._bindApptToDialog(appt);
                    this._editEventDialog.wijpopup("show", position);

                    popupWijdget = this._editEventDialog.data("wijmo-wijpopup");
                    if (popupWijdget) {
                        popupWijdget._setPosition(position);
                    }
                }
            };

            /** Private methods */
            wijevcal.prototype._getCustomViewUnit = function () {
                var o = this.options, timeUnit, viewIndex = this._getCurrentViewIndex();
                if (!o.views[viewIndex].unit) {
                    return "day";
                }
                timeUnit = o.views[viewIndex].unit.toLowerCase();
                if ($.inArray(timeUnit, ["day", "week", "month", "year"])) {
                    return timeUnit;
                } else {
                    return "day";
                }
            };

            wijevcal.prototype._renderViewByViewType = function (viewType) {
                var self = this, o = self.options;
                switch (viewType) {
                    case "day":
                    case "week":
                    case "list":
                        self.element.find(".wijmo-wijev-view.wijmo-wijev-dayview").show();
                        self._renderDayView();
                        break;
                    case "month":
                        self.element.find(".wijmo-wijev-view.wijmo-wijev-monthview").show();
                        self._renderMonthView();
                        break;
                    case "year":
                        self.element.find(".wijmo-wijev-view.wijmo-wijev-yearview").show();
                        self._renderYearView();
                        break;
                    default:
                        break;
                }
            };

            wijevcal.prototype._getCurrentViewIndex = function () {
                var self = this, o = self.options, viewIndex = 0;
                $.each(o.views, function (index, view) {
                    if ($.isPlainObject(view)) {
                        if (view.name.toLowerCase() === o.viewType.toLowerCase()) {
                            viewIndex = index;
                            return false;
                        }
                    } else {
                        if (view.toLowerCase() === o.viewType.toLowerCase()) {
                            viewIndex = index;
                            return false;
                        }
                    }
                });
                return viewIndex;
            };

            // render views
            wijevcal.prototype._renderActiveView = function () {
                var self = this, o = self.options, toolsBar = self.element.find(".wijmo-wijev-headerbar .wijmo-wijev-tools"), timeUnit, viewType, viewIndex;
                self.element.find(".wijmo-wijev-view").hide();
                self.element.find(".wijmo-wijev-viewdetails").hide();
                viewIndex = self._getCurrentViewIndex();
                if (self._isCustomView(viewIndex)) {
                    viewType = o.views[viewIndex].unit;
                    o.viewType = o.views[viewIndex].name;
                } else {
                    viewType = o.views[viewIndex];
                    o.viewType = viewType;
                }
                self.element.find(".wijmo-wijev-" + o.viewType.toLowerCase() + "-details").show();

                self._renderViewByViewType(viewType);
                toolsBar.find("input")[viewIndex]["checked"] = true;
                if ($().buttonset) {
                    toolsBar.buttonset("refresh");
                } else if ($().checkboxradio) {
                    toolsBar.find(":radio").checkboxradio("refresh");
                }
            };

            wijevcal.prototype._redrawActiveView = function () {
                if (this._isUpdating) {
                    this._pendingRedrawActiveView = true;
                    return;
                }
                switch (this.options.viewType.toLowerCase()) {
                    case "day":
                    case "week":

                    case "list":
                        this._clearDayViewCache();
                        this._templateDayColumn = null;
                        break;
                }
                this._renderActiveView();
            };

            /* DAY(S)/WEEK view*/
            wijevcal.prototype._getDayColumnDates = function (updateSelectedDates) {
                var self = this, o = self.options, columnDates = o.selectedDates, startDt, dt, i, viewIndex = self._getCurrentViewIndex(), isCustomView = self._isCustomView(viewIndex), unitCount = o.views[viewIndex].count || 1;
                if (!columnDates) {
                    columnDates = [new Date()];
                }
                if (o.viewType.toLowerCase() === "week" || (isCustomView && self._getCustomViewUnit() === "week")) {
                    startDt = o.selectedDate || columnDates[0];
                    i = o.firstDayOfWeek - startDt.getDay();
                    if (Math.abs(i) > 6) {
                        i = startDt.getDay() - o.firstDayOfWeek;
                    }
                    startDt = self._addDays(startDt, i);
                    columnDates = [];
                    for (i = 0; i < 7 * (unitCount); i += 1) {
                        dt = self._addDays(startDt, i);
                        columnDates.push(dt);
                    }
                } else if (isCustomView && self._getCustomViewUnit() === "day") {
                    startDt = o.selectedDate || columnDates[0];
                    columnDates = [];
                    for (i = 0; i < unitCount; i += 1) {
                        dt = self._addDays(startDt, i);
                        columnDates.push(dt);
                    }
                }
                if (updateSelectedDates) {
                    o.selectedDates = columnDates;
                }
                return columnDates;
            };

            wijevcal.prototype._scrolling = function (e, data) {
                var headercontainer = this.element.find(".wijmo-wijev-headercontainer");
                headercontainer.css({ position: "relative", left: data.afterPosition.left });
            };

            wijevcal.prototype._resetHeaderContainer = function () {
                var headercontainer = this.element.find(".wijmo-wijev-headercontainer");
                headercontainer.css("left", 0);
            };

            wijevcal.prototype._renderDayView = function () {
                var self = this, o = self.options, curMinute = 0, lastMinute = 24 * 60, s, cellClass, timeRulerCellClass, columnDates = self._getDayColumnDates(true), i, curDayHeader, curDayColumn, curDayDate, todayDate = new Date(), columnCount, skipNextBorder = false, dayview = self.element.find(".wijmo-wijev-dayview"), scrollPanel, headercontainer, scrollcontent, timeruler, scrollBarVisibility, maxTimeCount = 7, isCustomView = self._isCustomView(), customCount, curTimeRulerInterval = 0, isOddRow, viewIndex = self._getCurrentViewIndex();
                if (isCustomView) {
                    customCount = o.views[viewIndex].count || 1;
                    switch (self._getCustomViewUnit()) {
                        case "day":
                            scrollBarVisibility = customCount > maxTimeCount;
                            break;
                        case "week":
                            scrollBarVisibility = customCount * 7 > maxTimeCount;
                            break;
                    }
                }
                if (dayview.length === 0) {
                    dayview = $("<div class=\"wijmo-wijev-view wijmo-wijev-dayview " + o.wijCSS.content + "\">" + "<h3 class=\"wijmo-wijev-header-title\">title" + "</h3>" + "<div class=\"wijmo-wijev-dayview-inner\">" + "<div class=\"wijmo-wijev-headercontainer\">" + "<div class=\"wijmo-wijev-sizer\">" + "<div class=\"wijmo-wijev-gmtlabel\">" + self.localizeString("labelAllDay", "all-day") + "</div>" + "</div>" + "</div>" + "<div class=\"wijmo-wijev-scrollpanel\">" + "<div class=\"wijmo-wijev-scrollcontent\">" + "<div class=\"wijmo-wijev-timeruler\">" + "<div class=\"wijmo-wijev-currenttime-indicator\">" + "<div class=\"wijmo-wijev-currenttime-indicator-arrow " + o.wijCSS.stateError + "\"></div>" + "<div class=\"wijmo-wijev-currenttime-indicator-line " + o.wijCSS.stateError + "\"></div>" + "</div>" + "</div>" + "</div>" + "</div>" + "</div>" + "</div>");

                    dayview.appendTo(self.element.find(".wijmo-wijev-view-container"));
                    scrollPanel = self.element.find(".wijmo-wijev-scrollpanel").wijsuperpanel({
                        hScroller: { scrollBarVisibility: scrollBarVisibility ? "visible" : "hidden" },
                        animationOptions: { disabled: true }
                    });
                } else {
                    scrollPanel = self.element.find(".wijmo-wijev-scrollpanel");
                }
                scrollPanel.wijsuperpanel("option", "hScroller", { scrollBarVisibility: scrollBarVisibility ? "visible" : "hidden" });
                scrollPanel.wijsuperpanel("option", "scrolled", scrollBarVisibility ? $.proxy(self._scrolling, self) : null);
                dayview.removeClass("wijmo-wijev-weekview wijmo-wijev-listview");

                dayview.addClass("wijmo-wijev-" + (isCustomView ? "custom" : o.viewType.toLowerCase()) + "view");

                headercontainer = self.element.find(".wijmo-wijev-headercontainer");
                scrollcontent = self.element.find(".wijmo-wijev-scrollcontent");
                timeruler = scrollcontent.find(".wijmo-wijev-timeruler");

                //Fix the issue #114538.
                if (isCustomView) {
                    dayview.find(".wijmo-wijev-gmtlabel").css("opacity", 0.7);
                } else {
                    dayview.find(".wijmo-wijev-gmtlabel").removeAttr("style");
                }

                if (!self._templateDayColumn) {
                    timeruler.find(".wijmo-wijev-timerulerinterval").remove();

                    s = "<div class=\"wijmo-wijev-daycolumn\">";
                    isOddRow = true;
                    while (curMinute < lastMinute) {
                        cellClass = "wijmo-wijev-timeinterval " + o.wijCSS.content + " wijmo-wijev-minute-" + curMinute;
                        if (isOddRow) {
                            cellClass += " wijmo-wijev-oddrow";
                        }
                        isOddRow = !isOddRow;
                        timeRulerCellClass = "wijmo-wijev-timerulerinterval " + o.wijCSS.content + " wijmo-wijev-minute-" + curMinute;
                        s += "<div class=\"" + cellClass + "\" style=\"height: " + o.timeIntervalHeight + "px\"></div>";
                        curMinute += o.timeInterval;
                        curTimeRulerInterval += o.timeInterval;
                        if (curTimeRulerInterval >= o.timeRulerInterval) {
                            cellClass += " wijmo-wijev-timeinterval-hourstart";
                            timeRulerCellClass += " wijmo-wijev-timerulerinterval-hourstart";
                            timeruler.append($("<div class=\"" + timeRulerCellClass + "\" style=\"height:" + (curTimeRulerInterval / o.timeInterval) * o.timeIntervalHeight + "px\">" + self._formatString(o.timeRulerFormat, new Date(todayDate.getFullYear(), todayDate.getMonth(), todayDate.getDate(), 0, (curMinute - curTimeRulerInterval))) + "</div>"));
                            curTimeRulerInterval = 0;
                        }
                    }
                    s += "</div>";
                    self._templateDayColumn = $(s);
                    self._templateDayHeader = $("<div class=\"wijmo-wijev-dayheadercolumn " + o.wijCSS.content + "\">" + "<div class=\"wijmo-wijev-allday-cell " + o.wijCSS.content + "\">" + "<div class=\"wijmo-wijev-daylabel\">3 Monday</div>" + "</div>" + "</div>");
                }
                headercontainer.find(".wijmo-wijev-dayheadercolumn").remove();
                scrollcontent.find(".wijmo-wijev-daycolumn").remove();
                for (i = 0, columnCount = columnDates.length; i < columnCount; i = i + 1) {
                    curDayDate = columnDates[i];
                    curDayHeader = self._getCachedDayHeader(curDayDate);
                    curDayColumn = self._getCachedDayColumn(curDayDate);
                    if (!curDayHeader) {
                        curDayHeader = self._templateDayHeader.clone(true);
                        curDayColumn = self._templateDayColumn.clone(true);
                        curDayHeader.addClass(self._dayDateToCssClass(curDayDate));
                        curDayHeader.find(".wijmo-wijev-daylabel").html(self._formatDayHeaderDate(curDayDate));
                        curDayColumn.addClass(self._dayDateToCssClass(curDayDate));
                        if (skipNextBorder) {
                            skipNextBorder = false;
                        } else {
                            curDayColumn.addClass("wijmo-wijev-leftborder");
                            curDayHeader.addClass("wijmo-wijev-leftborder");
                        }

                        if (self._compareDayDates(curDayDate, todayDate) === 0) {
                            //curDayColumn.addClass("wijmo-wijev-today ui-state-highlight");
                            curDayColumn.addClass("wijmo-wijev-today " + o.wijCSS.stateHighlight);
                            curDayColumn.addClass("wijmo-wijev-leftborder");
                            curDayColumn.addClass("wijmo-wijev-rightborder");
                            curDayHeader.addClass("wijmo-wijev-today").find(".wijmo-wijev-allday-cell").addClass(o.wijCSS.stateHighlight);
                            curDayHeader.addClass("wijmo-wijev-leftborder");
                            curDayHeader.addClass("wijmo-wijev-rightborder");
                            skipNextBorder = true;
                        }
                        if (i === columnCount - 1) {
                            curDayColumn.addClass("wijmo-wijev-rightborder");
                            curDayHeader.addClass("wijmo-wijev-rightborder");
                        }
                    } else {
                        curDayHeader = $(curDayHeader);
                        curDayHeader.find(".wijmo-wijev-daylabel").html(self._formatDayHeaderDate(curDayDate));
                    }

                    headercontainer.append(curDayHeader);
                    scrollcontent.append(curDayColumn);
                }
                self._invalidateDayView();
                self._renderDayViewAppointments();
            };

            // view cache>>
            wijevcal.prototype._getCachedDayHeader = function (dt) {
                var h = null;
                if (this._dayViewCache) {
                    if (this._dayViewCache[dt]) {
                        h = this._dayViewCache[dt].h;
                    }
                }
                return h;
            };
            wijevcal.prototype._getCachedDayColumn = function (dt) {
                var c = null;
                if (this._dayViewCache) {
                    if (this._dayViewCache[dt]) {
                        c = this._dayViewCache[dt].c;
                    }
                }
                return c;
            };
            wijevcal.prototype._storeDayCache = function (dt, h, c) {
                if (!this._dayViewCache) {
                    this._dayViewCache = {};
                }
                this._dayViewCache[dt] = { "h": h, "c": c };
            };
            wijevcal.prototype._clearViewsCache = function () {
                this._clearDayViewCache();
                this._clearListViewCache();
            };
            wijevcal.prototype._clearDayViewCache = function () {
                this._dayViewCache = {};
            };
            wijevcal.prototype._clearListViewCache = function () {
                var $agendaList = this.element.find(".wijmo-wijev-list-details .wijmo-wijev-agenda-container .wijmo-wijsuperpanel-templateouterwrapper");

                // fixed the issue in IE10.
                if (!$agendaList[0]) {
                    $agendaList = this.element.find(".wijmo-wijev-list-details .wijmo-wijev-agenda-container .wijmo-wijsuperpanel-contentwrapper-touch");
                }
                $agendaList.data("wijevcal_agenda_initialized", false);
                $agendaList.data("wijevcal_agenda_loadedeventscount", 0);
            };

            //<< end of views cache
            wijevcal.prototype._invalidateDayView = function (scrollHeightOnly) {
                var self = this, o = self.options, headercontainer = self.element.find(".wijmo-wijev-headercontainer"), scrollcontent = self.element.find(".wijmo-wijev-scrollcontent"), timeruler = scrollcontent.find(".wijmo-wijev-timeruler"), dayHeaderColumns = headercontainer.find(".wijmo-wijev-dayheadercolumn"), dayColumns = scrollcontent.find(".wijmo-wijev-daycolumn"), isCustomView = self._isCustomView(), viewType = isCustomView ? "custom" : o.viewType.toLowerCase(), headerTitleH, title, viewWidth, allDayCellH, allDayApptH, allDayLabelH, maxAllDayApptCount, curAllDayApptCount, timeRulerOuterWidth = timeruler.outerWidth(), i, dayscontainerWidth, dayscontainerHeight, columnOuterWidth, indicatorLine = timeruler.find(".wijmo-wijev-currenttime-indicator"), scrollpanel;
                self._updateHeaderTitleText(); // ensure header title visibility
                title = self.element.find(".wijmo-wijev-view.wijmo-wijev-" + viewType + "view .wijmo-wijev-header-title");
                headerTitleH = title.is(":visible") ? title.outerHeight(true) : 0;
                self._invalidateView();

                if (!self._maxAllDayEventCount) {
                    self._maxAllDayEventCount = 0;
                }
                allDayApptH = headercontainer.find(".wijmo-wijev-dayheadercolumn .wijmo-wijev-appointment").outerHeight(true);
                if (!allDayApptH) {
                    allDayApptH = 17;
                }

                allDayLabelH = headercontainer.find(".wijmo-wijev-daylabel").outerHeight(true);

                maxAllDayApptCount = 0;
                for (i = 0; i < dayHeaderColumns.length; i += 1) {
                    curAllDayApptCount = $(dayHeaderColumns[i]).find(".wijmo-wijev-allday-cell .wijmo-wijev-appointment").length;
                    if (curAllDayApptCount > maxAllDayApptCount) {
                        maxAllDayApptCount = curAllDayApptCount;
                    }
                }
                allDayCellH = allDayApptH * maxAllDayApptCount + allDayLabelH + allDayApptH;

                headercontainer.outerHeight(allDayCellH + Math.round(allDayApptH / 2));

                headercontainer.find(".wijmo-wijev-allday-cell").outerHeight(allDayCellH);

                viewWidth = self.element.find(".wijmo-wijev-view").width(); // Getting the viewWidth shall not contain the padding of the view container.
                dayscontainerWidth = viewWidth - timeRulerOuterWidth;
                dayscontainerWidth = dayscontainerWidth - 18; //vertical scrollbar width
                dayscontainerHeight = self.element.find(".wijmo-wijev-view").innerHeight() - headercontainer.outerHeight(true) - headerTitleH;
                columnOuterWidth = Math.floor(dayscontainerWidth / (dayColumns.length > 7 ? 7 : dayColumns.length));

                if (isCustomView && dayColumns.length > 7) {
                    dayscontainerWidth = columnOuterWidth * dayColumns.length;
                    headercontainer.outerWidth(dayscontainerWidth + timeRulerOuterWidth + 18);
                    indicatorLine.outerWidth(dayscontainerWidth + timeRulerOuterWidth);
                } else {
                    headercontainer.outerWidth(viewWidth);
                    indicatorLine.outerWidth("100%");
                }
                scrollcontent.width(dayscontainerWidth + timeRulerOuterWidth);
                dayHeaderColumns.outerWidth(columnOuterWidth);
                dayColumns.outerWidth(columnOuterWidth);
                self._invalidateCurrentTimeIndicator();
                scrollpanel = self.element.find(".wijmo-wijev-scrollpanel");
                scrollpanel.outerWidth(viewWidth);
                scrollpanel.outerHeight(dayscontainerHeight);
                self._refreshSuperPanel(scrollpanel);
                switch (viewType) {
                    case "day":
                        self._updateDayViewDetails();
                        break;
                    case "list":
                        self._updateListViewDetails();
                        break;
                }
            };

            wijevcal.prototype._refreshSuperPanel = function (panel) {
                if (!($.support.isTouchEnabled && $.support.isTouchEnabled()) && this._isIE8()) {
                    panel.wijsuperpanel("paintPanel", true);
                } else {
                    panel.wijsuperpanel("refresh");
                }
            };

            /* view details */
            wijevcal.prototype._updateDayViewDetails = function () {
                var o = this.options, selectedDate = o.selectedDate, leftPane = this.element.find(".wijmo-wijev-leftpane"), agendaContainer = leftPane.find(".wijmo-wijev-agenda-container");
                if (!this._dayViewDetailsInit) {
                    this._dayViewDetailsInit = true;
                    this.element.find(".wijmo-wijev-day-details .wijmo-wijev-daycalendar").wijcalendar($.extend(true, {
                        culture: o.culture,
                        cultureCalendar: o.cultureCalendar,
                        titleFormat: this.localizeString("calendarTitleFormat", "MMMM yyyy"),
                        toolTipFormat: this.localizeString("calendarToolTipFormat", "dddd, MMMM dd, yyyy"),
                        showTitle: false,
                        showOtherMonthDays: false,
                        showWeekNumbers: false,
                        selectionMode: { day: true, days: false },
                        selectedDatesChanged: $.proxy(function (e, args) {
                            if (args.dates && !this._isDisabled()) {
                                this.goToDate(args.dates[0]);
                            }
                        }, this),
                        nextTooltip: this.localizeString("calendarNextTooltip", "Next"),
                        prevTooltip: this.localizeString("calendarPrevTooltip", "Previous")
                    }, o.calendar));
                    this.element.find(".wijmo-wijev-day-details .wijmo-wijev-agenda-container").wijsuperpanel();
                }

                this.element.find(".wijmo-wijev-day-details .wijmo-wijev-daycalendar").wijcalendar("option", "displayDate", selectedDate).wijcalendar("unSelectAll").wijcalendar("selectDate", selectedDate);
                this.element.find(".wijmo-wijev-day-details .wijmo-wijev-daycalendar").wijcalendar("refresh");

                this.element.find(".wijmo-wijev-day-details .wijmo-wijev-monthday-label").html(selectedDate.getDate());
                this.element.find(".wijmo-wijev-day-details .wijmo-wijev-fulldate-label").html(this._formatString(this.localizeString("dayDetailsLabelFulldateFormat", "{0:dddd, MMMM d}"), selectedDate));

                //Tuesday, November 1
                this.element.find(".wijmo-wijev-day-details .wijmo-wijev-year-label").html(this._formatString(this.localizeString("dayDetailsLabelYearFormat", "{0:yyyy}"), selectedDate));

                //selectedDate.getFullYear()
                this._updateAgendaList(this.element.find(".wijmo-wijev-day-details  .wijmo-wijev-agenda-container"), selectedDate, selectedDate, false);
            };

            wijevcal.prototype._listViewAgendaScrolled = function (e, data) {
                var supPanel = this.element.find(".wijmo-wijev-list-details .wijmo-wijev-agenda-container"), vScroller = supPanel.wijsuperpanel("option", "vScroller"), $agendaList, scrollValue = vScroller.scrollValue, scrollMax = vScroller.scrollMax - vScroller.scrollLargeChange * 2, eventType = e.type, isEnd = false, position;

                // in IE10, the superpanel's event is scroll.
                if (eventType === "wijsuperpanelscroll") {
                    position = data.position;
                    $agendaList = supPanel.find(".wijmo-wijsuperpanel-contentwrapper-touch");
                    if (supPanel.height() + position >= $agendaList.height()) {
                        isEnd = true;
                    }
                } else {
                    $agendaList = supPanel.find(".wijmo-wijsuperpanel-templateouterwrapper");
                }

                if (scrollValue >= scrollMax || isEnd) {
                    if ($agendaList.data("wijevcal_agenda_loadnextpage")) {
                        $agendaList.data("wijevcal_agenda_loadnextpage", false);
                        $agendaList.find(".wijmo-wijev-agenda-more-events").show().html(this.localizeString("agendaLoadingMoreEvents", "Loading more events..."));
                        if (this._renderAgendaEventsTimeoutId) {
                            clearTimeout(this._renderAgendaEventsTimeoutId);
                            this._renderAgendaEventsTimeoutId = null;
                        }
                        this._renderAgendaEventsTimeoutId = setTimeout($.proxy(function () {
                            this._renderAgendaEventsTimeoutId = null;

                            // fix the issue 42885, this method lack an argument, and when scroll the superpanel to load
                            // more events, it will throw exception.
                            this._renderAgendaEvents($agendaList, null, null, true, supPanel);

                            // fix for 29488:
                            $agendaList.find(".wijmo-wijev-agenda-more-events").remove();
                        }, this), 100);
                    }
                }
            };

            wijevcal.prototype._updateListViewDetails = function () {
                if (!this._listViewDetailsInit) {
                    this._listViewDetailsInit = true;
                    if ($.support.isTouchEnabled && $.support.isTouchEnabled()) {
                        this.element.find(".wijmo-wijev-list-details .wijmo-wijev-agenda-container").wijsuperpanel({
                            scroll: $.proxy(this._listViewAgendaScrolled, this)
                        });
                    } else {
                        this.element.find(".wijmo-wijev-list-details .wijmo-wijev-agenda-container").wijsuperpanel({
                            scrolled: $.proxy(this._listViewAgendaScrolled, this)
                        });
                    }
                }
                this._updateAgendaList(this.element.find(".wijmo-wijev-list-details  .wijmo-wijev-agenda-container"), null, null, true);
            };

            wijevcal.prototype._updateAgendaList = function (agendaContainer, startDt, endDt, listViewMode) {
                var leftPane = this.element.find(".wijmo-wijev-leftpane"), $agendaList = agendaContainer;

                ///////////
                // invalidate agenda height when text is changed(fix for 21282):
                agendaContainer.outerHeight(leftPane.innerHeight() - agendaContainer[0].offsetTop);

                if ($agendaList.find(".wijmo-wijsuperpanel-templateouterwrapper").length > 0) {
                    $agendaList = $agendaList.find(".wijmo-wijsuperpanel-templateouterwrapper");
                }
                if ($.support.isTouchEnabled && $.support.isTouchEnabled()) {
                    $agendaList = $agendaList.find(".wijmo-wijsuperpanel-contentwrapper-touch");
                }

                if (listViewMode && $agendaList.data("wijevcal_agenda_initialized")) {
                    /*fix for 24623 */
                    //$agendaList.parents(".wijmo-wijsuperpanel:first").wijsuperpanel("refresh");
                    // fixed the issue 41787, do not use the parents if the eventscalender is inside of superpanel, it will cause exception.
                    if (agendaContainer.data("wijmo-wijsuperpanel")) {
                        //Don't set focus back to element in IE8
                        this._refreshSuperPanel(agendaContainer);
                    }
                    return;
                }
                $agendaList.data("wijevcal_agenda_initialized", true);
                $agendaList.data("wijevcal_agenda_loadedeventscount", 0);

                /////////
                $agendaList.html("");
                this._renderAgendaEvents($agendaList, startDt, endDt, listViewMode, agendaContainer);
            };

            wijevcal.prototype._isIE8 = function () {
                return $.browser.msie && $.browser.version && parseFloat($.browser.version) <= 8;
            };
            wijevcal.prototype._renderAgendaEvents = function ($agendaList, startDt, endDt, listViewMode, agendaContainer) {
                var appts = this._eventsView, appt, i, apptsCount, daysCount, dayIdx = 0, curDayApptsCount, s = "", s2 = "", viewStart = null, viewEnd = null, o = this.options, curDayStart, curDayEnd, eventsPerPage = 100, self = this, loadedEventsCount = $agendaList.data("wijevcal_agenda_loadedeventscount");
                if (startDt) {
                    viewStart = _toDayDate(startDt);
                    viewEnd = this._addDays(_toDayDate(endDt), 1);
                    daysCount = (viewEnd.getTime() - viewStart.getTime()) / (1000 * 60 * 60 * 24);
                }

                if (appts) {
                    apptsCount = (appts.length < (eventsPerPage + loadedEventsCount) || !listViewMode) ? appts.length : (eventsPerPage + loadedEventsCount);
                    $agendaList.data("wijevcal_agenda_loadedeventscount", apptsCount);
                    if (!viewStart) {
                        s2 = "";
                        for (i = loadedEventsCount; i < apptsCount; i += 1) {
                            appt = appts[i];
                            if (i === loadedEventsCount || curDayStart.getDate() !== appt.start.getDate()) {
                                curDayStart = appt.start;

                                if (i !== 0) {
                                    s += "<ul class=\"wijmo-wijev-agenda-list\">" + s2 + "</ul>";
                                    s += "</div>";
                                }

                                s += "<div class=\"wijmo-wijev-agenda-day-container " + this._dayDateToCssClass(curDayStart) + "\">";
                                if (listViewMode) {
                                    s += this._renderAgendaDayHeader(curDayStart);
                                }
                                s2 = "";
                            }
                            s2 += this._renderAgendaAppointmentVisual(appt);
                            curDayApptsCount += 1;

                            if (i === apptsCount - 1) {
                                s += "<ul class=\"wijmo-wijev-agenda-list\">" + s2 + "</ul>";
                                s += "</div>";
                                if (apptsCount < appts.length) {
                                    s += "<div class=\"wijmo-wijev-agenda-more-events\">";

                                    s += this._formatString(this.localizeString("agendaMoreEventsFormat", "More events ({0})..."), (appts.length - apptsCount));

                                    s += "<div>";
                                    $agendaList.data("wijevcal_agenda_loadnextpage", true);
                                } else {
                                    $agendaList.data("wijevcal_agenda_loadnextpage", false);
                                }
                            }
                        }
                    } else {
                        while (dayIdx < daysCount) {
                            curDayStart = this._addDays(viewStart, dayIdx);
                            curDayStart = new Date(curDayStart.getFullYear(), curDayStart.getMonth(), curDayStart.getDate());
                            curDayEnd = new Date(curDayStart.getFullYear(), curDayStart.getMonth(), curDayStart.getDate(), 23, 59, 59);
                            curDayApptsCount = 0;
                            s2 = "";
                            for (i = loadedEventsCount; i < apptsCount; i += 1) {
                                appt = appts[i];
                                if ((appt.start < viewEnd && appt.end > viewStart) && (appt.start < curDayEnd && appt.start >= curDayStart)) {
                                    s2 += this._renderAgendaAppointmentVisual(appt);
                                    curDayApptsCount += 1;
                                }
                            }
                            if (s2 !== "") {
                                s += "<div class=\"wijmo-wijev-agenda-day-container " + this._dayDateToCssClass(curDayStart) + "\">";
                                if (listViewMode) {
                                    s += this._renderAgendaDayHeader(curDayStart);
                                }
                                s += "<ul class=\"wijmo-wijev-agenda-list\">" + s2 + "</ul>";
                                s += "</div>";
                            }
                            dayIdx += 1;
                        }
                    }
                    $(s).appendTo($agendaList);
                }
                $agendaList.on("click", ".wijmo-wijev-agenda-event", $.proxy(this._onAgendaEventClick, this)).on("mouseover", ".wijmo-wijev-agenda-event", function (e) {
                    if (self._isDisabled()) {
                        return;
                    }
                    $(this).addClass(o.wijCSS.stateHover);
                }).on("mouseout", ".wijmo-wijev-agenda-event", function (e) {
                    if (self._isDisabled()) {
                        return;
                    }
                    $(this).removeClass(o.wijCSS.stateHover).removeClass(o.wijCSS.stateActive);
                }).on("mousedown", ".wijmo-wijev-agenda-event", function () {
                    if (self._isDisabled()) {
                        return;
                    }
                    $(this).addClass(o.wijCSS.stateActive);
                }).on("mouseup", ".wijmo-wijev-agenda-event", function () {
                    if (self._isDisabled()) {
                        return;
                    }
                    $(this).removeClass(o.wijCSS.stateActive);
                });

                // Fixed the issue 41787.
                if (agendaContainer.data("wijmo-wijsuperpanel")) {
                    this._refreshSuperPanel(agendaContainer);
                }
                //$agendaList.parents(".wijmo-wijsuperpanel").wijsuperpanel("refresh");
            };

            wijevcal.prototype._renderAgendaDayHeader = function (curDayStart) {
                //var s = "<div class=\"wijmo-wijev-agenda-header ui-widget-header\">" +
                var s = "<div class=\"wijmo-wijev-agenda-header " + this.options.header + "\">" + "<div class=\"wijmo-wijev-weekday\">" + this._formatString("{0:dddd}", curDayStart) + "</div>" + "<div class=\"wijmo-wijev-date\">" + this._formatString(this.localizeString("agendaHeaderFullDateFormat", "{0:MMMM d, yyyy}"), curDayStart) + "</div>" + "</div>";
                return s;
            };
            wijevcal.prototype._onAgendaEventClick = function (e) {
                if (this._isDisabled()) {
                    return;
                }
                var target = $(e.target);
                if (!target.hasClass("wijmo-wijev-agenda-event")) {
                    target = target.parent(".wijmo-wijev-agenda-event");
                }
                if (target.length > 0) {
                    //alert(this._parseEventIdFromClass(target[0].className) + "," + target[0].className);
                    this.goToEvent(this._parseEventIdFromClass(target[0].className));
                    //this.goToDate(this._parseDateFromClass(target[0].className));
                }
            };

            wijevcal.prototype._renderAgendaAppointmentVisual = function (ev) {
                var s = "<li class=\"wijmo-wijev-agenda-event " + this._dayDateToCssClass(ev.start) + " " + this._eventIdToCssClass(ev.id) + " " + this.options.wijCSS.stateDefault + " " + this.options.wijCSS.helperClearFix + "\">" + "<div class=\"wijmo-wijev-agenda-event-color " + "wijmo-wijev-event-color-" + (ev.color || "default") + "\">" + "<div></div>" + "</div>" + "<div class=\"wijmo-wijev-agenda-event-title\">" + ev.subject + "</div>" + "<div class=\"wijmo-wijev-agenda-event-time\">" + (this.isAllDayEvent(ev) ? this.localizeString("labelAllDay", "all-day") : this._formatString(this.localizeString("agendaTimeFormat", "{0:hh:mm tt} to {1:hh:mm tt}"), ev.start, ev.end)) + "</div>" + "</li>";
                return s;
            };

            //wijmo-wijev-day-details
            wijevcal.prototype._invalidateCurrentTimeIndicator = function () {
                var timeInicator = this.element.find(".wijmo-wijev-timeruler .wijmo-wijev-currenttime-indicator"), curTime = new Date(), o = this.options;
                curTime = curTime.getMinutes() + curTime.getHours() * 60;
                timeInicator.css("top", (curTime / o.timeInterval) * o.timeIntervalHeight);
            };

            // <- end of day view
            wijevcal.prototype._onEventsDataChanged = function () {
                this._clearViewsCache();
                this._prepareEventsForView();
                this._renderActiveView();
                this._trigger("eventsDataChanged", null, { eventsData: this.options.eventsData });
            };
            wijevcal.prototype._onCalendarsChanged = function () {
                this._trigger("calendarsChanged", null, { calendars: this.options.calendars });
            };

            wijevcal.prototype._renderDayViewAppointments = function () {
                var self = this, appts = self._eventsView, appt, i, j, apptsCount, daysCount, headercontainer = self.element.find(".wijmo-wijev-headercontainer"), scrollcontent = self.element.find(".wijmo-wijev-scrollcontent"), dayHeaderColumns = headercontainer.find(".wijmo-wijev-dayheadercolumn"), dayColumns = scrollcontent.find(".wijmo-wijev-daycolumn"), curDayStart, curDayEnd, o = self.options, columnDates = self._getDayColumnDates(), viewStart = columnDates[0], viewEnd, allDayCellChanged, eventsArg, eventsTemplate = null, eventsTmp, apptVisual, visualStartDt, visualEndDt, visualStartMin, visualEndMin, visualStartPx, visualEndPx, conflictColumns = [], superpanelEle;
                viewEnd = columnDates[columnDates.length - 1];
                viewEnd = new Date(viewEnd.getFullYear(), viewEnd.getMonth(), viewEnd.getDate(), 23, 59, 59);
                if (appts) {
                    for (j = 0, daysCount = columnDates.length; j < daysCount; j += 1) {
                        if (!dayColumns[j]._cached) {
                            curDayStart = columnDates[j];
                            curDayStart = new Date(curDayStart.getFullYear(), curDayStart.getMonth(), curDayStart.getDate());
                            curDayEnd = new Date(curDayStart.getFullYear(), curDayStart.getMonth(), curDayStart.getDate(), 23, 59, 59);
                            for (i = 0, apptsCount = appts.length; i < apptsCount; i += 1) {
                                appt = appts[i];
                                if ((appt.start < viewEnd && appt.end > viewStart) && (appt.start < curDayEnd && appt.end > curDayStart)) {
                                    if (this.isAllDayEvent(appt)) {
                                        allDayCellChanged = true;
                                        apptVisual = $(self._getAllDayEventMarkup(appt));

                                        $(dayHeaderColumns[j]).find(".wijmo-wijev-allday-cell").append(apptVisual);
                                    } else {
                                        visualStartDt = appt.start;
                                        visualEndDt = appt.end;
                                        if (visualStartDt < curDayStart) {
                                            visualStartDt = curDayStart;
                                        }
                                        if (visualEndDt > curDayEnd) {
                                            visualEndDt = curDayEnd;
                                        }

                                        visualStartMin = (((visualStartDt - curDayStart) / 1000) / 60);
                                        visualEndMin = (((visualEndDt - curDayStart) / 1000) / 60);
                                        visualStartPx = Math.round(visualStartMin * o.timeIntervalHeight / o.timeInterval);
                                        visualEndPx = Math.round(visualEndMin * o.timeIntervalHeight / o.timeInterval);

                                        apptVisual = $(self._getEventMarkup(appt));
                                        apptVisual.css("top", visualStartPx);
                                        apptVisual.outerHeight(visualEndPx - visualStartPx);
                                        $(dayColumns[j]).append(apptVisual);
                                    }
                                }
                            }

                            //
                            this._storeDayCache(columnDates[j], dayHeaderColumns[j], dayColumns[j]);
                            dayColumns[j]._cached = true;
                            conflictColumns.push(dayColumns[j]);
                        } else {
                            // fix for 30112 case 1:
                            conflictColumns.push(dayColumns[j]);
                        }
                    }
                }

                this._dayColumnsToResolve = conflictColumns;
                this._dayColumnResolveIdx = 0;
                if (!this._resolveDayApptConflictsTimeout) {
                    clearTimeout(this._resolveDayApptConflictsTimeout);
                    this._resolveDayApptConflictsTimeout = null;
                }
                this._resolveDayApptConflictsTimeout = setTimeout($.proxy(this._resolveDayViewAppointmentConflictsCb1, this), 1);

                // adjust scroll height according new all day cells height:
                if (allDayCellChanged) {
                    this._invalidateDayView(true);
                }
                if (this._dayViewScrollToEvent) {
                    apptVisual = this.element.find(".wijmo-wijev-dayview .wijmo-wijev-daycolumn ." + this._eventIdToCssClass(this._dayViewScrollToEvent.id));
                    if (apptVisual.length > 0) {
                        superpanelEle = apptVisual.parents(".wijmo-wijev-scrollpanel");
                        if (superpanelEle.length > 0) {
                            superpanelEle.wijsuperpanel("scrollChildIntoView", apptVisual);
                        }
                    }
                    //this._dayViewScrollToEvent = null;
                }
            };

            wijevcal.prototype._getAllDayEventMarkup = function (appt) {
                return "<div class=\"wijmo-wijev-appointment " + this._eventIdToCssClass(appt.id) + "\">" + "<div class=\"" + " wijmo-wijev-colordot wijmo-wijev-event-color-" + (appt.color || "default") + "\"></div>" + "<div class=\"wijmo-wijev-event-title\">" + appt.subject + "</div>" + "</div>";
            };

            wijevcal.prototype._getEventMarkup = function (appt) {
                var self = this, eventsArg = { data: appt, eventTemplate: null }, eventsTmp, o = self.options;
                if (o.eventTemplate) {
                    eventsArg.eventTemplate = o.eventTemplate;
                }
                self._trigger("eventCreating", null, eventsArg);
                eventsTmp = eventsArg.eventTemplate ? $(eventsArg.eventTemplate) : null;
                if (eventsTmp) {
                    eventsTmp.addClass("wijmo-wijev-appointment " + self._eventIdToCssClass(appt.id));
                    return eventsTmp[0].outerHTML;
                } else {
                    return "<div class=\"wijmo-wijev-appointment wijmo-wijev-event-color-" + (appt.color || "default") + " " + self._eventIdToCssClass(appt.id) + "\">" + "<div class=\"wijmo-wijev-content\"><div class=\"wijmo-wijev-title\">" + self._formatString(self.options.eventTitleFormat, appt.start, appt.end, appt.subject, appt.location, "", appt.description) + "</div></div>" + "<div class=\"wijmo-wijev-resizer\">" + "<div class=\"" + self.options.wijCSS.icon + " " + self.options.wijCSS.iconHGripSolid + "\">" + "&nbsp;</div></div>" + "</div>";
                }
            };

            wijevcal.prototype._resolveDayViewAppointmentConflictsCb1 = function () {
                this._resolveDayApptConflictsTimeout = null;
                if (!this._dayColumnsToResolve || this._dayColumnResolveIdx >= this._dayColumnsToResolve.length) {
                    this._renderComplete();
                    return;
                }
                this._resolveDayViewAppointmentConflicts(this._dayColumnsToResolve[this._dayColumnResolveIdx]);
                this._dayColumnResolveIdx = this._dayColumnResolveIdx + 1;
                setTimeout($.proxy(this._resolveDayViewAppointmentConflictsCb1, this), 1);
            };

            wijevcal.prototype._renderComplete = function () {
                if (this.element.find(".loadCompletely").length === 0) {
                    $("<input type='hidden' class='loadCompletely'></input>").appendTo(this.element);
                }
            };

            wijevcal.prototype._resolveDayViewAppointmentConflicts = function (col) {
                var eventsData = $(col).find(".wijmo-wijev-appointment"), eventDataArray, intersections = [], arr1, i, j, appt1, appt2, count1, count2, v, startIndex = 0;
                eventDataArray = $(eventsData).toArray().sort(this._sortOffsetTop);
                for (i = 0, count1 = eventsData.length; i < count1; i += 1) {
                    if (i < startIndex) {
                        continue;
                    }
                    appt1 = eventDataArray[i];
                    for (j = i; j < count1; j += 1) {
                        if (j !== i) {
                            appt2 = eventDataArray[j];
                            if ((appt1.offsetTop) < (appt2.offsetTop + appt2.offsetHeight) && (appt1.offsetTop + appt1.offsetHeight) > appt2.offsetTop) {
                                if (!intersections[i]) {
                                    intersections[i] = [appt1];
                                }
                                intersections[i].push(appt2);

                                if ((appt2.offsetTop + appt2.offsetHeight) > (appt1.offsetTop + appt1.offsetHeight))
                                    appt1 = appt2;
                            } else {
                                break;
                            }
                        }
                    }
                    startIndex = j;
                }

                for (i = 0, count1 = intersections.length; i < count1; i += 1) {
                    arr1 = intersections[i];
                    if (arr1) {
                        count2 = arr1.length;
                        arr1.sort(this._sortOffsetTop);
                        for (j = 0; j < count2; j += 1) {
                            appt1 = arr1[j];
                            appt1.style.width = Math.floor(100 / count2) + "%";
                            v = Math.floor(100 * j / count2);
                            appt1.style.marginLeft = v + "%";
                            appt1.style.zIndex = v;
                        }
                    }
                }
            };

            wijevcal.prototype._sortOffsetTop = function (a, b) {
                if (a.offsetTop < b.offsetTop) {
                    return -1;
                } else if (a.offsetTop > b.offsetTop) {
                    return 1;
                }
                return 0;
            };

            // day view time interval
            wijevcal.prototype._onDayViewTimeIntervalClick = function (e) {
                if (this._isDisabled()) {
                    return;
                }
                if (this.options.readOnly) {
                    return;
                }
                this.showEditEventDialog(null, e.target, e);
            };

            wijevcal.prototype._onDayViewAllDayCellClick = function (e) {
                if (this._isDisabled()) {
                    return;
                }
                if (this.options.readOnly) {
                    return;
                }
                var targetAppt = $(e.target);
                if (targetAppt.hasClass("wijmo-wijev-appointment") || targetAppt.parents(".wijmo-wijev-appointment").length > 0) {
                    return;
                }
                if ((targetAppt.hasClass("wijmo-wijev-daylabel") || targetAppt.parents(".wijmo-wijev-daylabel").length > 0)) {
                    return;
                }

                //
                this.showEditEventDialog(null, e.target, e);
            };

            wijevcal.prototype._onYearViewDayLabelClick = function (e) {
                var o = this.options;
                if (this._isDisabled()) {
                    return;
                }
                if ($.inArray("month", this._viewsToLower(o.views)) < 0) {
                    return;
                }
                var yearcellcontainer = $(e.target).parents(".wijmo-wijev-yearcellcontainer"), o = this.options, cellDate;

                //
                if (yearcellcontainer[0]) {
                    cellDate = this._parseDateFromClass(yearcellcontainer[0].className);
                    if (o.viewType !== "month") {
                        o.viewType = "month";
                        this._onViewTypeChanged();
                    }
                    o.selectedDates = [new Date(cellDate)];
                    this._onSelectedDatesChanged();
                }
            };

            wijevcal.prototype._onMonthViewDayLabelClick = function (e) {
                var o = this.options;
                if (this._isDisabled()) {
                    return;
                }
                if ($.inArray("day", this._viewsToLower(o.views)) < 0) {
                    return;
                }
                var monthcellcontainer = $(e.target).parents(".wijmo-wijev-monthcellcontainer"), o = this.options, cellDate;

                if (monthcellcontainer.length < 1) {
                    monthcellcontainer = $(e.target).parents(".wijmo-wijev-dayheadercolumn");
                }

                if (monthcellcontainer[0]) {
                    cellDate = this._parseDateFromClass(monthcellcontainer[0].className);
                    if (o.viewType !== "day") {
                        o.viewType = "day";
                        this._onViewTypeChanged();
                    }
                    o.selectedDates = [new Date(cellDate)];
                    this._onSelectedDatesChanged();
                }
            };
            wijevcal.prototype._onMonthViewCellClick = function (e) {
                if (this._isDisabled()) {
                    return;
                }
                var monthcellcontainer = $(e.target).parent(".wijmo-wijev-monthcellcontainer");
                if (this.options.readOnly) {
                    return;
                }
                if (monthcellcontainer.length < 1) {
                    return;
                }
                this.showEditEventDialog(null, monthcellcontainer, e);
            };

            wijevcal.prototype._onYearViewCellClick = function (e) {
                if (this._isDisabled()) {
                    return;
                }
                var yearcellcontainer = $(e.target).parent(".wijmo-wijev-yearcellcontainer");
                if (this.options.readOnly) {
                    return;
                }
                if (yearcellcontainer.length < 1) {
                    return;
                }
                this.showEditEventDialog(null, yearcellcontainer, e);
            };

            wijevcal.prototype._onAppointmentClick = function (e) {
                var target = $(e.target), appt;
                if (this._isDisabled()) {
                    return;
                }
                if (this.options.readOnly) {
                    return;
                }
                if (this._apptDragResizeFlag) {
                    return;
                }
                if (!target.hasClass("wijmo-wijev-appointment")) {
                    target = target.parents(".wijmo-wijev-appointment");
                }
                if (target.length > 0) {
                    appt = this.findEventById(target[0].className);
                    this.showEditEventDialog(appt, target, e);
                }
            };

            /** Find event object by id
            * @returns {object} events data.
            */
            wijevcal.prototype.findEventById = function (id) {
                var i;
                if (id) {
                    i = id.indexOf("apptid_");
                    if (i !== -1) {
                        id = this._parseEventIdFromClass(id);
                    }
                    if (this._eventsDataById) {
                        return this._eventsDataById[id];
                    }
                }
                return null;
            };

            // month view appointment drag/drop
            wijevcal.prototype._onMonthViewAppointmentMouseDown = function (e) {
                if (this._isDisabled()) {
                    return;
                }
                if (this.options.readOnly) {
                    return;
                }
                var target = $(e.target), appt = target.hasClass("wijmo-wijev-appointment") ? target : target.parents(".wijmo-wijev-appointment");
                e.preventDefault();
                this.__targetAppt = appt;
                $(document).bind("mouseup.tmp_wijevcal", $.proxy(this._onMonthViewAppointmentMouseUp, this));
                this.element.find(".wijmo-wijev-monthview .wijmo-wijev-monthcellcontainer").bind("mouseover.tmp_wijevcal", $.proxy(this._onMonthViewCellMouseOver, this));
            };

            // day view appointment drag/drop/resize/inline edit
            wijevcal.prototype._onDayViewAppointmentMouseDown = function (e) {
                if (this._isDisabled()) {
                    return;
                }
                if (this.options.readOnly) {
                    return;
                }
                var target = $(e.target), appt = target.hasClass("wijmo-wijev-appointment") ? target : target.parents(".wijmo-wijev-appointment"), isResize = target.hasClass("wijmo-wijev-resizer") || target.parents(".wijmo-wijev-resizer").length > 0;
                if (this._isDisabled()) {
                    //fix for 20811
                    return;
                }

                this._isApptResize = isResize;
                e.preventDefault();
                if (this._isApptResize) {
                    this.__startApptH = appt[0].offsetHeight;
                    this.__startApptY = appt[0].offsetTop;
                } else {
                    this.__startApptY = appt[0].offsetTop;
                }
                this.__startClientY = e.clientY;
                this.__targetAppt = appt;
                $(document).bind("mousemove.tmp_wijevcal", $.proxy(this._onDayViewAppointmentMouseMove, this));
                $(document).bind("mouseup.tmp_wijevcal", $.proxy(this._onDayViewAppointmentMouseUp, this));
                $(this.element).find(".wijmo-wijev-dayview .wijmo-wijev-daycolumn").bind("mouseover.tmp_wijevcal", $.proxy(this._onDayViewColumnMouseOver, this));
                $(this.element).find(".wijmo-wijev-dayview .wijmo-wijev-allday-cell").bind("mouseover.tmp_wijevcal", $.proxy(this._onDayViewAllDayMouseOver, this));
            };

            wijevcal.prototype._onDayViewAppointmentMouseMove = function (e) {
                if (this._isDisabled()) {
                    return;
                }
                e.preventDefault();
                var ychange = e.clientY - this.__startClientY, top, o = this.options, newHeight, offsetTop, superpanelEle;
                if (!e.ctrlKey) {
                    ychange = Math.round(ychange / o.timeIntervalHeight) * o.timeIntervalHeight;
                }
                if (ychange !== 0 && !this._apptDragResizeFlag) {
                    this._apptDragResizeFlag = true;
                    this.__targetAppt.addClass("wijmo-wijev-dragging");
                    this.__targetAppt.css("width", "100%").css("margin-left", "0").css("z-index", "1000");
                }
                if (this._apptDragResizeFlag) {
                    if (this._isApptResize) {
                        newHeight = this.__startApptH + ychange;
                        if (newHeight < 0) {
                            newHeight = Math.abs(newHeight);
                            top = this.__startApptY - newHeight;
                            if (top >= 0) {
                                this.__targetAppt.css("height", newHeight);
                                this.__targetAppt.css("top", top);
                            }
                        } else {
                            this.__targetAppt.css("height", newHeight);
                        }
                    } else {
                        top = this.__startApptY + ychange;
                        if (top < 0) {
                            top = 0;
                        }
                        this.__targetAppt.css("top", top);
                        offsetTop = this.__targetAppt.offset().top;

                        //fix for 25070 (part 1):
                        superpanelEle = this.__targetAppt.parents(".wijmo-wijev-scrollpanel");
                        if (superpanelEle.length > 0) {
                            superpanelEle.wijsuperpanel("scrollChildIntoView", this.__targetAppt);
                        }

                        this.__startApptY = this.__startApptY - (this.__targetAppt.offset().top - offsetTop);
                    }
                    this._onApptVisualDargOrResize(this.__targetAppt, this.findEventById(this.__targetAppt[0].className));
                }
            };
            wijevcal.prototype._onDayViewAppointmentMouseUp = function (e) {
                if (this._isDisabled()) {
                    return;
                }
                if (this.__targetAppt) {
                    this.__targetAppt.removeClass("wijmo-wijev-dragging");
                }
                $(document).unbind(".tmp_wijevcal");
                $(this.element).find(".wijmo-wijev-dayview .wijmo-wijev-daycolumn").unbind(".tmp_wijevcal");

                $(this.element).find(".wijmo-wijev-dayview .wijmo-wijev-allday-cell").unbind(".tmp_wijevcal");

                if (this._apptDragResizeFlag || this._apptMovedFlag) {
                    var o = this.findEventById(this.__targetAppt[0].className);
                    this._onApptVisualDargOrResize(this.__targetAppt, o);
                    this._apptMovedFlag = false;
                    this._movedFromTimeInervalApptElem = null;
                    this.updateEvent(o);
                    window.setTimeout($.proxy(function () {
                        if (this.__targetAppt && !this.__targetAppt.hasClass("wijmo-wijev-dragging")) {
                            this._apptDragResizeFlag = false;

                            // fix for 30112 case 2
                            this._resolveDayViewAppointmentConflicts(this.__targetAppt.parents(".wijmo-wijev-daycolumn"));
                        }
                    }, this), 1);
                }
            };

            wijevcal.prototype._updateMonthViewApptVisual = function (appt) {
                var visual = this.element.find(".wijmo-wijev-monthview ." + this._eventIdToCssClass(appt.id)), o = this.options, curDayStart, columnDateClass, sourceCol, targetCol;

                if (visual.length !== 1) {
                    return;
                }

                curDayStart = _toDayDate(appt.start);

                columnDateClass = this._dayDateToCssClass(curDayStart);
                sourceCol = visual[0].parentNode;
                targetCol = this.element.find(".wijmo-wijev-monthcellcontainer." + columnDateClass + ">.wijmo-wijev-monthcell");
                sourceCol.removeChild(visual[0]);
                visual.appendTo(targetCol);
            };

            wijevcal.prototype._updateDayViewApptVisual = function (appt) {
                var visual = this.element.find(".wijmo-wijev-dayview ." + this._eventIdToCssClass(appt.id)), o = this.options, visualStartMin, visualEndMin, visualStartPx, visualEndPx, curDayStart, columnDateClass, sourceCol, targetCol;

                if (visual.length < 1) {
                    return;
                }

                visual.remove();
                if (appt.allday) {
                    this.element.find(".wijmo-wijev-dayheadercolumn." + this._dayDateToCssClass(appt.start)).find(".wijmo-wijev-allday-cell").append($(this._getAllDayEventMarkup(appt)));
                    return;
                } else {
                    visual = $(this._getEventMarkup(appt));
                }

                visual.find(".wijmo-wijev-title").html(this._formatString(o.eventTitleFormat, appt.start, appt.end, appt.subject, appt.location, "", appt.description));
                curDayStart = _toDayDate(appt.start);
                visualStartMin = (((appt.start - curDayStart) / 1000) / 60);
                visualEndMin = (((appt.end - curDayStart) / 1000) / 60);
                visualStartPx = Math.round(visualStartMin * o.timeIntervalHeight / o.timeInterval);
                visualEndPx = Math.round(visualEndMin * o.timeIntervalHeight / o.timeInterval);
                visual.css("top", visualStartPx);
                visual.css("height", (visualEndPx - visualStartPx));

                columnDateClass = this._dayDateToCssClass(curDayStart);
                if (visual.parents(".wijmo-wijev-daycolumn." + columnDateClass).length !== 1) {
                    sourceCol = visual[0].parentNode;
                    targetCol = this.element.find(".wijmo-wijev-daycolumn." + columnDateClass);
                    sourceCol.removeChild(visual[0]);
                    visual.appendTo(targetCol);
                }
            };

            wijevcal.prototype._updateAppointmentVisual = function (appt) {
                if (this.options.viewType === "month") {
                    this._updateMonthViewApptVisual(appt);
                } else {
                    this._updateDayViewApptVisual(appt);
                }
            };

            wijevcal.prototype._onApptVisualDargOrResize = function (visual, appt) {
                if (this._isDisabled()) {
                    return;
                }
                var o = this.options, visualStartPx = visual[0].offsetTop, visualEndPx = visualStartPx + visual[0].offsetHeight, visualStartMin, visualEndMin, visualStartDt, visualEndDt, realEndDt, durationMs, curDayStart, parentCol;
                if (visual.parents(".wijmo-wijev-dayheadercolumn").length > 0) {
                    parentCol = visual.parents(".wijmo-wijev-dayheadercolumn")[0];
                } else {
                    parentCol = visual.parents(".wijmo-wijev-daycolumn")[0];
                }
                curDayStart = this._parseDateFromClass(parentCol.className, null);

                //If drop into allday or not resize action, start/end values should be fit in timeslot.
                if (appt.allday || !this._isApptResize) {
                    visualStartMin = Math.round(visualStartPx / o.timeIntervalHeight) * o.timeInterval;
                    visualEndMin = Math.round(visualEndPx / o.timeIntervalHeight) * o.timeInterval;
                } else {
                    visualStartMin = Math.round(visualStartPx * o.timeInterval / o.timeIntervalHeight);
                    visualEndMin = Math.round(visualEndPx * o.timeInterval / o.timeIntervalHeight);
                }
                visualStartDt = new Date(visualStartMin * 60 * 1000 + curDayStart.getTime());

                visualEndDt = new Date(visualEndMin * 60 * 1000 + curDayStart.getTime());
                if (appt) {
                    if (!this._isApptResize) {
                        // fix for 25120
                        // do not change duration for drag action
                        durationMs = appt.end.getTime() - appt.start.getTime();
                        realEndDt = new Date(visualStartDt.getTime() + durationMs);
                    } else {
                        realEndDt = visualEndDt;
                    }
                    appt.allday = visual.parents(".wijmo-wijev-dayheadercolumn").length > 0;
                    appt.start = visualStartDt;
                    appt.end = realEndDt; //visualEndDt;

                    visual.find(".wijmo-wijev-title").html(this._formatString(o.eventTitleFormat, appt.start, appt.end, appt.subject, appt.location, "", appt.description));
                    if (!this._isApptResize && realEndDt.getTime() !== visualEndDt.getTime()) {
                        // fix for 25120
                        // Update visual height
                        visual.css("height", (Math.round((((appt.end - _toDayDate(appt.start)) / 1000) / 60) * o.timeIntervalHeight / o.timeInterval) - Math.round((((appt.start - _toDayDate(appt.start)) / 1000) / 60) * o.timeIntervalHeight / o.timeInterval)));
                    }
                }
            };

            wijevcal.prototype._onDayViewColumnMouseOver = function (e) {
                if (this._isDisabled()) {
                    return;
                }
                var targetCol = $(e.target).parents(".wijmo-wijev-daycolumn"), sourceCol = this.__targetAppt.parents(".wijmo-wijev-daycolumn");
                if (targetCol.length < 1) {
                    return;
                }
                if (sourceCol.length < 1) {
                    sourceCol = this.__targetAppt.parents(".wijmo-wijev-dayheadercolumn");
                    if (sourceCol.length < 1) {
                        return;
                    } else {
                        // move from all day event cell to time interval.
                        if (this._movedFromTimeInervalApptElem) {
                            // fix for 25070 case 2.
                            this.__targetAppt.replaceWith(this._movedFromTimeInervalApptElem);
                            this.__targetAppt = $(this._movedFromTimeInervalApptElem);
                            this._movedFromTimeInervalApptElem = null;
                        } else {
                            this.__targetAppt.html(this._getEventMarkup(this.findEventById(this.__targetAppt[0].className)));
                        }
                    }
                }
                if (targetCol[0].className !== sourceCol[0].className) {
                    this.__targetAppt[0].parentNode.removeChild(this.__targetAppt[0]);

                    this._resolveDayViewAppointmentConflicts(sourceCol);
                    this.__targetAppt.appendTo(targetCol);
                    this._apptMovedFlag = true;
                }
            };

            wijevcal.prototype._onMonthViewCellMouseOver = function (e) {
                if (this._isDisabled()) {
                    return;
                }
                var target = $(e.target), targetCell = target.hasClass("wijmo-wijev-monthcellcontainer") ? target : target.parents(".wijmo-wijev-monthcellcontainer"), sourceCell = this.__targetAppt.parents(".wijmo-wijev-monthcellcontainer");

                if (targetCell.length < 1 || sourceCell.length < 1) {
                    return;
                }
                if (targetCell[0].className !== sourceCell[0].className) {
                    this.__targetAppt[0].parentNode.removeChild(this.__targetAppt[0]);
                    this.__targetAppt.appendTo(targetCell.find(".wijmo-wijev-monthcell"));
                    this.__targetApptChanged = true;
                }
            };

            wijevcal.prototype._onMonthViewAppointmentMouseUp = function () {
                if (this._isDisabled()) {
                    return;
                }
                var appt, parentCell = this.__targetAppt.parents(".wijmo-wijev-monthcellcontainer")[0], curDayStart = this._parseDateFromClass(parentCell.className, null), daysDiff;

                $(document).unbind(".tmp_wijevcal");
                this.element.find(".wijmo-wijev-monthview .wijmo-wijev-monthcellcontainer").unbind(".tmp_wijevcal");
                if (this.__targetApptChanged) {
                    this.__targetApptChanged = false;
                    appt = this.findEventById(this.__targetAppt[0].className);
                    daysDiff = (curDayStart.getTime() - _toDayDate(appt.start).getTime()) / (1000 * 60 * 60 * 24);
                    appt.start = this._addDays(appt.start, daysDiff);
                    appt.end = this._addDays(appt.end, daysDiff);
                    this.updateEvent(appt);
                }
            };

            wijevcal.prototype._onDayViewAllDayMouseOver = function (e) {
                if (this._isDisabled()) {
                    return;
                }
                var targetCol = $(e.target).parents(".wijmo-wijev-dayheadercolumn"), sourceCol = this.__targetAppt.parents(".wijmo-wijev-daycolumn"), newVisual;
                if (targetCol.length < 1) {
                    return;
                }
                if (sourceCol.length > 0) {
                    // update appointment element
                    // move from time interval to all day cell
                    newVisual = $(this._getAllDayEventMarkup(this.findEventById(this.__targetAppt[0].className)));

                    // fix for 25070 case 2:
                    this._movedFromTimeInervalApptElem = this.__targetAppt[0].cloneNode(true);

                    this.__targetAppt.replaceWith(newVisual);
                    this.__targetAppt = newVisual;
                } else {
                    // move from all day cell to another all day cell
                    sourceCol = this.__targetAppt.parents(".wijmo-wijev-dayheadercolumn");
                }
                if (sourceCol.length < 1) {
                    return;
                }
                if (targetCol[0].className !== sourceCol[0].className) {
                    this.__targetAppt[0].parentNode.removeChild(this.__targetAppt[0]);
                    this._resolveDayViewAppointmentConflicts(sourceCol);
                    this.__targetAppt.appendTo($(targetCol).find(".wijmo-wijev-allday-cell"));
                    this._apptMovedFlag = true;
                }
            };

            // <-
            wijevcal.prototype._getMonthGrid = function (date) {
                var self = this, o = self.options, rows = 3, cols = 4, monthGrid, year, i, j, index, cellText, currentDate;

                monthGrid = "<div class = 'wijmo-wijev-yearview-inner'>";
                year = date.getFullYear();

                for (i = 0; i < rows; i++) {
                    monthGrid += "<div>";
                    for (j = 0; j < cols; j++) {
                        index = i * 4 + j;
                        currentDate = new Date(year, index);
                        cellText = self._formatString(self.localizeString("customYearViewMonthFormat", "{0:MMM}"), currentDate);
                        monthGrid += self._generateMonthCell(currentDate, cellText);
                    }
                    monthGrid += "</div>";
                }
                monthGrid += "</div>";
                return monthGrid.toString();
            };

            wijevcal.prototype._generateMonthCell = function (date, cellText) {
                var o = this.options;
                return "<div class = '" + o.wijCSS.content + " wijmo-wijev-yearcellcontainer" + " wijmo-wijev-month_" + date.getFullYear() + "_" + date.getMonth() + "_1'>" + "<div class = 'wijmo-wijev-yearcellheader'>" + cellText + "</div>" + "<div  class = 'wijmo-wijev-yearcell'>" + "</div>" + "</div>";
            };

            wijevcal.prototype._getSuperPanelScrollPosition = function (superPanel) {
                if (superPanel.data("wijmoWijsuperpanel")) {
                    return superPanel.length === 0 ? 0 : superPanel.wijsuperpanel("option", "vScroller").scrollValue;
                }
                return 0;
            };

            wijevcal.prototype._renderYearView = function () {
                var self = this, o = self.options, yearView = self.element.find(".wijmo-wijev-view.wijmo-wijev-yearview"), yearViewInner, superPanel, superPanelContent, yearIndex, currentDate, viewIndex = self._getCurrentViewIndex(), isCustomView = self._isCustomView(), yearCount = o.views[viewIndex].count || 1, scrollPosition, shouldRenderSuperPanel = isCustomView && yearCount > 1;
                if (shouldRenderSuperPanel) {
                    scrollPosition = self._getSuperPanelScrollPosition(yearView.find(".wijmo-wijev-panel"));
                }
                if (yearView.length === 0) {
                    yearView = $("<div class=\"wijmo-wijev-view wijmo-wijev-yearview " + o.wijCSS.content + "\">" + "</div>");
                    yearView.appendTo(this.element.find(".wijmo-wijev-view-container"));
                }
                yearView.empty();
                yearView.append($("<h3 class=\"wijmo-wijev-header-title\">title</h3>"));
                superPanel = $("<div class = \"wijmo-wijev-panel\"></div>");
                superPanelContent = $("<div id = \"wijmo-wijev-content\"></div>");
                superPanel.append(superPanelContent);
                yearView.append(superPanel);
                for (yearIndex = 0; yearIndex < yearCount; yearIndex++) {
                    currentDate = new Date(o.selectedDate.getFullYear() + yearIndex, o.selectedDate.getMonth(), 1);

                    if (shouldRenderSuperPanel) {
                        superPanelContent.append($("<h5 class=\"wijmo-wijev-year-title\">" + this._formatString(this.localizeString("customYearViewSecondTitleFormat", "{0:yyyy}"), currentDate) + "</h5>"));
                    }
                    yearViewInner = $(this._getMonthGrid(currentDate));
                    superPanelContent.append(yearViewInner);
                }

                if (shouldRenderSuperPanel) {
                    superPanel.wijsuperpanel({
                        hScroller: { scrollBarVisibility: "hidden" },
                        vScroller: { scrollValue: scrollPosition },
                        animationOptions: { disabled: true }
                    });
                }

                this._invalidateYearView();
                this._renderYearViewAppointments();
            };

            wijevcal.prototype._renderYearViewAppointments = function () {
                var appts = this._eventsView, appt, i, j, apptsCount, yearcellcontainers = this.element.find(".wijmo-wijev-yearcellcontainer"), yearcellcontainer, curDayStart, curDayEnd, apptVisual;
                if (appts) {
                    for (j = 0; j < yearcellcontainers.length; j++) {
                        yearcellcontainer = yearcellcontainers[j];
                        curDayStart = this._parseDateFromClass(yearcellcontainer.className);
                        curDayEnd = new Date(curDayStart.getFullYear(), curDayStart.getMonth() + 1, 0, 23, 59, 59);
                        for (i = 0, apptsCount = appts.length; i < apptsCount; i += 1) {
                            appt = appts[i];
                            if ((appt.start < curDayEnd && appt.end > curDayStart)) {
                                apptVisual = $("<div class=\"wijmo-wijev-appointment " + this._eventIdToCssClass(appt.id) + "\">" + "<div class=\"" + " wijmo-wijev-colordot wijmo-wijev-event-color-" + (appt.color || "default") + "\"></div>" + "<div class=\"wijmo-wijev-event-title\">" + appt.subject + "</div>" + "</div>");

                                $(yearcellcontainer).find(".wijmo-wijev-yearcell").append(apptVisual);
                            }
                        }
                    }
                }

                // display "show more..." if needed:
                yearcellcontainers.find(".wijmo-wijev-yearcell").each($.proxy(function (i, el) {
                    var yearcell = $(el), apps = yearcell.find(".wijmo-wijev-appointment"), monthcellH = yearcell.outerHeight(), appH = apps.outerHeight(), appsH = apps.length * appH, hiddenCount = 0;

                    if (appsH > monthcellH) {
                        apps.each(function (j, a) {
                            if ((j * appH + appH) > monthcellH) {
                                a["style"].display = "none";
                                hiddenCount += 1;
                            }
                        });
                        if (hiddenCount > 0) {
                            if (yearcell.find(".wijmo-wijev-yearcell-showmore").length < 1) {
                                yearcell.append($("<div class=\"wijmo-wijev-yearcell-showmore\">" + this._formatString(this.localizeString("yearCellMoreEventsFormat", "{0}  more..."), hiddenCount) + "</div>"));
                            }
                        }
                    }
                }, this));

                this._renderComplete();
            };

            wijevcal.prototype._invalidateYearView = function () {
                var self = this, o = self.options, yearView = self.element.find(".wijmo-wijev-yearview"), yearCellContainers = yearView.find(".wijmo-wijev-yearcellcontainer"), yearViewInner = yearView.find(".wijmo-wijev-yearview-inner"), superPanel = yearView.find(".wijmo-wijev-panel"), title = self.element.find(".wijmo-wijev-yearview .wijmo-wijev-header-title"), viewIndex = self._getCurrentViewIndex(), yearcellcontainerH, monthCellH, yearHeaderH, viewWidth, viewHeight;

                self._updateHeaderTitleText(); // ensure header title visibility
                self._invalidateView();
                viewWidth = yearView.innerWidth();
                viewHeight = yearView.innerHeight() - title.outerHeight(true);
                superPanel.width(viewWidth);
                superPanel.height(viewHeight);
                if (self._isCustomView() && o.views[viewIndex].count > 1) {
                    //remove the width of scrollbar
                    viewWidth -= 18;
                }
                yearViewInner.outerWidth(viewWidth);
                yearViewInner.outerHeight(viewHeight);
                viewWidth = viewWidth - (yearViewInner.outerWidth(true) - yearViewInner.innerWidth());
                viewHeight = viewHeight - (yearViewInner.outerHeight(true) - yearViewInner.innerHeight());

                yearCellContainers.outerWidth(Math.ceil(viewWidth / 4));
                yearCellContainers.outerHeight(Math.ceil(viewHeight / 3));
                yearcellcontainerH = yearCellContainers.height();
                yearHeaderH = $(yearCellContainers[0]).find(".wijmo-wijev-yearcellheader").outerHeight(true);

                monthCellH = yearcellcontainerH - yearHeaderH;
                yearCellContainers.find(".wijmo-wijev-yearcell").outerHeight(monthCellH);

                if (self._isCustomView() && o.views[viewIndex].count > 1) {
                    self._refreshSuperPanel(superPanel);
                }
            };

            /* MONTH view */
            wijevcal.prototype._renderMonthView = function () {
                var self = this, o = self.options, selectedDate = o.selectedDate, firstDayOfWeek = o.firstDayOfWeek, isToday = false, isOtherMonth = false, curDate, startDate, endDate, todayDate = new Date(), curColumnInd, curRowInd, skipNextBorder = false, containerClass, s, i, j, columnData, viewIndex = self._getCurrentViewIndex(), isCustomView = self._isCustomView(), monthCount = isCustomView ? o.views[viewIndex].count : 1, monthIndex, sColsList = [], currentDate, superPanel, superPanelContent, monthview = self.element.find(".wijmo-wijev-view.wijmo-wijev-monthview"), monthviewinner, dayHeaderFormat = o.dayHeaderFormat, firstRowDayHeaderFormat = o.firstRowDayHeaderFormat, scrollPosition, shouldRenderSuperPanel = isCustomView && monthCount > 1;
                if (shouldRenderSuperPanel) {
                    scrollPosition = self._getSuperPanelScrollPosition(monthview.find(".wijmo-wijev-panel"));
                }
                if (!selectedDate) {
                    selectedDate = new Date();
                }

                for (monthIndex = 0; monthIndex < monthCount; monthIndex++) {
                    currentDate = startDate = new Date(selectedDate.getFullYear(), selectedDate.getMonth() + monthIndex, 1);
                    columnData = { startDate: startDate, data: ["", "", "", "", "", "", ""] };
                    while (startDate.getDay() !== parseInt(firstDayOfWeek)) {
                        startDate = this._addDays(startDate, -1);
                    }
                    endDate = new Date(selectedDate.getFullYear(), selectedDate.getMonth() + monthIndex, self._daysInMonth(selectedDate.getMonth() + monthIndex, selectedDate.getFullYear()));

                    curDate = startDate;
                    curColumnInd = 0;
                    curRowInd = 0;

                    while (curDate < endDate || curColumnInd < 7) {
                        if (curDate > endDate) {
                            endDate = curDate;
                        }
                        s = "";
                        containerClass = "wijmo-wijev-monthcellcontainer " + o.wijCSS.content + " " + self._dayDateToCssClass(curDate);
                        isOtherMonth = curDate.getMonth() !== currentDate.getMonth() || curDate.getFullYear() !== currentDate.getFullYear();
                        if (isOtherMonth) {
                            // ui-priority-secondary
                            containerClass += " wijmo-wijev-othermonth";
                        }
                        if (skipNextBorder) {
                            skipNextBorder = false;
                        } else {
                            containerClass += " wijmo-wijev-leftborder";
                            if (curColumnInd === 6) {
                                containerClass += " wijmo-wijev-rightborder";
                            }
                        }
                        isToday = self._compareDayDates(curDate, todayDate) === 0;
                        if (isToday) {
                            // ui-state-highlight
                            containerClass += " wijmo-wijev-today";
                            containerClass += " wijmo-wijev-rightborder";
                            skipNextBorder = true;
                        }
                        s += "<div class=\"" + containerClass + "\">";
                        s += "<div class=\"wijmo-wijev-monthcellheader";
                        if (isOtherMonth) {
                            //s += " ui-priority-secondary";
                            s += " " + o.wijCSS.prioritySecondary;
                        }
                        if (isToday) {
                            //s += " ui-state-highlight";
                            s += " " + o.wijCSS.stateHighlight;
                        }
                        s += "\">";

                        if (isToday) {
                            s += "<span class=\"wijmo-wijev-todaylabel\">" + this.localizeString("labelToday", "Today") + "</span>";
                        }

                        if (curRowInd === 0) {
                            s += self._formatString(firstRowDayHeaderFormat, curDate);
                        } else {
                            s += self._formatString(dayHeaderFormat, curDate);
                        }
                        s += "</div>";
                        s += "<div class=\"wijmo-wijev-monthcell";

                        if (isOtherMonth) {
                            //s += " ui-priority-secondary";
                            s += " " + o.wijCSS.prioritySecondary;
                        }
                        if (isToday) {
                            //s += " ui-state-highlight";
                            s += " " + o.wijCSS.stateHighlight;
                        }

                        s += "\"></div>";
                        s += "</div>";
                        columnData.data[curColumnInd] = columnData.data[curColumnInd] + s;
                        curColumnInd += 1;
                        curDate = self._addDays(curDate, 1);
                        if (curColumnInd > 6) {
                            if (curDate > endDate) {
                                break;
                            }
                            curColumnInd = 0;
                            curRowInd += 1;
                        }
                    }
                    sColsList.push(columnData);
                }

                if (monthview.length === 0) {
                    monthview = $("<div class=\"wijmo-wijev-view wijmo-wijev-monthview " + o.wijCSS.content + "\">" + "</div>");
                    monthview.appendTo(self.element.find(".wijmo-wijev-view-container"));
                }
                monthview.empty();
                monthview.append($("<h3 class=\"wijmo-wijev-header-title\">title</h3>"));
                superPanel = $("<div class = \"wijmo-wijev-panel\"></div>");
                superPanelContent = $("<div id = \"wijmo-wijev-content\"></div>");
                superPanel.append(superPanelContent);
                monthview.append(superPanel);
                for (i = 0; i < sColsList.length; i++) {
                    if (shouldRenderSuperPanel) {
                        superPanelContent.append($("<h5 class=\"wijmo-wijev-month-title\">" + self._formatString(self.localizeString("customMonthViewSecondTitleFormat", "{0:MMM}"), sColsList[i].startDate) + "</h5>"));
                    }
                    monthviewinner = $("<div class=\"wijmo-wijev-monthview-inner\"></div>");
                    superPanelContent.append(monthviewinner);

                    for (j = 0; j < 7; j += 1) {
                        monthviewinner.append("<div class=\"wijmo-wijev-monthcolumn\">" + sColsList[i].data[j] + "</div>");
                    }
                }
                if (shouldRenderSuperPanel) {
                    superPanel.wijsuperpanel({
                        hScroller: { scrollBarVisibility: "hidden" },
                        vScroller: { scrollValue: scrollPosition },
                        animationOptions: { disabled: true }
                    });
                }

                self._invalidateMonthView();
                self._renderMonthViewAppointments();
            };

            wijevcal.prototype._invalidateMonthView = function () {
                var self = this, o = self.options, monthview = self.element.find(".wijmo-wijev-monthview"), monthviewinner = monthview.find(".wijmo-wijev-monthview-inner"), monthColumns = monthviewinner.find(".wijmo-wijev-monthcolumn"), superPanel = monthview.find(".wijmo-wijev-panel"), title = self.element.find(".wijmo-wijev-monthview .wijmo-wijev-header-title"), viewWidth, viewHeight, columnOuterWidth, monthcellcontainerH, monthHeaderH, monthCellH, weekdaynameH, viewIndex = self._getCurrentViewIndex(), diff;

                self._updateHeaderTitleText(); // ensure header title visibility
                self._invalidateView();
                if (monthColumns.length < 1) {
                    return;
                }
                viewWidth = monthview.innerWidth();
                viewHeight = monthview.innerHeight() - title.outerHeight(true);
                superPanel.width(viewWidth);
                superPanel.height(viewHeight);
                if (self._isCustomView() && o.views[viewIndex].count > 1) {
                    //remove the width of scrollbar
                    viewWidth -= 18;
                }
                monthviewinner.outerWidth(viewWidth);
                monthviewinner.outerHeight(viewHeight);

                viewWidth = viewWidth - (monthviewinner.outerWidth(true) - monthviewinner.innerWidth());
                viewHeight = viewHeight - (monthviewinner.outerHeight(true) - monthviewinner.innerHeight());

                columnOuterWidth = Math.floor(viewWidth / (monthColumns.length / monthviewinner.length));
                monthColumns.outerWidth(columnOuterWidth);
                diff = viewWidth - columnOuterWidth * monthColumns.length;
                if (diff > 0) {
                    $(monthColumns[monthColumns.length - 1]).outerWidth(columnOuterWidth + diff);
                }

                weekdaynameH = $(monthColumns[0]).find(".wijmo-wijev-weekdayname").outerHeight(true);
                if (!weekdaynameH) {
                    //(20120830) fix for 27354(regression issue?):
                    weekdaynameH = 0;
                }

                // every month should display for a whole inner view.
                $.each(monthviewinner, function (index, ele) {
                    var monthInner = $(ele), singleMonthCellContainers = monthInner.find(".wijmo-wijev-monthcellcontainer");
                    monthcellcontainerH = Math.floor((viewHeight - weekdaynameH) / monthInner.find(".wijmo-wijev-monthcolumn").eq(0).find(".wijmo-wijev-monthcellcontainer").length);
                    singleMonthCellContainers.outerHeight(monthcellcontainerH);

                    monthHeaderH = $(singleMonthCellContainers[0]).find(".wijmo-wijev-monthcellheader").outerHeight(true);

                    monthCellH = monthcellcontainerH - monthHeaderH;
                    singleMonthCellContainers.find(".wijmo-wijev-monthcell").outerHeight(monthCellH);
                });

                if (self._isCustomView() && o.views[viewIndex].count > 1) {
                    this._refreshSuperPanel(superPanel);
                }
            };

            wijevcal.prototype._renderMonthViewAppointments = function () {
                var appts = this._eventsView, appt, i, j, apptsCount, daysCount, monthcellcontainers = this.element.find(".wijmo-wijev-monthcellcontainer"), monthcellcontainer, curDayStart, curDayEnd, apptVisual;
                if (appts) {
                    for (j = 0, daysCount = monthcellcontainers.length; j < daysCount; j += 1) {
                        monthcellcontainer = monthcellcontainers[j];
                        curDayStart = this._parseDateFromClass(monthcellcontainer.className);
                        curDayEnd = new Date(curDayStart.getFullYear(), curDayStart.getMonth(), curDayStart.getDate(), 23, 59, 59);
                        for (i = 0, apptsCount = appts.length; i < apptsCount; i += 1) {
                            appt = appts[i];
                            if ((appt.start < curDayEnd && appt.end > curDayStart)) {
                                apptVisual = $("<div class=\"wijmo-wijev-appointment " + this._eventIdToCssClass(appt.id) + "\">" + "<div class=\"" + " wijmo-wijev-colordot wijmo-wijev-event-color-" + (appt.color || "default") + "\"></div>" + "<div class=\"wijmo-wijev-event-title\">" + appt.subject + "</div>" + "</div>");

                                $(monthcellcontainer).find(".wijmo-wijev-monthcell").append(apptVisual);
                            }
                        }
                    }
                }

                // display "show more..." if needed:
                monthcellcontainers.find(".wijmo-wijev-monthcell").each($.proxy(function (i, el) {
                    var monthcell = $(el), apps = monthcell.find(".wijmo-wijev-appointment"), monthcellH = monthcell.outerHeight(), appH = apps.outerHeight(), appsH = apps.length * appH, hiddenCount = 0;

                    if (appsH > monthcellH) {
                        apps.each(function (j, a) {
                            if ((j * appH + appH) > monthcellH) {
                                a["style"].display = "none";
                                hiddenCount += 1;
                            }
                        });
                        if (hiddenCount > 0) {
                            if (monthcell.find(".wijmo-wijev-monthcell-showmore").length < 1) {
                                monthcell.append($("<div class=\"wijmo-wijev-monthcell-showmore\">" + this._formatString(this.localizeString("monthCellMoreEventsFormat", "{0}  more..."), hiddenCount) + "</div>"));
                            }
                        }
                    }
                }, this));

                this._renderComplete();
            };

            /**  Sends a log message to built-in log console.
            * Note: n order to use this method, you must set the enableLogs option to true.
            * @param {string} msg Log message.
            * @param {string} className
            * Optional. CSS class name that will be applied to the destination message.
            * Few predefined classes are available:
            * "error", "warning", "information", "status"
            */
            wijevcal.prototype.log = function (msg, className) {
            };

            wijevcal.prototype._log = function (msg, className) {
                var dt;
                if (this.logPanel) {
                    dt = new Date();
                    this.logPanel.prepend($('<span class="' + (className ? className : "wijmo-wijev-information") + '">' + '[' + dt.getHours() + ':' + dt.getMinutes() + ':' + dt.getSeconds() + '] ' + msg + '</span><br/>'));
                }
            };

            wijevcal.prototype._createLogPanel = function () {
                if (!this.logPanel) {
                    this.logDialog = $('<div title="Log">' + '<div class="wijmo-wijev-log"></div></div>');
                    this.logDialog.appendTo(this.element);
                    var btnsHash = {};
                    btnsHash[this.localizeString("buttonClearAll", "Clear All")] = function () {
                        $(this).find(".wijmo-wijev-log").html("");
                    };
                    btnsHash[this.localizeString("buttonClose", "Close")] = function () {
                        $(this).wijdialog("close");
                    };
                    this.logPanel = this.logDialog.wijdialog({
                        captionButtons: {},
                        buttons: btnsHash,
                        width: 600, height: 420,
                        position: ["right", "top"]
                    }).find(".wijmo-wijev-log");
                }
                this.logDialog.wijdialog("open");
            };

            /**
            * Changes status label text.
            * @param {string} txt The new status text.
            */
            wijevcal.prototype.status = function (txt, className) {
                this.element.find(".wijmo-wijev-statusbar").html("<span class='" + (className ? className : "wijmo-wijev-status") + "'>" + txt + "</span>");
                this.log(txt, className ? className : "wijmo-wijev-status");
                if (!this.statusbarEventsAdded) {
                    this.statusbarEventsAdded = true;
                    this._initStatusbar();
                }
            };

            //<--
            /* common view code */
            wijevcal.prototype._invalidateView = function () {
                var rightPane = this.element.find(".wijmo-wijev-rightpane"), leftPane = this.element.find(".wijmo-wijev-leftpane"), header = this.element.find(".wijmo-wijev-headerbar"), navigationbar = this.element.find(".wijmo-wijev-navigationbar"), footer = this.element.find(".wijmo-wijev-statusbar"), viewContainer = this.element.find(".wijmo-wijev-view-container"), view = this.element.find(".wijmo-wijev-view"), elemInnerW, elemInnerH, headerH, navigationbarH, footerH, viewHeight, viewWidth, leftPaneW, rightPaneW, i;

                elemInnerW = this.element.innerWidth() - (viewContainer.outerWidth(true) - viewContainer.innerWidth());
                elemInnerH = this.element.innerHeight() - (viewContainer.outerHeight(true) - viewContainer.innerHeight());

                headerH = header.is(":visible") ? header.outerHeight(true) : 0;
                navigationbarH = navigationbar.is(":visible") ? navigationbar.outerHeight(true) : 0;
                footerH = footer.is(":visible") ? footer.outerHeight(true) : 0;

                viewContainer.outerWidth(elemInnerW);
                viewContainer.outerHeight(elemInnerH - headerH - navigationbarH - footerH);

                leftPaneW = 0;
                for (i = 0; i < leftPane.length; i += 1) {
                    if ($(leftPane[i]).is(":visible")) {
                        leftPaneW += $(leftPane[i]).outerWidth();
                    }
                }
                rightPaneW = rightPane.is(":visible") ? rightPane.outerWidth() : 0;

                viewHeight = elemInnerH - headerH - navigationbarH - footerH;

                // -1 is fix for [29300] [JPN issue]
                // [Sample][EventCalendar]List view of EventCalendar gets control desorted
                viewWidth = elemInnerW - rightPaneW - leftPaneW - 1;

                //alert("leftPaneW=" + leftPaneW + ",viewWidth=" + viewWidth);
                view.outerHeight(viewHeight);
                view.outerWidth(viewWidth);

                header.outerWidth(viewWidth + leftPaneW);
                navigationbar.outerWidth(this.element.innerWidth());

                footer.outerWidth(viewWidth + leftPaneW + rightPaneW);
                leftPane.outerHeight(elemInnerH - headerH - navigationbarH - footerH);

                /*
                //agendaContainer invalidated later(fix for 21282) when date label text is changed.
                agendaContainer.outerHeight(leftPane.innerHeight() -
                agendaContainer[0].offsetTop);
                */
                rightPane.outerHeight(elemInnerH + 100);

                this.element.find(".wijmo-wijev-datepager").wijdatepager("refresh");
            };

            //<-
            // util methods:
            // note, month is zero-based(0-11)
            wijevcal.prototype._daysInMonth = function (month, year) {
                var dd = new Date(year, month + 1, 0);
                return dd.getDate();
            };
            wijevcal.prototype._addMinutes = function (dt, num) {
                return new Date(dt.getFullYear(), dt.getMonth(), dt.getDate(), dt.getHours(), dt.getMinutes() + num);
            };
            wijevcal.prototype._addDays = function (dt, num) {
                return new Date(dt.getFullYear(), dt.getMonth(), dt.getDate() + num, dt.getHours(), dt.getMinutes(), dt.getSeconds(), dt.getMilliseconds());
            };
            wijevcal.prototype._addYears = function (dt, num) {
                return new Date(dt.getFullYear() + num, dt.getMonth(), dt.getDate(), dt.getHours(), dt.getMinutes(), dt.getSeconds(), dt.getMilliseconds());
            };
            wijevcal.prototype._setTime = function (dt, timePart, daysTestPart) {
                var daysDuration;
                dt = new Date(dt);
                dt.setHours(timePart.getHours());
                dt.setMinutes(timePart.getMinutes());
                dt.setSeconds(timePart.getSeconds());
                dt.setMilliseconds(timePart.getMilliseconds());
                if (daysTestPart) {
                    daysDuration = Math.floor((timePart.getTime() - daysTestPart.getTime()) / (1000 * 60 * 60 * 24));
                    if (daysDuration > 0) {
                        dt = this._addDays(dt, daysDuration);
                    }
                }
                return dt;
            };
            wijevcal.prototype._addMonths = function (dt, num) {
                return new Date(dt.getFullYear(), dt.getMonth() + num, dt.getDate());
            };
            wijevcal.prototype._compareDayDates = function (dt1, dt2) {
                dt1 = new Date(dt1.getFullYear(), dt1.getMonth(), dt1.getDate());
                dt2 = new Date(dt2.getFullYear(), dt2.getMonth(), dt2.getDate());
                if (dt1 < dt2) {
                    return -1;
                } else if (dt1 > dt2) {
                    return 1;
                }
                return 0;
            };
            wijevcal.prototype._dayDateToCssClass = function (dt) {
                return "wijmo-wijev-date_" + dt.getFullYear() + "_" + dt.getMonth() + "_" + dt.getDate();
            };
            wijevcal.prototype._parseDateFromClass = function (dateClass, minuteClass, defaultVal) {
                var dt, min, datearr, classArr, minregexp = new RegExp("wijmo-wijev-minute-(\\d+)\\s"), dateregexp = new RegExp("wijmo-wijev-date_(\\d+_\\d+_\\d+)\\s"), monthregexp = new RegExp("wijmo-wijev-month_(\\d+_\\d+_\\d+)\\s");
                if (dateClass) {
                    classArr = dateregexp.exec(dateClass + " ");
                    if (!classArr) {
                        classArr = monthregexp.exec(dateClass + " ");
                    }
                    datearr = classArr[1].split("_");
                    dt = new Date(parseInt(datearr[0], 10), parseInt(datearr[1], 10), parseInt(datearr[2], 10));
                    if (minuteClass) {
                        min = minregexp.exec(minuteClass + " ");
                        if (min) {
                            min = parseInt(min[1], 10);
                            dt.setMinutes(min);
                        }
                    }
                    return dt;
                } else {
                    return defaultVal || null;
                }
            };
            wijevcal.prototype._eventIdToCssClass = function (id) {
                return "apptid_" + id;
            };
            wijevcal.prototype._parseEventIdFromClass = function (cssClass) {
                var id = "", regexp, match;
                regexp = new RegExp("apptid_(\\S+)");
                match = regexp.exec(cssClass);
                if (match && match.length > 1) {
                    id = match[1];
                }
                return id;
            };
            wijevcal.prototype._isContainsDayDate = function (arr, dt) {
                var i;
                if (arr) {
                    for (i = 0; i < arr.length; i += 1) {
                        if (this._compareDayDates(arr[i], dt) === 0) {
                            return true;
                        }
                    }
                } else {
                    return false;
                }
            };

            //format:
            wijevcal.prototype._formatString = function (fmt, arg0, arg1, arg2, arg3, arg4, arg5, arg6) {
                var r, args = arguments, i, funcArgs, self = this;
                if (args.length <= 1) {
                    return Globalize.format(args);
                }
                if (typeof fmt === "string") {
                    if (fmt === "_formatWeekTitle") {
                        fmt = this._formatWeekTitle;
                    } else if (fmt === "_formatMonthTitle") {
                        fmt = this._formatMonthTitle;
                    } else if (fmt === "_formatCustomTitle") {
                        fmt = this._formatCustomTitle;
                    } else if (typeof window[fmt] === "function") {
                        fmt = window[fmt];
                    }
                }
                if (typeof fmt === "function") {
                    funcArgs = [];
                    for (i = 1; i < args.length; i += 1) {
                        funcArgs[i - 1] = args[i];
                    }
                    return fmt.apply(this, funcArgs);
                }
                r = new RegExp("\\{(\\d+)(?:,([-+]?\\d+))?(?:\\:" + "([^(^}]+)(?:\\(((?:\\\\\\)|[^)])+)\\)){0,1}){0,1}\\}", "g");
                return fmt.replace(r, function (m, num, len, f, params) {
                    m = args[Number(num) + 1];
                    if (f) {
                        return Globalize.format(m, f, self._getCulture());
                    } else {
                        return m;
                    }
                });
            };
            wijevcal.prototype._formatMonthTitle = function (dt) {
                return this._formatString(this.localizeString("monthViewHeaderFormat", "{0:MMMM yyyy}"), dt);
            };

            wijevcal.prototype._formatCustomTitle = function (start, end) {
                var self = this, o = self.options, viewIndex = self._getCurrentViewIndex(), isSingleUnit = o.views[viewIndex].count === 1;
                switch (this._getCustomViewUnit()) {
                    case "day":
                        return isSingleUnit ? self._formatString(self.localizeString("customSingleWeekViewHeaderFormat", "{0:d}"), start, end) : self._formatString(self.localizeString("customWeekViewHeaderFormat", "{0:d} - {1:d}"), start, end);
                    case "week":
                        return self._formatString(self.localizeString("customWeekViewHeaderFormat", "{0:d} - {1:d}"), start, end);
                    case "month":
                        return isSingleUnit ? self._formatString(self.localizeString("customSingleMonthViewHeaderFormat", "{0:MMMM yyyy}"), start, end) : self._formatString(self.localizeString("customMonthViewHeaderFormat", "{0:MMMM yyyy} - {1:MMMM yyyy}"), start, end);
                    case "year":
                        return isSingleUnit ? self._formatString(self.localizeString("customSingleYearViewHeaderFormat", "{0:yyyy}"), start, end) : self._formatString(self.localizeString("customYearViewHeaderFormat", "{0:yyyy} - {1:yyyy}"), start, end);
                }
            };

            wijevcal.prototype._formatWeekTitle = function (start, end) {
                if (start.getMonth() !== end.getMonth()) {
                    return this._formatString(this.localizeString("weekViewHeaderFormat2Months", "{0:MMMM} - {1:MMMM yyyy}"), start, end);
                } else {
                    return this._formatString(this.localizeString("weekViewHeaderFormat", "{0:MMMM yyyy}"), start);
                }
            };

            // format date/time:
            wijevcal.prototype._formatDayHeaderDate = function (dt) {
                var self = this, o = self.options, viewType = self._isCustomView() ? "custom" : o.viewType.toLowerCase(), dayViewHeaderFormat = self.options.dayViewHeaderFormat;
                if (dayViewHeaderFormat[viewType]) {
                    dayViewHeaderFormat = dayViewHeaderFormat[viewType];
                } else if (!dayViewHeaderFormat[viewType]) {
                    return "";
                }

                //return Globalize.format(date, format, this._getCulture());
                return self._formatString(dayViewHeaderFormat, dt);
            };

            wijevcal.prototype._getCulture = function (name) {
                if (!this._innerCulture) {
                    this._resetCulture(name);
                }
                return this._innerCulture;
            };
            wijevcal.prototype._resetCulture = function (culture) {
                var cal = $.wijGetCulture(culture || this.options.culture, this.options.cultureCalendar);
                this._innerCulture = cal;
            };
            wijevcal.prototype._isRTL = function () {
                return !!this._getCulture().isRTL;
            };

            //<--
            wijevcal.prototype._onAjaxError = function (event, jqXHR, ajaxSettings, thrownError) {
                if (jqXHR) {
                    this.status("Ajax error " + jqXHR.status + " (" + jqXHR.statusText + ")", "error");
                    this.log("Error, requested url: " + ajaxSettings.url, "error");
                    if (jqXHR.responseText) {
                        this.log("Error, response text: " + jqXHR.responseText, "error");
                    }
                } else {
                    this.status("Ajax error detected.", "error");
                    this.log("Error, requested url: " + ajaxSettings.url, "error");
                }
            };
            wijevcal.prototype._onWindowResize = function () {
                this.invalidate();
            };
            return wijevcal;
        })(wijmo.wijmoWidget);
        evcal.wijevcal = wijevcal;

        var wijevcal_options = (function () {
            function wijevcal_options() {
                /** wijMobileCSS
                * @ignore
                */
                this.wijMobileCSS = {
                    header: "ui-header ui-bar-a",
                    content: "ui-body ui-body-b",
                    stateDefault: "ui-btn ui-btn-b"
                };
                /** Selector option for auto self initialization.
                * This option is internal.
                * @ignore
                */
                this.initSelector = ":jqmData(role='wijevcal')";
                /** Determines the culture to be used, for example, "de-DE" is German.
                * Date and time formatting depends on the culture option.
                */
                this.culture = "";
                /** Determines the culture calendar to be used. This option must work with culture option. */
                this.cultureCalendar = "";
                /** Use the localization option in order to localize
                * text which not depends on culture option.
                * @default {
                * messageEndOccursBeforeStart: "The end date you entered occurs before the start date.",
                * activityLoading: "Loading...",
                * activityDeletingCalendar: "Deleting calendar...",
                * activityCreatingCalendar: "Creating calendar...",
                * activityUpdatingCalendar: "Updating calendar...",
                * activityCreatingEvent: "Creating event...",
                * activityUpdatingEvent: "Updating event...",
                * activityDeletingEvent: "Deleting event...",
                * activityUpdating: "Updating...",
                * agendaLoadingMoreEvents: "Loading more events...",
                * agendaMoreEventsFormat: "More events ({0})...", // (0) - Number, invisible events count
                * agendaTimeFormat: "{0:hh:mm tt} to {1:hh:mm tt}", // {0} Date, event start time, {1} - Date, event end time
                * buttonToday: "today",
                * buttonDayView: "Day",
                * buttonWeekView: "Week",
                * buttonMonthView: "Month",
                * buttonListView: "List",
                * customView: "Custom"
                * buttonDelete: "Delete",
                * buttonOK: "OK",
                * buttonCancel: "Cancel",
                * calendarNextTooltip: "Next",
                * calendarPrevTooltip: "Previous",
                * navigatorBarNextTooltip: "right",
                * navigatorBarPrevTooltip: "left",
                * labelAllDay: "all-day",
                * labelToday: "Today",
                * labelName: "name",
                * labelStarts: "starts",
                * labelEnds: "ends",
                * labelLocation: "location",
                * labelRepeat: "repeat",
                * labelCalendar: "calendar",
                * labelDescription: "description",
                * monthCellMoreEventsFormat: "{0}  more...", // (0) - Number, invisible events count,
                * yearCellMoreEventsFormat: "{0}  more...", // (0) - Number, invisible events count,
                * promptOpenOccurrenceFormat: "{2}  is recurring event. Do you want to open only this occurrence?", // {0} = Start, {1} = End, {2} = Subject, {3} = Location
                * textNewEvent: "New event",
                * repeatNone: "None",
                * repeatDaily: "Every Day",
                * repeatWorkDays: "Work days",
                * repeatWeekly: "Every Week",
                * repeatMonthly: "Every Month",
                * repeatYearly: "Every Year",
                * labelCalendarName: "Calendar name",
                * labelColor: "Color",
                * buttonSave: "Save",
                * titleEditCalendar: "Edit calendar",
                * calendarToolTipFormat: "dddd, MMMM dd, yyyy",
                * calendarTitleFormat: "MMMM yyyy",
                * dayDetailsLabelFulldateFormat: "{0:dddd, MMMM d}",
                * dayDetailsLabelYearFormat: "{0:yyyy}",
                * weekViewHeaderFormat2Months: "{0:MMMM} - {1:MMMM yyyy}",
                * weekViewHeaderFormat: "{0:MMMM yyyy}",
                * customSingleWeekViewHeaderFormat: "{0:d}",
                * customWeekViewHeaderFormat, "{0:d} - {1:d}",
                * customYearViewSecondTitleFormat, "{0:yyyy}",
                * customMonthViewSecondTitleFormat, "{0:MMM}",
                * customSingleMonthViewHeaderFormat, "{0:MMMM yyyy}",
                * customMonthViewHeaderFormat, "{0:MMMM yyyy} - {1:MMMM yyyy}"),
                * customSingleYearViewHeaderFormat: "{0:yyyy}",
                * customYearViewHeaderFormat, "{0:yyyy} - {1:yyyy}",
                * customYearViewMonthFormat, "{0:MMM}",
                * monthViewHeaderFormat: "{0:MMMM yyyy}",
                * agendaHeaderFullDateFormat: "{0:MMMM d, yyyy}",
                * logCouldntOpenLocalStorage: "Couldn't open built-in local data storage. Please, add amplify.store references.",
                * buttonClearAll: "Clear All",
                * buttonClose: "Close"
                * }
                * @type {object}
                * @example $("#eventscalendar").wijevcal(
                *   {
                *       localization: {
                *       buttonToday: "Go today",
                *       buttonListView: "Agenda"
                *   }
                * });
                */
                this.localization = null;
                /** Use the datePagerLocalization option in order to localize
                * bottom date pager.
                * @ignore
                */
                this.datePagerLocalization = null;
                /** Set this option to true if you want to prevent users to edit events data.
                * @example
                * $("#report").wijevcal({
                *   readOnly: true
                * });
                */
                this.readOnly = false;
                /** Determines the URL of the web service which will be used to store information about events.
                * @example
                * $("#report").wijevcal({
                *   webServiceUrl: "http://mysite/c1evcalservice.ashx"
                * });
                */
                this.webServiceUrl = "";
                /** The colors option specifies the name of the colors that will be shown in the color name drop-down list.
                * "blue", "cornflowerblue", "yellow", "bronze"]
                * @type {Array}
                * @example $("#eventscalendar").wijevcal(
                *   { colors: ["cornflowerblue", "yellow"]);
                */
                this.colors = null;
                /** Data storage methods. Use this option in order to implement custom
                * data storage layer.
                * @type {object}
                * @example $("#eventscalendar").wijevcal(
                *   { dataStorage: {
                *       addEvent: function(obj, successCallback, errorCallback) {
                *       },
                *       updateEvent: function(obj, successCallback, errorCallback) {
                *       },
                *       deleteEvent: function(obj, successCallback, errorCallback) {
                *       },
                *       loadEvents: function(visibleCalendars,
                *           successCallback, errorCallback) {
                *       },
                *       addCalendar: function(obj, successCallback, errorCallback) {
                *       },
                *       updateCalendar: function(obj, successCallback, errorCallback) {
                *       },
                *       deleteCalendar: function(obj, successCallback, errorCallback) {
                *       },
                *       loadCalendars: function(successCallback, errorCallback) {
                *       }
                *   });
                */
                this.dataStorage = {
                    addEvent: null,
                    updateEvent: null,
                    deleteEvent: null,
                    loadEvents: null,
                    addCalendar: null,
                    updateCalendar: null,
                    deleteCalendar: null,
                    loadCalendars: null
                };
                /** A dataview object to bind to events data
                * @type {object}
                * @example
                * var dv = $.wijmo.wijdataview({....});
                * $("#eventscalendar").wijevcal({
                *   dataSource: dv
                * })
                */
                this.dataSource = null;
                /** The event objects array.
                * @example $("#eventscalendar").wijevcal(
                *       { eventsData: [{id: "appt1",
                *           start: new Date(2011, 4, 6, 17, 30),
                *           end: new Date(2011, 4, 6, 17, 35) }] });
                */
                this.eventsData = null;
                /** The event objects array. This option is read-only.
                * This option is deprecated:
                * please, use eventsData option, instead.
                * @example $("#eventscalendar").wijevcal(
                *           { eventsData: [{id: "appt1",
                *               start: new Date(2011, 4, 6, 17, 30),
                *               end: new Date(2011, 4, 6, 17, 35) }] });
                */
                this.appointments = [];
                /** Available calendar objects array.
                * This option is read-only.
                * Use addCalendar/updateCalendar/deleteCalendar methods in order
                * to add/edit or delete a calendar.
                * @example
                *   var calendars = $("#eventscalendar")
                *       .wijevcal("option", "calendars");
                */
                this.calendars = [];
                /** Specifies whether the events calendar is disabled.
                * @example $("#eventscalendar").wijevcal("option",
                *       "disabled", true);
                */
                this.disabled = false;
                /** The calendar dialog box template.
                * @example $("#eventscalendar").wijevcal(
                *       { editCalendarTemplate: "html content");
                */
                this.editCalendarTemplate = "";
                /** Enables a built-in log console.
                * @example
                * $("#eventscalendar").wijevcal({ enableLogs: true });
                */
                this.enableLogs = false;
                /** Format of the title text for the event.
                * Format arguments:
                * {0} = Start, {1} = End, {2} = Subject, {3} = Location, {4} = Icons,
                * {5} = Description.
                * @example
                * $("#eventscalendar").wijevcal({
                *           eventTitleFormat: "{0:h:mmtt}-{1:h:mmtt} {4} {2}" });
                */
                this.eventTitleFormat = "{2}";
                /** The title text format that will be shown under the header bar.
                * {0} = start date. {1} = end date.
                * @type {object}
                * @example
                * Specify common title format:
                *   $("#eventscalendar").wijevcal(
                *       {
                *           titleFormat: "First date: {0:d} Last date: {1:d}"
                *       }
                *   );
                * Specify separate format for the each view:
                *   $("#eventscalendar").wijevcal(
                *       {
                *           titleFormat:  {
                *           //function customFormatFunc will be called
                *           //in order to format string:
                *           day: customFormatFunc,
                *           week: "Week {0:d} : {1:d}",
                *           month: "{0:yyyy, MMMM}",
                *           list: "Events until {1:d}",
                *           custom: "{0:d} - {1:d}"
                *       }
                *   }
                *);
                */
                this.titleFormat = {
                    day: false,
                    week: "_formatWeekTitle",
                    month: "_formatMonthTitle",
                    list: false,
                    custom: "_formatCustomTitle"
                };
                /** The first day of the week (from 0 to 6).
                * Sunday is 0, Monday is 1, and so on.
                * @example $("#eventscalendar").wijevcal(
                * { firstDayOfWeek: 1 });
                */
                this.firstDayOfWeek = 0;
                /** Indicates whether the header bar will be visible.
                * @example
                * $("#element").wijevcal({ headerBarVisible: false });
                */
                this.headerBarVisible = true;
                /** Indicates whether the bottom navigation bar will be visible.
                * @example $("#element").wijevcal({ navigationBarVisible: false });
                */
                this.navigationBarVisible = true;
                /** Indicates whether the right pane will be visible.
                * By default the right pane are empty.
                * You can use this pane in order to provide additional custom UI.
                * @example
                * $("#element").wijevcal({ rightPaneVisible: false });
                */
                this.rightPaneVisible = false;
                /** The selected date.
                * @type {Date}
                * @example $("#eventscalendar").wijevcal(
                *       { selectedDate: new Date(2015, 11, 21) });
                */
                this.selectedDate = null;
                /** The selected dates.
                * @type {Date}
                * @example $("#eventscalendar").wijevcal(
                * { selectedDates: [new Date(2012, 11, 21), new Date(2015, 11, 21)] });
                */
                this.selectedDates = null;
                /** Indicates whether the status bar will be visible.
                * @example $("#element").c1reportviewer({ statusBarVisible: false });
                */
                this.statusBarVisible = false;
                /** The time interval in minutes for the Day view.
                * @example $("#eventscalendar").wijevcal(
                *       { timeInterval: 10 });
                */
                this.timeInterval = 30;
                /** The Day view time interval row height in pixels.
                * @example $("#eventscalendar").wijevcal(
                *       { timeIntervalHeight: 30 });
                */
                this.timeIntervalHeight = 15;
                /** Time ruler interval for the Day view (in minutes).
                * @example $("#eventscalendar").wijevcal(
                *       { timeRulerInterval: 60 });
                */
                this.timeRulerInterval = 60;
                /** Time ruler format for the Day view.
                * @remarks
                * Format argument:
                *  {0} = Current ruler time.
                * @example $("#eventscalendar").wijevcal(
                *   { timeRulerFormat: "{0:t}" });
                */
                this.timeRulerFormat = "{0:h tt}";
                /** Format of the text for the day cell header(month view).
                * Format argument:
                *  {0} = Day date.
                * @example
                * $("#eventscalendar").wijevcal(
                *   { dayHeaderFormat: "{0}" });
                */
                this.dayHeaderFormat = "{0:d }";
                /** Format of the text for the first cell header in the first row of the month view.
                * Format argument:
                *  {0} = Day date.
                * @example
                * $("#eventscalendar").wijevcal(
                *       { firstRowDayHeaderFormat: "{0}" });
                */
                this.firstRowDayHeaderFormat = "{0:ddd d}";
                /** Format of the text for the day header in the day view. Format argument: {0} = Day date.
                * @remarks
                * Format argument:
                *  {0} = Day date.
                *       day: "all-day events",
                *       week: "{0:d dddd}",
                *       list: "{0:d dddd}",
                *       custom: "{0:d dddd}"
                * }
                * @example
                *   $("#eventscalendar").wijevcal(
                *       { dayViewHeaderFormat: "{0: d}" });
                */
                this.dayViewHeaderFormat = {
                    day: "all-day events",
                    week: "{0:d dddd}",
                    list: "{0:d dddd}",
                    custom: "{0:d dddd}"
                };
                /** The active view type. Possible values are: day, week, month, list. If it is a custom view, the viewType should be its name.
                * @example $("#eventscalendar").wijevcal(
                *   { viewType: "month" });
                */
                this.viewType = "day";
                /** Array of the view types which need to be shown.
                * @type {Array}
                * possible items in the array is "day", "week", "month", "list".
                * If add a custom view, item should be an Object:
                * object fields:
                * name - String, The unique name of custom view which is displayed on the toolbar;
                * unit - String, the time unit of custom view possible values are "day", "week", "month", "year";
                * count - number, the count of time span, depends on the unit;
                * {
                *   name: "2 Days",
                *   unit: "day",
                *   count: 2
                * }
                * @example
                * $("#eventscalendar").wijevcal("option",
                * "views", ["day", "week", "month", "list", {name: "2 Days", unit: "day", count: 2}]
                * );
                */
                this.views = ["day", "week", "month", "list"];
                /** A value indicating the event dialog element will be append to the body or eventcalendar container.
                * @remarks
                *       If the value is true, the dialog will be appended to body element.
                *       else it will append to the eventcalendar container.
                * @example $("#eventscalendar").wijevcal(
                *      { ensureEventDialogOnBody: true });
                */
                this.ensureEventDialogOnBody = false;
                /** Array of the calendar names which need to be shown.
                * @type {Array}
                * @example
                *       $("#eventscalendar").wijevcal("option",
                *       "visibleCalendars", ["My Calendar"]);
                */
                this.visibleCalendars = [];
                /** A value that indicates calendar's options in evets calendar.
                * @remarks Its value is wijcalendar's option, visit
                * http://wijmo.com/docs/wijmo/#Wijmo~jQuery.fn.-~wijcalendar.html for more details.
                * @type {object}
                * @example
                *      $("#eventscalendar").wijevcal(
                *      { calendar: { prevTooltip: "Previous", nextTooltip: "Next" } });
                */
                this.calendar = null;
                /** Occurs when calendars option has been changed.
                * @event
                * @dataKey {object} calendars the new calendars option value.
                */
                this.calendarsChanged = null;
                /** Occurs when events calendar is constructed and events
                * data is loaded from an external or local data source.
                * @event
                
                */
                this.initialized = null;
                /** Occurs when selectedDates option has been changed.
                * Event type: wijevcalselecteddateschanged
                * @event
                * @dataKey {object} selectedDates the new selectedDates value.
                
                */
                this.selectedDatesChanged = null;
                /** Occurs when viewType option has been changed.
                * @event
                * @param {string} viewType The new viewType value.
                */
                this.viewTypeChanged = null;
                /** Occurs when event markup is creating.
                * @event
                * @param {Object} data The data with this event. data object fields:
                * id - String, unique event id, this field generated automatically;
                * calendar - String, calendar id to which the event belongs;
                * subject - String, event title;
                * location - String, event location;
                * start - Date, start date/time;
                * end - Date, end date/time;
                * description - String, event description;
                * color - String, event color;
                * allday - Boolean, indicates all day event
                * tag - String, this field can be used to store custom information.
                * @param {String} eventTemplate The template of events displayed on the view.
                */
                this.eventCreating = null;
                /** Occurs before the built-in event dialog is shown.
                * Return false or call event.preventDefault() in order to cancel event and
                * prevent the built-in dialog to be shown.
                * @event
                * @dataKey {object} data This is the event data.
                * @dataKey {DOMElement} targetCell This is target offset DOM element which can be used for popup callout.
                */
                this.beforeEditEventDialogShow = null;
                /** Occurs before the add event action.
                * Return false or call event.preventDefault() in order to cancel event and
                * prevent the add action.
                * @event
                * @dataKey {object} data This is the new event data that should be added to a data source.
                
                */
                this.beforeAddEvent = null;
                /** Occurs before the update event action.
                * Return false or call event.preventDefault() in order to cancel event and
                * prevent the update action.
                * @event
                * @dataKey {object} data This is the new event data that should be added to a data source.
                * @dataKey {object} prevData This is previous event data.
                
                */
                this.beforeUpdateEvent = null;
                /** Occurs before the delete action.
                * Return false or call event.preventDefault() in order to cancel event and
                * prevent the delete action.
                * @event
                * @dataKey {object} data This is the event object that should be deleted.
                
                */
                this.beforeDeleteEvent = null;
                /** Occurs before the add calendar action.
                * Return false or call event.preventDefault() in order to cancel event and
                * prevent the add action.
                * @event
                * @dataKey {object} data This is  the new calendar data that should be added to a data source.
                
                */
                this.beforeAddCalendar = null;
                /** Occurs before the update calendar action.
                * Return false or call event.preventDefault() in order to cancel event and
                * prevent the update action.
                * @event
                * @dataKey {object} data This is the new event data that should be added to a data source.
                * @dataKey {object} prevData This is previous event data.
                */
                this.beforeUpdateCalendar = null;
                /** Occurs before the delete calendar action.
                * Return false or call event.preventDefault() in order to cancel event and
                * prevent the delete action.
                * @event
                * @dataKey {object} data This is the calendar data that should be deleted from a data source.
                
                */
                this.beforeDeleteCalendar = null;
                /** Occurs when the eventsData option is changed.
                * @event
                * @dataKey {object} eventsData This is array of the event objects.
                
                */
                this.eventsDataChanged = null;
            }
            return wijevcal_options;
        })();

        

        wijevcal.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijevcal_options());

        $.wijmo.registerWidget(widgetName, wijevcal.prototype);
    })(wijmo.evcal || (wijmo.evcal = {}));
    var evcal = wijmo.evcal;
})(wijmo || (wijmo = {}));

;
/// <reference path="../Base/jquery.wijmo.widget.ts" />
/// <reference path="../wijutil/jquery.wijmo.wijutil.ts" />
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*globals jQuery*/
    /*
    * Depends:
    *  jquery.mobile.js
    *
    */
    (function (appview) {
        var $ = jQuery, widgetName = "wijappview", roles = {
            menu: "menu",
            content: "content",
            header: "header",
            footer: "footer",
            page: "appviewpage"
        }, dataAttributes = {
            adjusted: widgetName + "-adjusted"
        }, initialHash = "", forceUpdateUrl = false;

        $.fn.findRole = function (role) {
            return this.find(":jqmData(role='" + role + "')");
        };

        /** @widget */
        var wijappview = (function (_super) {
            __extends(wijappview, _super);
            function wijappview() {
                _super.apply(this, arguments);
                this._updatingUrl = false;
            }
            //#region Initialization
            wijappview.prototype._appViewCSS = function () {
                return this.options.wijCSS.wijappview;
            };

            wijappview.prototype._initMenu = function () {
                this._menuDiv = this.element.findRole(roles.menu);
                if (!this._menuDiv.length) {
                    throw "A DIV with data-role='" + roles.menu + "' not found!";
                }
                this._linkList = this._menuDiv.find("ul");
                if (!this._linkList.length) {
                    throw "Invalid markup. Link list not found";
                }
                this._menuDiv.addClass(this._appViewCSS().menu);
            };

            wijappview.prototype._initPages = function ($pages, fileUrl) {
                var pageStore = this._pageStore, css = this._appViewCSS();
                $pages.each(function () {
                    var page = $(this).addClass(css.page), id = page.attr("id"), dataUrl = fileUrl;
                    if (page.jqmData("url"))
                        return;
                    if (id) {
                        dataUrl += "#" + id;
                    }

                    page.attr("data-url", dataUrl);
                });
            };
            wijappview.prototype._initPageContainer = function () {
                var css = this._appViewCSS(), pageStore = this._pageStore;

                this._pageContainer = $("<div/>").addClass(css.pageContainer).prependTo(this.element);

                var pages = this.element.findRole(roles.page);
                this._initPages(pages, this._documentUrl);
                pages.each(function (index) {
                    pageStore.push($(this).clone());
                    if (index > 0) {
                        $(this).remove();
                    }
                });
                this._firstPage = pages.first().addClass(css.pageActive).appendTo(this._pageContainer);
                this._initCurrentPage();
            };

            wijappview.prototype._getUrl = function (elem) {
                var urlAttrName = elem.is("form") ? "action" : "href", url = elem.attr(urlAttrName);

                if (!url || url === "#")
                    return null;

                if ($.mobile.path.isRelativeUrl(url)) {
                    elem.parents(":jqmData(url)").each(function (_, parent) {
                        var parentUrl = $(parent).jqmData("url");
                        if (parentUrl && $.mobile.path.isAbsoluteUrl(parentUrl)) {
                            url = $.mobile.path.makeUrlAbsolute(url, parentUrl);
                            return false;
                        }
                    });
                }

                return url;
            };

            wijappview.prototype._clickLinks = function (e) {
                if (e.isDefaultPrevented() || this._isDisabled())
                    return;
                var link = this._findClosestLink(e.target);
                if (!link || $(link).jqmData("appviewpage") === false)
                    return;

                var url = this._getUrl($(link));
                if (url) {
                    e.preventDefault();
                    e.stopPropagation();
                    this.changePage(url);
                }
            };

            wijappview.prototype._hijackLinks = function (root) {
                var _this = this;
                root.on("click." + widgetName, "a:not(.WijListviewNestedLink), .ui-btn:not(.WijListviewNestedLink)", function (e) {
                    _this._clickLinks(e);
                });
            };

            wijappview.prototype._submitForms = function (e) {
                if (e.isDefaultPrevented() || this._isDisabled())
                    return;

                var $form = $(e.currentTarget), $page = $form.closest("." + this._appViewCSS().page);

                if (!$.mobile.ajaxEnabled || $form.is(":jqmData(ajax='false')") || !$form.jqmHijackable().length) {
                    return;
                }

                var type = $form.attr("method"), target = $form.attr("target"), url = this._getUrl($form);

                if (!url) {
                    return;
                }

                e.preventDefault();
                e.stopPropagation();
                this.changePage(url, {
                    type: type && type.length && type.toLowerCase() || "get",
                    data: $form.serialize(),
                    reloadPage: true
                });
            };

            wijappview.prototype._hijackForms = function (root) {
                var _this = this;
                root.on("submit." + widgetName, "form", function (e) {
                    _this._submitForms(e);
                });
            };

            wijappview.prototype._initNavigation = function () {
                var _this = this;
                this._onPopStateScoped = this._onPopStateScoped || $.proxy(this._onPopState, this);
                $(window).bind("popstate." + widgetName, this._onPopStateScoped);
                $(window).bind("appviewpagehashchange." + widgetName, function () {
                    return _this._navigateToCurrentLocation();
                });

                this._onNavigateScoped = this._onNavigateScoped || $.proxy(this._onNavigate, this);
                $($.mobile.pageContainer).bind("navigate." + widgetName, this._onNavigateScoped);
            };

            wijappview.prototype._create = function () {
                this._pageStore = [];
                this._documentUrl = this._removePageUrlParam(location.href);
                this.element.attr("data-url", this._documentUrl);
                this._jqmPageEnclosingWidget = this._findJqmPage();

                this.element.addClass(this._appViewCSS().outerDiv);

                this._initMenu();
                this._initPageContainer();
                this._hijackLinks(this.element);
                this._hijackForms(this.element);
                this._initNavigation();
                this._navigateToCurrentLocation();

                this._toggleDisable();
            };

            wijappview.prototype._toggleDisable = function () {
                _super.prototype._toggleDisable.call(this);

                this._setInnerElementsDisabledForIE(this._isDisabled());
            };

            wijappview.prototype._setInnerElementsDisabledForIE = function (disabled) {
                if (!$.browser.msie) {
                    return;
                }
                var css = this._appViewCSS(), ele = this.element, eleOffset = ele.offset(), header = this._pageContainer.find("." + css.header), content = this._pageContainer.find("." + css.content), menu = ele.find("." + css.menu), disabeldCSS = this.options.wijCSS.stateDisabled;

                header.toggleClass(disabeldCSS, disabled);
                content.toggleClass(disabeldCSS, disabled);
                menu.toggleClass(disabeldCSS, disabled);
            };

            wijappview.prototype.destroy = function () {
                _super.prototype.destroy.call(this);
                var dotNs = "." + widgetName;
                this.element.unbind(dotNs);
                $(window).unbind(dotNs);
                $($.mobile.pageContainer).unbind(dotNs);
            };

            //#endregion
            wijappview.prototype._findJqmPage = function () {
                for (var elem = this.element; elem.length; elem = elem.parent()) {
                    var page = elem.jqmData("mobile-page");
                    if (page) {
                        return page;
                    }
                }

                return null;
            };

            wijappview.prototype._initCurrentPage = function () {
                var css = this._appViewCSS();
                var page = this.activePage();
                page.findRole(roles.content).addClass(css.content);
                var header = page.findRole(roles.header).addClass(css.header);

                var position = header.jqmData("position");
                var headerFixed = !position || position === "fixed";
                if (headerFixed) {
                    header.addClass("ui-header-fixed");
                }

                this.element.toggleClass(css.withFixedHeader, headerFixed);
            };

            wijappview.prototype._findClosestLink = function (ele) {
                while (ele && !(typeof ele.nodeName === "string" && ele.nodeName.toLowerCase() === "a")) {
                    ele = ele.parentNode;
                }
                return ele;
            };
            wijappview.prototype._clickHandler = function (e) {
                var target = $(e.currentTarget), url = target.is("li") ? target.jqmData("url") : target.is("a") ? target.attr("href") : null;
                if (!url)
                    return;

                e.preventDefault();
                e.stopPropagation();
                this.changePage(url);
            };

            wijappview.prototype._inheritAttribute = function (src, dest, attrName) {
                if (src.attr(attrName) && !dest.attr(attrName)) {
                    dest.attr(attrName, src.attr(attrName));
                }
            };

            wijappview.prototype._findInCache = function (url) {
                return $($.grep(this._pageStore, function (p) {
                    return p.jqmData("url") === url;
                })[0]).clone();
            };

            /** Load an appview page
            * @param {String} url URL of the page to load
            * @param options Load settings to override options.loadSettings
            */
            wijappview.prototype.loadPage = function (url, options) {
                var _this = this;
                url = url || "";

                // This function uses deferred notifications to let callers
                // know when the page is done loading, or if an error has occurred.
                var deferred = $.Deferred(), path = $.mobile.path, settings = $.extend({}, this.options.loadSettings, options), isLocal = !url || url.charAt(0) === "#", page = null, dupCachedPage = null, absUrl = this._makeAbsoluteUrl(url);

                // ==== Disable caching for now ====
                // Check to see if the page already exists in the DOM.
                // NOTE do _not_ use the :jqmData psuedo selector because parenthesis
                //      are a valid url char and it breaks on the first occurence
                // page = this._findInCache(absUrl);
                // If the page we are interested in is already in the DOM,
                // and the caller did not indicate that we should force a
                // reload of the file, we are done. Otherwise, track the
                // existing page as a duplicated.
                //if (page.length) {
                //    if (isLocal || !settings.reloadPage) {
                //	    // enhancePage(page, settings.role);
                //	    deferred.resolve(absUrl, options, page);
                //	    return deferred.promise();
                //    }
                //    dupCachedPage = page;
                //}
                if (settings.data) {
                    switch (settings.type) {
                        case "get":
                            absUrl = path.addSearchParams(absUrl, settings.data);
                            settings.data = undefined;
                            break;

                        case "post":
                            settings.reloadPage = true;
                            break;
                    }
                }

                var pblEvent = $.Event("pagebeforeload"), triggerData = { url: url, absUrl: absUrl, dataUrl: absUrl, deferred: deferred, options: settings };

                // Let listeners know we're about to load a page.
                this._trigger(pblEvent.type, pblEvent, triggerData);

                // If the default behavior is prevented, stop here!
                if (pblEvent.isDefaultPrevented()) {
                    return deferred.promise();
                }

                if (!$.mobile.allowCrossDomainPages && !path.isSameDomain(path.parseLocation(), absUrl)) {
                    deferred.reject(absUrl, options);
                    return deferred.promise();
                }

                // The absolute version of the URL minus any dialog/subpage params.
                // In otherwords the real URL of the page to be loaded.
                var fileUrl = absUrl && path.getFilePath(absUrl).replace(/#.+/, "");

                // Load the new page.
                var xhr = $.ajax({
                    url: fileUrl,
                    type: settings.type,
                    data: settings.data,
                    dataType: "html",
                    success: function (html, textStatus, xhr) {
                        //pre-parse html to check for a data-url,
                        //use it as the new fileUrl, base path, etc
                        var all = $("<div></div>"), pageElemRegex = new RegExp("(<[^>]+\\bdata-" + $.mobile.ns + "role=[\"']?" + roles.page + "[\"']?[^>]*>)"), dataUrlRegex = new RegExp("\\bdata-" + $.mobile.ns + "url=[\"']?([^\"'>]*)[\"']?");

                        function tryMakeAbsolute(url) {
                            if (path.isAbsoluteUrl(url) || /^(\w+:|#|\/)/.test(url)) {
                                return null;
                            }

                            return path.makeUrlAbsolute(url, fileUrl);
                        }

                        if ($.browser.msie && parseFloat($.browser.version) <= 7) {
                            // for some reason IE7 automatically makes all links absolute before I do it.
                            // I have to use regex in this case
                            html = html.replace(/<a[^>]+href=['"][^'"]+['"]/g, function (link) {
                                return link.replace(/href=['"]([^'"]+)['"]/, function (m, url) {
                                    url = tryMakeAbsolute(url) || url;
                                    return "href='" + url + "'";
                                });
                            });
                        }

                        //workaround to allow scripts to execute when included in page divs
                        all.get(0).innerHTML = html;
                        var allPages = _this._getAllPages(all, url);

                        //if page elem couldn't be found, create one and insert the body element's contents
                        if (!allPages.length) {
                            allPages = $("<div/>").attr("data-role", roles.page).html(html.split(/<\/?body[^>]*>/gmi)[1]);
                        }

                        var pageTitleFromHead = html.match(/<title[^>]*>([^<]*)/) && RegExp["$1"];
                        if (pageTitleFromHead && ~pageTitleFromHead.indexOf("&")) {
                            pageTitleFromHead = $("<div>" + pageTitleFromHead + "</div>").text();
                        }

                        // fix data-title
                        allPages.each(function (i, page) {
                            page = $(page);

                            page.attr("data-external-page", true);

                            // fix data-title
                            if (!page.jqmData("title") && pageTitleFromHead) {
                                page.attr("data-title", pageTitleFromHead);
                            }

                            //rewrite src and href attrs to use a base url
                            var newPath = path.get(fileUrl);
                            page.find("[src], [href]").each(function () {
                                var thisAttr = $(this).is('[href]') ? 'href' : $(this).is('[src]') ? 'src' : 'action', url = tryMakeAbsolute($(this).attr(thisAttr));
                                if (url) {
                                    $(this).attr(thisAttr, url);
                                }
                            });
                        });

                        _this._initPages(allPages, fileUrl);

                        // Let listeners know the page loaded successfully.
                        // Add the page reference and xhr to our triggerData.
                        page = allPages.filter(function () {
                            return $(this).jqmData("url") === absUrl;
                        });
                        if (!page.length) {
                            page = allPages.first();
                        }

                        triggerData.xhr = xhr;
                        triggerData.textStatus = textStatus;
                        triggerData.page = page;
                        triggerData.allPages = allPages;
                        _this._trigger("pageload", null, triggerData);

                        allPages.each(function (i, p) {
                            _this._pageStore.push($(p).clone());
                        });

                        deferred.resolve(absUrl, options, page, dupCachedPage);
                    },
                    error: function (xhr, textStatus, errorThrown) {
                        // Add error info to our triggerData.
                        triggerData.xhr = xhr;
                        triggerData.textStatus = textStatus;
                        triggerData.errorThrown = errorThrown;

                        var plfEvent = $.Event("pageloadfailed");

                        // Let listeners know the page load failed.
                        _this._trigger(plfEvent.type, plfEvent, triggerData);

                        // If the default behavior is prevented, stop here!
                        // Note that it is the responsibility of the listener/handler
                        // that called preventDefault(), to resolve/reject the
                        // deferred object within the triggerData.
                        if (plfEvent.isDefaultPrevented()) {
                            return;
                        }

                        // Remove loading message.
                        //if (settings.showLoadMsg) {
                        // Remove loading message.
                        // hideMsg();
                        // show error message
                        // $.mobile.showPageLoadingMsg($.mobile.pageLoadErrorMessageTheme, $.mobile.pageLoadErrorMessage, true);
                        // hide after delay
                        // setTimeout($.mobile.hidePageLoadingMsg, 1500);
                        //}
                        deferred.reject(absUrl, options);
                    }
                });

                deferred.fail(function () {
                    xhr.abort();
                });
                return deferred;
            };

            wijappview.prototype._getAllPages = function (html, url) {
                return html.findRole(roles.page);
            };

            /** Current active appview page DOM element */
            wijappview.prototype.activePage = function () {
                return this._pageContainer.children("." + this._appViewCSS().pageActive).first();
            };

            /** @ignore */
            wijappview.prototype.isMenuUrl = function (url) {
                var that = this;
                url = url.toLowerCase();
                return this._menuDiv.find("a").is(function () {
                    var getUrl = that._getUrl($(this));
                    if (!getUrl) {
                        return false;
                    }
                    return getUrl.toLowerCase() === url;
                });
            };

            wijappview.prototype._showLoading = function () {
                $.mobile.loading("show");
            };
            wijappview.prototype._hideLoading = function () {
                $.mobile.loading("hide");
            };

            /** Change current appview page
            * @param toPage A URL or an appview page DOM element to switch to
            * @param options Load settings to be used if 'toPage' is a URL
            * @remarks
            * If 'toPage' is a URL, then changePage() loads the page first and calls itself recursively
            */
            wijappview.prototype.changePage = function (toPage, options) {
                var _this = this;
                options = $.extend({ updateUrl: true }, this.options.loadSettings, options);
                var triggerData = { toPage: toPage, options: options };

                if (this._curRequest && this._curRequest.state() === "pending" && this._curRequest.rejectWith) {
                    this._curRequest.rejectWith(this, [toPage, options, true]);
                }

                var currentDataUrl;
                var toPageAbs;

                if (typeof toPage === "string") {
                    currentDataUrl = this.activePage().data("url");
                    toPageAbs = this._makeAbsoluteUrl(toPage);
                    var hashPos = toPageAbs.indexOf("#");
                    if (hashPos >= 0 && toPageAbs.substr(0, hashPos) === currentDataUrl.split("#")[0]) {
                        var fromCache = this._findInCache(toPageAbs);
                        if (fromCache.length) {
                            toPage = fromCache;
                        }
                    }
                }

                if (typeof toPage === "string") {
                    this._updateUIBeforeChange(toPageAbs);
                    if (options.showLoadMsg) {
                        this._showLoading();
                    }
                    this._curRequest = this.loadPage(toPage, options).always(function () {
                        if (options.showLoadMsg) {
                            _this._hideLoading();
                        }
                        _this._curRequest = null;
                    }).done(function (url, options, page, dupCachedPage) {
                        _this._updateUIAfterChange(page.jqmData("url"));
                        _this.changePage(page, options);
                    }).fail(function (url, options, anotherPage) {
                        if (!anotherPage) {
                            _this._updateUI(currentDataUrl);
                        }
                        _this._trigger("pagechangefailed", null, triggerData);
                    });
                    return;
                }

                var pbcEvent = $.Event("pagebeforechange");
                this._trigger(pbcEvent.type, pbcEvent, triggerData);
                if (pbcEvent.isDefaultPrevented()) {
                    return;
                }

                var absUrl = toPage.jqmData("url"), relUrl = null;

                this._updateUI(absUrl);

                if (absUrl) {
                    relUrl = this._makeRelative(absUrl);
                    if (relUrl != null) {
                        relUrl = this._makeRelative(relUrl);
                    }
                }

                var pageTitle = toPage.jqmData("title"), header = toPage.findRole("header"), css = this._appViewCSS();

                if (!header.length && pageTitle) {
                    header = $("<div data-role='header'/>").append($("<h2/>").text(pageTitle)).prependTo(toPage);
                }

                if (header.length && !header.jqmData(dataAttributes.adjusted)) {
                    header.jqmData(dataAttributes.adjusted, true);
                    var oldHeader = this._firstPage.findRole(roles.header);
                    if (oldHeader) {
                        this._inheritAttribute(oldHeader, header, "data-position");
                    }

                    if (this.isMenuUrl(absUrl) && !header.find("a[data-icon=back]").length) {
                        $("<a/>").attr({
                            href: this._documentUrl,
                            "data-icon": "back"
                        }).text("Back").prependTo(header);
                    }
                }

                if (pageTitle) {
                    document.title = pageTitle;
                }

                this._pageContainer.children().removeClass(css.pageActive);
                toPage.addClass(css.pageActive).appendTo(this._pageContainer.empty());

                this._initCurrentPage();

                if (options.updateUrl || forceUpdateUrl) {
                    this._updateUrl(absUrl, relUrl, document.title);
                    forceUpdateUrl = false;
                }

                toPage.jqmData("mobile-page", this._jqmPageEnclosingWidget).jqmData("page", this._jqmPageEnclosingWidget).enhanceWithin().trigger("pagecreate").trigger(this.widgetEventPrefix + "pageinit", triggerData);

                // TODO: temporary workaround
                this._trigger("pagechange", null, triggerData);
            };

            wijappview.prototype._updateUIBeforeChange = function (pageUrl) {
                var that = this, isRoot = pageUrl === this._documentUrl;

                var menuItems = this._linkList.find("li"), activeClass = this._appViewCSS().menuItemActive;
                if (isRoot) {
                    menuItems.removeClass(activeClass);
                } else {
                    var newMenuItem = menuItems.filter(function () {
                        var url = that._getUrl($(this).find("a"));
                        return url && url.toLowerCase() === pageUrl.toLowerCase();
                    });
                    if (newMenuItem.length && !newMenuItem.hasClass(activeClass)) {
                        menuItems.removeClass(activeClass);
                        newMenuItem.addClass(activeClass);
                    }
                }
            };
            wijappview.prototype._updateUIAfterChange = function (pageUrl) {
                var css = this._appViewCSS(), isRoot = pageUrl === this._documentUrl;
                this.element.toggleClass(css.inPage, !isRoot);
            };
            wijappview.prototype._updateUI = function (pageUrl) {
                this._updateUIBeforeChange(pageUrl);
                this._updateUIAfterChange(pageUrl);
            };

            wijappview.prototype._changePageIfDifferent = function (toPage, options) {
                var targetUrl = typeof toPage === "string" ? toPage : toPage.jqmData("url");
                if (this.activePage().jqmData("url") !== targetUrl) {
                    this.changePage(toPage, options);
                }
            };

            wijappview.prototype._onNavigate = function (e) {
                var hashRgx = new RegExp("^#?" + this.options.urlParamName + "=");
                if (history.state && history.state.wijappview || document.location.hash.match(hashRgx)) {
                    e.preventDefault();
                }
            };

            wijappview.prototype._removePageUrlParam = function (url) {
                return url.replace(/\#.*$/, "");
            };
            wijappview.prototype._addUrl = function (pageUrl) {
                var param = this.options.urlParamName;
                var url = this._removePageUrlParam(location.href);
                if (pageUrl) {
                    url += "#" + param + "=" + pageUrl;
                }
                return url;
            };

            wijappview.prototype._makeRelative = function (absUrl) {
                var loc = $.mobile.path.parseLocation();
                var url = absUrl;
                if (absUrl) {
                    var baseDir = loc.domain + loc.directory;
                    if (absUrl.substr(0, loc.hrefNoHash.length) === loc.hrefNoHash) {
                        url = absUrl.substr(loc.hrefNoHash.length);
                    } else if (absUrl.substr(0, baseDir.length) === baseDir) {
                        url = absUrl.substr(baseDir.length);
                    }
                }
                return url;
            };

            wijappview.prototype._makeAbsoluteUrl = function (url) {
                var path = $.mobile.path, activePage = this.activePage(), curAbsUrl = path.makeUrlAbsolute(activePage.jqmData("url") || this._documentUrl, this._documentUrl);
                if (!curAbsUrl.match(/\/$/) && !curAbsUrl.match(/\./)) {
                    curAbsUrl += "/";
                }
                return url && path.makeUrlAbsolute(url, curAbsUrl);
            };

            wijappview.prototype._onPopState = function (e) {
                if (this._updatingUrl)
                    return;

                if (history.state && history.state.wijappview) {
                    this._changePageIfDifferent(history.state.absUrl || this._firstPage, { updateUrl: false });
                } else {
                    this._navigateToCurrentLocation();
                }
            };

            wijappview.prototype._navigateToCurrentLocation = function () {
                var rgx = new RegExp("#" + this.options.urlParamName + "=(.+)"), match = rgx.exec(location.href) || initialHash && rgx.exec(initialHash), toPage = match ? $.mobile.path.makeUrlAbsolute(match[1], this._documentUrl) : this._firstPage;
                initialHash = "";
                this._changePageIfDifferent(toPage, { updateUrl: false });
            };

            wijappview.prototype._updateUrl = function (absUrl, relUrl, title) {
                this._updatingUrl = true;
                try  {
                    $.mobile.navigate.navigator.preventHashAssignPopState = true;
                    document.location.hash = absUrl === this._documentUrl ? "" : this.options.urlParamName + "=" + relUrl;
                } finally {
                    this._updatingUrl = false;
                }
            };
            return wijappview;
        })(wijmo.wijmoWidget);
        appview.wijappview = wijappview;

        var mainClass = "wijmo-wijappview", classPrefix = mainClass + "-";

        

        

        

        

        var wijappview_options = (function () {
            function wijappview_options() {
                /** Name of a parameter in a URL that specifies current appview page address */
                this.urlParamName = "appviewpage";
                /** Settings used to load appview pages */
                this.loadSettings = {
                    type: "GET",
                    data: undefined,
                    reloadPage: false,
                    showLoadMsg: false
                };
                /** Fires before a page is loaded
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {IPageLoadEventArgs} args Information about an event
                */
                this.pagebeforeload = null;
                /** Fires after a page is loaded
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {IPageLoadEventArgs} args Information about an event
                */
                this.pageload = null;
                /** Fires when a page load is failed
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {IPageLoadEventArgs} args Information about an event
                */
                this.pageloadfailed = null;
                /** Fires before the current page is changed
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {IPageChangeEventArgs} args Information about an event
                */
                this.pagebeforechange = null;
                /** Fires after a page is changed
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {IPageChangeEventArgs} args Information about an event
                */
                this.pagechange = null;
                /** Fires when a page change is failed
                * @event
                * @param {jQuery.Event} e Standard jQuery event object
                * @param {IPageChangeEventArgs} args Information about an event
                */
                this.pagechangefailed = null;
                this.wijCSS = {
                    wijappview: {
                        outerDiv: mainClass,
                        inPage: classPrefix + "in-page",
                        menu: classPrefix + "menu",
                        menuItemActive: "ui-btn-down-b",
                        page: classPrefix + "page",
                        pageActive: classPrefix + "page-active",
                        pageContainer: classPrefix + "page-container",
                        content: classPrefix + "content",
                        header: classPrefix + "header",
                        withFixedHeader: classPrefix + "with-fixed-header"
                    }
                };
            }
            return wijappview_options;
        })();
        appview.wijappview_options = wijappview_options;

        wijappview.prototype.options = $.extend({}, wijmo.wijmoWidget.prototype.options, new wijappview_options());

        function isAppViewPageUrl() {
            return document.location.hash.match(/^#\w+=/);
        }

        if ($.mobile) {
            $.wijmo.registerWidget(widgetName, wijappview.prototype);

            $(window).bind("hashchange", function (e) {
                if (isAppViewPageUrl()) {
                    e.stopImmediatePropagation();
                    $(window).trigger("appviewpagehashchange");
                }
            });

            // prevent initial jQM page transition
            if (isAppViewPageUrl()) {
                initialHash = document.location.hash;
                $(window).bind("pagecontainercreate", function () {
                    document.location.hash = "";
                    forceUpdateUrl = true;
                });
            }
        }
    })(wijmo.appview || (wijmo.appview = {}));
    var appview = wijmo.appview;
})(wijmo || (wijmo = {}));
;
/// <reference path="../Base/jquery.wijmo.widget.ts" />
/// <reference path="../wijutil/jquery.wijmo.wijutil.ts" />
/// <reference path="../wijutil/jquery.wijmo.raphael.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*globals $, Raphael, jQuery, document, window */
    /*
    * Depends:
    *  raphael.js
    *  globalize.js
    *
    */
    (function (_sparkline) {
        var $ = jQuery, widgetName = "wijsparkline", defaultSeriesStyle = {
            line: {
                stroke: "#5b8f00",
                "stroke-width": 1,
                opacity: 0.9
            },
            area: {
                stroke: "#009999",
                "stroke-width": 1,
                fill: "#0099ff",
                "fill-opacity": 0.5
            },
            column: {
                stroke: "none",
                fill: "#0099ff",
                "fill-opacity": 0.9,
                negStyle: {
                    fill: "#ff0000"
                },
                zeroStyle: {
                    fill: "#808080"
                }
            }
        };

        /** @ignore */
        var SparklineTooltip = (function () {
            function SparklineTooltip(style) {
                this._hOffset = 15;
                this._vOffset = -15;
                this._tooltipEle = $("<div style='position:absolute' class='wijmo-wijsparkline-tooltip'></div>");
                this._tooltipEle.appendTo("body").hide();
            }
            SparklineTooltip.prototype.show = function (content, position) {
                this._tooltipEle.css({
                    "left": position.originalLeft + this._hOffset,
                    "top": position.originalTop + this._vOffset
                }).empty().append(content);

                if (this._tooltipEle.is(":hidden")) {
                    this._tooltipEle.show();
                }
            };

            SparklineTooltip.prototype.hide = function () {
                this._tooltipEle.hide();
            };

            SparklineTooltip.prototype.destroy = function () {
                this._tooltipEle.remove();
                this._tooltipEle = null;
            };
            return SparklineTooltip;
        })();
        _sparkline.SparklineTooltip = SparklineTooltip;

        /**
        * @widget
        */
        var wijsparkline = (function (_super) {
            __extends(wijsparkline, _super);
            function wijsparkline() {
                _super.apply(this, arguments);
            }
            wijsparkline.prototype._create = function () {
                var self = this, o = self.options, width = o.width || self.element.width(), height = o.height || self.element.height(), originalStyle = self.element.attr("style"), canvas, vals;

                self.wrapper = $("<div class='ui-widget " + o.wijCSS.sparkline + "'></div>").attr("style", originalStyle || "");
                if (width) {
                    self.wrapper.css("width", width);
                }

                if (height) {
                    self.wrapper.css("height", height);
                }

                self.canvasWrapper = $("<div class='" + o.wijCSS.canvasWrapper + "'></div>");

                self.element.wrap(self.wrapper).after(self.canvasWrapper).hide();

                if (self.canvasWrapper.is(":hidden") && self.canvasWrapper.wijAddVisibilityObserver) {
                    if (self.canvasWrapper.hasClass("wijmo-wijobserver-visibility")) {
                        return;
                    }

                    self.canvasWrapper.wijAddVisibilityObserver(function () {
                        self.redraw();
                        if (self.canvasWrapper.wijRemoveVisibilityObserver) {
                            self.canvasWrapper.wijRemoveVisibilityObserver();
                        }
                    }, "wijsparkline");
                }

                if (o.data) {
                    self.data = o.data;
                } else {
                    vals = self.element.html();
                    self.data = vals.replace(/(^\s*<!--)|(-->\s*$)|\s+/g, '').split(',');
                }

                canvas = Raphael(self.canvasWrapper[0], width, height);

                self.canvas = canvas;
                if (self.canvasWrapper.is(":visible")) {
                    self._render();
                }

                _super.prototype._create.call(this);
            };

            wijsparkline.prototype._setOption = function (key, value) {
                var o = this.options;
                if (key === "height" || key === "width") {
                    o[key] = value;
                    this.element[key](value);
                } else if (key === "data") {
                    this.data = o.data = value;
                } else {
                    _super.prototype._setOption.call(this, key, value);
                }

                this.redraw();
            };

            wijsparkline.prototype._innerDisable = function () {
                _super.prototype._innerDisable.call(this);
                this._toggleDisableSparkline(true);
            };

            wijsparkline.prototype._innerEnable = function () {
                _super.prototype._innerEnable.call(this);
                this._toggleDisableSparkline(false);
            };

            wijsparkline.prototype._toggleDisableSparkline = function (disabled) {
                this.element.parent().toggleClass(this.options.wijCSS.stateDisabled, disabled);
            };

            wijsparkline.prototype._render = function () {
                var self = this, o = self.options, type = o.type, seriesList = o.seriesList, seriesStylesLength = o.seriesStyles ? o.seriesStyles.length : 0, seriesStyle;

                self.seriesRegionInfos = [];

                self.canvas.clear();

                self.canvasBounds = {
                    startX: 0,
                    width: o.width || this.element.width() || this.canvasWrapper.width(),
                    startY: 0,
                    height: o.height || this.element.height() || this.canvasWrapper.height()
                };

                type = type && type !== "" ? type.toLowerCase() : "line";
                self.containsColumnType = type === "column" || $.grep(seriesList, function (s) {
                    return s.type && s.type.toLowerCase() === "column";
                }).length > 0;

                if (seriesList && seriesList.length > 0) {
                    $.each(seriesList, function (idx, series) {
                        var seriesType = series.type && series.type !== "" ? series.type.toLowerCase() : type;

                        seriesStyle = seriesStylesLength > 0 ? o.seriesStyles[idx % seriesStylesLength] : null;

                        self._internalRender(series, o, seriesType, seriesStyle);
                    });
                } else {
                    seriesStyle = seriesStylesLength > 0 ? o.seriesStyles[0] : null;
                    self._internalRender(null, o, type, seriesStyle);
                }

                self._bindCanvasEvents();
            };

            wijsparkline.prototype._internalRender = function (series, options, type, seriesStyle) {
                var render, seriesRegionInfo, data, columnWidth, defaultStyle = defaultSeriesStyle[type];

                seriesStyle = $.extend({}, defaultStyle, seriesStyle, series ? series.seriesStyle : null);
                data = series && series.data ? series.data : this.data;

                if (series && series.columnWidth !== undefined && series.columnWidth !== null && typeof series.columnWidth === "number") {
                    columnWidth = series.columnWidth;
                } else {
                    columnWidth = options.columnWidth;
                }
                render = new wijmo.sparkline[type + "Render"](this.element, this.canvas, type, {
                    data: data,
                    min: options.min,
                    max: options.max,
                    valueAxis: options.valueAxis,
                    origin: options.origin,
                    animation: options.animation,
                    bind: series ? series.bind || options.bind : options.bind,
                    seriesStyle: seriesStyle,
                    columnWidth: columnWidth,
                    canvasBounds: this.canvasBounds
                });

                if (!render.isValid()) {
                    return true;
                }

                render.render();

                seriesRegionInfo = {
                    type: type,
                    bind: series ? series.bind : null,
                    regionInfos: render.getRegionInfos()
                };

                if (type === "column") {
                    this.colunmWidth = render.getColumnWidth();
                }

                this.seriesRegionInfos.push(seriesRegionInfo);
            };

            /**
            * This method redraws the chart.
            */
            wijsparkline.prototype.redraw = function () {
                var o = this.options, width = 0, height = 0;

                width = o.width || this.element.width() || this.canvasWrapper.width();
                height = o.height || this.element.height() || this.canvasWrapper.height();

                if (width < 1 || height < 1) {
                    return;
                }

                this.canvas.setSize(width, height);
                this._render();
            };

            /**
            * Remove the functionality completely. This will return the element back to its pre-init state.
            */
            wijsparkline.prototype.destroy = function () {
                this._unbindCanvasEvents();

                this.element.unwrap().show();

                this.canvas.clear();

                this.wrapper = null;
                this.canvasWrapper.remove();
                this.canvasWrapper = null;

                this.seriesRegionInfos = [];
                this.canvasBounds = null;

                if (this.tooltip) {
                    this.tooltip.destroy();
                    this.tooltip = null;
                }

                _super.prototype.destroy.call(this);
            };

            wijsparkline.prototype._bindCanvasEvents = function () {
                var self = this, o = self.options, $wrapper = self.canvasWrapper, touchEventPre = "", namespace = "." + widgetName;

                if (!$wrapper || !self.canvas) {
                    return;
                }

                if ($.support.isTouchEnabled && $.support.isTouchEnabled()) {
                    if (window.navigator["pointerEnabled"]) {
                        this.element.css("touch-action", "none");
                    } else if (window.navigator.msPointerEnabled) {
                        this.element.css("-ms-touch-action", "none");
                    }
                }

                if ($.support.isTouchEnabled && $.support.isTouchEnabled()) {
                    touchEventPre = "wij";
                }
                $wrapper.bind(touchEventPre + "mousemove" + namespace, function (e) {
                    var mousePos = self._getMousePosition($wrapper, e), disabled = self._isDisabled();

                    if (disabled) {
                        return;
                    }

                    self._mouseMoveInsideArea(mousePos);
                });

                $wrapper.bind(touchEventPre + "mouseout" + namespace, function (e) {
                    var tg = e.currentTarget, reltg = (e.relatedTarget) ? e.relatedTarget : e.toElement, disabled = self._isDisabled();

                    if (disabled) {
                        return;
                    }

                    if (tg.nodeName.toLowerCase() !== 'div') {
                        return;
                    }

                    while (reltg && reltg !== tg && reltg.nodeName.toLowerCase() !== 'body') {
                        reltg = reltg.parentNode;
                    }

                    if (reltg === tg) {
                        return;
                    }

                    self._mouseOutInsideArea();
                });

                $wrapper.bind(touchEventPre + "click" + namespace, function (e) {
                    var mousePos = self._getMousePosition($wrapper, e), disabled = self._isDisabled(), currentRegionInfos = [];

                    if (disabled) {
                        return;
                    }

                    currentRegionInfos = self._getCurrentRegionInfos(mousePos);

                    self._trigger("click", null, {
                        currentRegion: currentRegionInfos
                    });
                });
            };

            wijsparkline.prototype._getMousePosition = function (element, e) {
                var elePos = element.offset(), isQuirksMode = document.compatMode === "CSS1Compat", originalLeft = isQuirksMode ? e.pageX : e.clientX, originalTop = isQuirksMode ? e.pageY : e.clientY, mousePos = {
                    left: originalLeft - elePos.left,
                    originalLeft: originalLeft,
                    top: originalTop - elePos.top,
                    originalTop: originalTop
                };

                return mousePos;
            };

            wijsparkline.prototype._mouseMoveInsideArea = function (mousePos) {
                var self = this, o = self.options, format = o.tooltipFormat, content = o.tooltipContent, tooltipContent = "", currentRegionInfos = [], currentLeftPosition = NaN;

                currentRegionInfos = self._getCurrentRegionInfos(mousePos);

                if (currentRegionInfos.length > 0) {
                    $.each(currentRegionInfos, function (idx, currentRegionInfo) {
                        var currentContent;
                        if (idx === 0) {
                            tooltipContent += "<span>";
                        }
                        if (content && $.isFunction(content)) {
                            currentContent = $.proxy(content, self.data[currentRegionInfo.index])();
                        } else {
                            if (currentRegionInfo.bind) {
                                tooltipContent += currentRegionInfo.bind + ": ";
                            }
                            if (format) {
                                currentContent = format.replace(/\{(\d+)\}/g, currentRegionInfo.value.toString());
                            } else {
                                currentContent = currentRegionInfo.value.toString();
                            }
                        }
                        tooltipContent += currentContent;
                        if (idx < currentRegionInfos.length - 1) {
                            tooltipContent += "<br />";
                        } else {
                            tooltipContent += "</span>";
                        }

                        if (isNaN(currentLeftPosition)) {
                            if (self.containsColumnType) {
                                if (currentRegionInfo.type === "column") {
                                    currentLeftPosition = currentRegionInfo.position.x + self.colunmWidth / 2;
                                }
                            } else {
                                if (currentRegionInfo.type === "line" || currentRegionInfo.type === "area") {
                                    currentLeftPosition = currentRegionInfo.position.x;
                                }
                            }
                        }
                    });

                    this._paintTooltip(tooltipContent, mousePos);

                    this._paintIndicatorLine(currentLeftPosition);
                }

                this._trigger("mouseMove", null, {
                    currentRegion: currentRegionInfos
                });
            };

            wijsparkline.prototype._mouseOutInsideArea = function () {
                if (this.tooltip) {
                    this.tooltip.hide();
                }

                if (this.indicatorLine) {
                    this.indicatorLine.wijRemove();
                    this.indicatorLine = null;
                }
            };

            wijsparkline.prototype._getCurrentRegionInfos = function (mousePos) {
                var self = this, currentRegionInfos = [];

                $.each(this.seriesRegionInfos, function (idx, regionInfo) {
                    var currentRegionInfo, methodName = "_" + regionInfo.type + "GetCurrentRegionInfo", method = self[methodName];

                    if (method) {
                        currentRegionInfo = method.call(self, regionInfo, mousePos);

                        if (currentRegionInfo) {
                            currentRegionInfo.type = regionInfo.type;
                            currentRegionInfo.bind = regionInfo.bind;
                            currentRegionInfos.push(currentRegionInfo);
                        }
                    }
                });

                return currentRegionInfos;
            };

            wijsparkline.prototype._lineGetCurrentRegionInfo = function (seriesInfo, mousePos) {
                var regionInfos = seriesInfo.regionInfos, length, currentRegion;

                if (!regionInfos) {
                    return;
                }

                length = regionInfos.length;

                $.each(regionInfos, function (idx, regionInfo) {
                    var currentPosition = regionInfo.position, nextRegionInfo, nextPostion;
                    if (idx < length - 1) {
                        nextRegionInfo = regionInfos[idx + 1];
                        nextPostion = nextRegionInfo.position;
                        if (mousePos.left >= currentPosition.x && mousePos.left < nextPostion.x) {
                            currentRegion = regionInfo;
                            currentRegion.index = idx;
                            return false;
                        }
                    } else {
                        if (mousePos.left >= currentPosition.x) {
                            currentRegion = regionInfo;
                            currentRegion.index = idx;
                            return false;
                        }
                    }
                });

                return currentRegion;
            };

            wijsparkline.prototype._areaGetCurrentRegionInfo = function (seriesInfo, mousePos) {
                return this._lineGetCurrentRegionInfo(seriesInfo, mousePos);
            };

            wijsparkline.prototype._columnGetCurrentRegionInfo = function (seriesInfo, mousePos) {
                return this._lineGetCurrentRegionInfo(seriesInfo, mousePos);
            };

            wijsparkline.prototype._pieGetCurrentRegionInfo = function (seriesInfo, mousePos) {
                /* Todo */
                return null;
            };

            wijsparkline.prototype._bulletGetCurrentRegionInfo = function (seriesInfo, mousePos) {
                /* Todo */
                return null;
            };

            wijsparkline.prototype._unbindCanvasEvents = function () {
                if ($.support.isTouchEnabled && $.support.isTouchEnabled()) {
                    if (window.navigator["pointerEnabled"]) {
                        this.element.css("touch-action", "");
                    } else if (window.navigator.msPointerEnabled) {
                        this.element.css("-ms-touch-action", "");
                    }
                }
                this.element.unbind("." + widgetName);
            };

            wijsparkline.prototype._paintTooltip = function (tooltipContent, mousePos) {
                if (!this.tooltip) {
                    this.tooltip = new SparklineTooltip(this.options.tooltipStyle);
                }

                this.tooltip.show(tooltipContent, mousePos);
            };

            wijsparkline.prototype._paintIndicatorLine = function (currentLeftPosition) {
                var height, left, top, pathArr;

                if (!this.indicatorLine) {
                    height = this.canvasBounds.height;
                    left = this.canvasBounds.startX;
                    top = this.canvasBounds.startY;
                    pathArr = ["M", left, top, "V", height];
                    this.indicatorLine = this.canvas.path(pathArr.join(" "));
                    this.indicatorLine.transform("T" + currentLeftPosition + " 0");
                } else {
                    this.indicatorLine.transform("T" + currentLeftPosition + " 0");
                }
            };
            return wijsparkline;
        })(wijmo.wijmoWidget);
        _sparkline.wijsparkline = wijsparkline;

        /** @ignore */
        var sparklineRenderBase = (function () {
            function sparklineRenderBase(element, canvas, type, options) {
                this.isValidData = true;
                this.values = [];
                this.type = type;
                this.options = options;
                this.element = element;
                this.canvas = canvas;
                this.animationSet = canvas.set();

                this.scanValues();
                if (this.options.min === null || this.options.min === undefined || typeof this.options.min !== "number") {
                    this.minValue = Math.min.apply(Math, this.values);
                } else {
                    this.minValue = this.options.min;
                }
                if (this.options.max === null || this.options.max === undefined || typeof this.options.max !== "number") {
                    this.maxValue = Math.max.apply(Math, this.values);
                } else {
                    this.maxValue = this.options.max;
                }
            }
            sparklineRenderBase.prototype.render = function () {
                if (!this.element || !this.canvas) {
                    return;
                }
            };

            sparklineRenderBase.prototype.playAnimation = function () {
                var o = this.options, canvasBounds = o.canvasBounds, animation = o.animation;

                if (this.animationSet.length > 0 && animation && animation.enabled) {
                    this.animationSet.wijAttr("clip-rect", Raphael.format("{0} {1} 0 {2}", canvasBounds.startX, canvasBounds.startY, canvasBounds.height));

                    this.animationSet.wijAnimate({ "clip-rect": Raphael.format("{0} {1} {2} {3}", canvasBounds.startX, canvasBounds.startY, canvasBounds.width, canvasBounds.height) }, animation.duration, animation.easing, null);
                }
            };

            sparklineRenderBase.prototype.scanValues = function () {
                var self = this, o = self.options, bind = o.bind, dataSource = o.data;

                if ($.isArray(dataSource)) {
                    $.each(dataSource, function (idx, val) {
                        var value;
                        if (bind && val && val[bind] !== undefined) {
                            value = val[bind];
                        } else {
                            value = val;
                        }

                        if (typeof value === "string") {
                            value = parseFloat(value);
                        }

                        if (isNaN(value)) {
                            self.isValidData = false;
                            return false;
                        }

                        self.values.push(value);
                    });
                }
            };

            sparklineRenderBase.prototype.setRegionInfos = function () {
                var self = this, valRange = 0, canvasHeight = self.options.canvasBounds.height, canvasWidth = self.options.canvasBounds.width, dataCnt;

                if (!self.values || self.values.length === 0) {
                    return;
                }

                if (!this.regionInfos) {
                    this.regionInfos = [];
                }

                dataCnt = self.values.length;

                valRange = self.maxValue - self.minValue;
                self.valRange = valRange = valRange === 0 ? 1 : valRange;

                $.each(self.values, function (idx, val) {
                    var xPosition, yPosition;

                    xPosition = idx * (canvasWidth / dataCnt);
                    yPosition = canvasHeight * (1 - (val - self.minValue) / valRange);
                    self.regionInfos.push({
                        value: val,
                        position: {
                            x: xPosition,
                            y: yPosition
                        }
                    });
                });
            };

            sparklineRenderBase.prototype.getRegionInfos = function () {
                if (!this.regionInfos || this.regionInfos.length === 0) {
                    this.setRegionInfos();
                }
                return this.regionInfos;
            };

            sparklineRenderBase.prototype.getColumnWidth = function () {
                return null;
            };

            sparklineRenderBase.prototype.isValid = function () {
                return this.isValidData;
            };
            return sparklineRenderBase;
        })();
        _sparkline.sparklineRenderBase = sparklineRenderBase;

        /** @ignore */
        var lineRender = (function (_super) {
            __extends(lineRender, _super);
            function lineRender(element, canvas, type, options) {
                _super.call(this, element, canvas, type, options);
                this.regionInfos = [];
            }
            lineRender.prototype.render = function () {
                var o = this.options, pathArr = [];

                _super.prototype.render.call(this);

                this.setRegionInfos();

                if (this.regionInfos && this.regionInfos.length > 0) {
                    $.each(this.regionInfos, function (idx, regionInfo) {
                        var position = regionInfo.position;
                        if (idx === 0) {
                            pathArr.push("M");
                        } else {
                            pathArr.push("L");
                        }
                        pathArr.push(position.x);
                        pathArr.push(position.y);
                    });

                    if (pathArr.length > 0) {
                        this.line = this.canvas.path(pathArr.join(" "));

                        this.line.wijAttr(o.seriesStyle);
                        this.line.wijAttr("fill", "none");

                        this.animationSet.push(this.line);

                        if (this.type === "line") {
                            this.playAnimation();
                        }
                    }
                }
            };
            return lineRender;
        })(sparklineRenderBase);
        _sparkline.lineRender = lineRender;

        /** @ignore */
        var areaRender = (function (_super) {
            __extends(areaRender, _super);
            function areaRender(element, canvas, type, options) {
                _super.call(this, element, canvas, type, options);
            }
            areaRender.prototype.render = function () {
                var canvasHeight = this.options.canvasBounds.height, maxValue = this.maxValue, minValue = this.minValue, origin = this.options.origin, startX, endY, currentPathArr, pathArr;

                _super.prototype.render.call(this);

                if (this.options.valueAxis) {
                    if (origin === null || origin === undefined || typeof origin !== "number") {
                        origin = (maxValue - minValue) / 2 + minValue;
                    }
                    endY = canvasHeight * (1 - (origin - this.minValue) / this.valRange);
                } else {
                    endY = canvasHeight;
                }

                currentPathArr = Raphael.parsePathString(this.line.attr("path"));

                if (currentPathArr && currentPathArr.length > 0) {
                    pathArr = [];
                    $.each(currentPathArr, function (i, currentPath) {
                        $.each(currentPath, function (j, val) {
                            pathArr.push(val);
                        });
                        if (currentPath[0] === "M") {
                            startX = currentPath[1];
                        }
                        if (i === currentPathArr.length - 1) {
                            pathArr.push("V");
                            pathArr.push(endY);
                            pathArr.push("H");
                            pathArr.push(startX);
                            pathArr.push("Z");
                        }
                    });
                }

                if (pathArr.length > 0) {
                    this.area = this.canvas.path(pathArr.join(" "));
                    this.area.wijAttr(this.options.seriesStyle);
                    this.area.wijAttr("stroke", "none");

                    this.animationSet.push(this.area);

                    this.playAnimation();
                }
            };
            return areaRender;
        })(lineRender);
        _sparkline.areaRender = areaRender;

        /** @ignore */
        var columnRender = (function (_super) {
            __extends(columnRender, _super);
            function columnRender(element, canvas, type, options) {
                _super.call(this, element, canvas, type, options);
                this.animateBars = [];
            }
            columnRender.prototype.render = function () {
                var _this = this;
                var self = this, maxValue = self.maxValue, minValue = self.minValue, canvas = self.canvas, o = self.options, origin = o.origin, animation = o.animation, canvasHeight = o.canvasBounds.height, normalStyle = o.seriesStyle, negStyle = o.seriesStyle.negStyle, zeroStyle = o.seriesStyle.zeroStyle, unitHeight, animationEnable, start;

                _super.prototype.render.call(this);

                self.setRegionInfos();

                delete normalStyle["zeroStyle"];
                delete normalStyle["negStyle"];
                negStyle = $.extend({}, normalStyle, negStyle);
                zeroStyle = $.extend({}, normalStyle, zeroStyle);

                this.columnWidth = self.adjustColumnWidth();
                unitHeight = canvasHeight / self.valRange;
                animationEnable = animation && animation.enabled;

                if (o.valueAxis) {
                    if (origin === null || origin === undefined || typeof origin !== "number") {
                        origin = (maxValue - minValue) / 2 + minValue;
                    }
                    start = (maxValue - origin) * unitHeight;
                } else {
                    start = canvasHeight;
                }

                if (self.regionInfos && self.regionInfos.length > 0) {
                    $.each(self.regionInfos, function (idx, regionInfo) {
                        var columnTop, columnHeight, seriesStyle, bar, actualTop, isZeroValue, columnLeft = regionInfo.position.x, val = regionInfo.value;

                        if (o.valueAxis) {
                            if (val >= origin) {
                                isZeroValue = val === origin;
                                actualTop = isZeroValue ? regionInfo.position.y - 2 * unitHeight : regionInfo.position.y;
                                ;
                                columnTop = animationEnable ? start : regionInfo.position.y;
                                columnHeight = isZeroValue ? 2 * unitHeight : (val - origin) * unitHeight;
                                seriesStyle = isZeroValue ? zeroStyle : normalStyle;
                            } else {
                                actualTop = columnTop = start;
                                columnHeight = (origin - val) * unitHeight;
                                seriesStyle = negStyle;
                            }
                        } else {
                            isZeroValue = val === minValue;
                            actualTop = isZeroValue ? regionInfo.position.y - 2 * unitHeight : regionInfo.position.y;
                            columnTop = start;
                            columnHeight = isZeroValue ? 2 * unitHeight : canvasHeight - regionInfo.position.y;
                            seriesStyle = isZeroValue ? zeroStyle : normalStyle;
                        }

                        bar = canvas.rect(columnLeft, columnTop, _this.columnWidth, columnHeight);
                        bar.wijAttr(seriesStyle);

                        bar["top"] = actualTop;
                        bar["height"] = columnHeight;
                        self.animateBars.push(bar);
                    });

                    self.playAnimation();
                }
            };

            columnRender.prototype.playAnimation = function () {
                var o = this.options, animation = o.animation;

                if (animation && animation.enabled) {
                    if (this.animateBars.length > 0) {
                        $.each(this.animateBars, function (idx, bar) {
                            var params = { height: bar["height"], y: bar["top"] };
                            bar.wijAttr({ height: 0 });
                            bar.stop().wijAnimate(params, animation.duration, animation.easing, null);
                        });
                    }
                } else {
                    if (this.animateBars.length > 0) {
                        $.each(this.animateBars, function (idx, bar) {
                            var params = { height: bar["height"], y: bar["top"] };
                            bar.wijAttr(params);
                        });
                    }
                }
            };

            columnRender.prototype.adjustColumnWidth = function () {
                var o = this.options, optionColumnWidth = o.columnWidth, canvasWidth = o.canvasBounds.width, columnSpacing = 2, calcColumnWidth;

                calcColumnWidth = canvasWidth / this.values.length - columnSpacing;

                return optionColumnWidth > calcColumnWidth ? calcColumnWidth : optionColumnWidth;
            };

            columnRender.prototype.getColumnWidth = function () {
                return this.columnWidth;
            };
            return columnRender;
        })(sparklineRenderBase);
        _sparkline.columnRender = columnRender;

        

        

        

        

        

        

        var wijsparkline_options = (function () {
            function wijsparkline_options() {
                /**
                * Selector option for auto self initialization. This option is internal.
                * @ignore
                */
                this.initSelector = ":jqmData(role='wijsparkline')";
                /**
                * All CSS classes used in widgets.
                * @ignore
                */
                this.wijCSS = {
                    sparkline: "wijmo-wijsparkline",
                    canvasWrapper: "wijmo-sparkline-canvas-wrapper"
                };
                /**
                * Specifies the type of the sparkline widget.
                * @remarks
                * The value of the type can be 'line', 'area' and 'column'.
                * And the default value is 'line'.
                */
                this.type = "line";
                /**
                * Creates an array of series objects that contain data values and labels to display in the chart.
                * @remarks
                * The series object contains following options
                * 1) type: Specifies the type of the sparkline widget.  The value for this option can be 'line', 'area' and 'column'.  And the default value is 'Line'.
                * 2) bind: Indicates that which property value is get from the object in the array if the data is set as a object array.
                * 3) seriesStyle: The specific style applies for current series of the sparkline widget for
                */
                this.seriesList = [];
                /**
                * Sets the width of the sparkline widget in pixels.
                * @remarks
                * Note that this value overrides any value you may set in the <div> element that
                * you use in the body of the HTML page
                * If you specify a width in the <div> element that is different from this value,
                * the chart and its border go out of synch.
                * @type {?number}
                */
                this.width = null;
                /**
                * Sets the height of the sparkline widget in pixels.
                * @remarks
                * Note that this value overrides any value you may set in the <div> element that
                * you use in the body of the HTML page. If you specify a height in the <div> element that
                * is different from this value, the chart and its border go out of synch.
                * @type {?number}
                */
                this.height = null;
                /**
                * Sets the array to use as a source for data that you can bind to the sparkline widget.
                * @remarks
                * The array can be a simple number array.  The array can be a complex object array also.
                * If it is an object array, use the seriesList object's bind option to specify the data field to use.
                */
                this.data = null;
                /**
                * A value indicates that which property value is get from the object in the array if the data is set as a object array.
                */
                this.bind = null;
                /**
                * Sets an array of style objects to use in rendering sparklines for each series in the sparkline widget.
                * @remarks
                * Each style object in the array applies to one series in your seriesList,
                * so you need specify only as many style objects as you have series objects in your seriesList.
                */
                this.seriesStyles = [];
                /**
                * The animation option defines the animation effect and controls other aspects of the widget's animation,
                * such as duration and easing.
                */
                this.animation = {
                    /**
                    * A value that determines whether to show the animation.
                    * Set this option to false in order to disable easing.
                    */
                    enabled: true,
                    /**
                    * A value that indicates the duration for the animation.
                    */
                    duration: 2000,
                    /**
                    * Sets the type of animation easing effect that users experience
                    * when the wijlinechart series is loaded to the page.
                    * For example, a user can have the wijlinechart series bounce several times as it loads.
                    * @remarks Values available for the animation easing effect include the following:
                    * easeInCubic ¨C Cubic easing in. Begins at zero velocity and then accelerates.
                    * easeOutCubic ¨C Cubic easing in and out. Begins at full velocity and then decelerates to zero.
                    * easeInOutCubic ¨C Begins at zero velocity, accelerates until halfway, and then decelerates to zero velocity again.
                    * easeInBack ¨C Begins slowly and then accelerates.
                    * easeOutBack ¨C Begins quickly and then decelerates.
                    * easeOutElastic ¨C Begins at full velocity and then decelerates to zero.
                    * easeOutBounce ¨C Begins quickly and then decelerates. The number of bounces is related to the duration, longer durations produce more bounces.
                    */
                    easing: "easeInCubic"
                };
                /**
                * Axis line as option (off by default) used for identifying negative or positive values.
                * @remarks
                * This option just works with area type sparkline.
                * @type {bool}
                */
                this.valueAxis = false;
                /**
                * Centers the value axis at the origin option setting value.
                * @remarks
                * This option just works when valueAxis is set to true.
                * @type {number}
                */
                this.origin = null;
                /**
                * A value that indicates the minimum value of the sparkline.
                * @type {?number}
                */
                this.min = null;
                /**
                * A value that indicates the maximum value of the sparkline.
                * @type {?number}
                */
                this.max = null;
                /**
                * Set width for each column
                * @remarks
                * This option only works for column type sparkline.
                */
                this.columnWidth = 10;
                /**
                * A value which formats the value for tooltip shown.
                * @remarks
                * If the tooltipContent option is set, this option won't work.
                */
                this.tooltipFormat = null;
                /**
                * A function which is used to get a value for the tooltip shown.
                */
                this.tooltipContent = null;
                /**
                * This event fires when the user moves the mouse pointer while it is over a sparkline.
                * @event
                * @param {Object} e The jQuery.Event object.
                * @param {IWijSparklineEventArgs} args The data with this event.
                */
                this.mouseMove = null;
                /**
                * This event fires when the user clicks the sparkline.
                * @event
                * @param {Object} e The jQuery.Event object.
                * @param {IWijSparklineEventArgs} args The data with this event.
                */
                this.click = null;
                /**
                * Indicates whether the event handler of the sparkline widget is enable.
                */
                this.disabled = false;
            }
            return wijsparkline_options;
        })();

        wijsparkline.prototype.options = $.extend(true, {}, wijsparkline.prototype.options, new wijsparkline_options());

        wijsparkline.prototype.widgetEventPrefix = "wijsparkline";

        $.wijmo.registerWidget("wijsparkline", wijsparkline.prototype);

        

        

        

        

        
    })(wijmo.sparkline || (wijmo.sparkline = {}));
    var sparkline = wijmo.sparkline;
})(wijmo || (wijmo = {}));

;
/// <reference path="../wijchart/jquery.wijmo.wijchartcore.ts"/>
/// <reference path="exportUtil.ts" />
var wijmo;
(function (wijmo) {
    (function (exporter) {
        (function (ChartExportMethod) {
            ChartExportMethod[ChartExportMethod["Content"] = 0] = "Content";
            ChartExportMethod[ChartExportMethod["Options"] = 1] = "Options";
        })(exporter.ChartExportMethod || (exporter.ChartExportMethod = {}));
        var ChartExportMethod = exporter.ChartExportMethod;

        /** @ignore
        *  Export the chart as image or pdf.
        * @param {ChartExportSetting} The export settings.
        */
        function exportChart(setting) {
            var chartExporter = new chartExport(setting.serviceUrl, setting.method), options = {
                fileName: setting.fileName,
                height: setting.height,
                width: setting.width,
                widgetName: setting.widgetName,
                widgetOptions: setting.widgetOptions,
                HTMLContent: setting.HTMLContent,
                widget: setting.chart,
                type: setting.exportFileType,
                pdfSetting: setting.pdf
            }, data = chartExporter.getExportData(options);
            exporter.exportFile(setting, data);
        }
        exporter.exportChart = exportChart;

        /** @ignore
        *  Export the chart as image or pdf.
        * @param {ChartExportSetting} The export settings.
        */
        var chartExport = (function () {
            function chartExport(serviceUrl, method) {
                this.serviceUrl = serviceUrl;
                this.method = method;
            }
            chartExport.prototype.getExportData = function (options) {
                var result;
                this.options = options;
                this._handleExportOption();
                result = {
                    fileName: options.fileName,
                    width: options.width,
                    height: options.height,
                    type: options.type,
                    pdfSettings: options.pdfSetting
                };
                if (this.method === 0 /* Content */) {
                    result.content = options.HTMLContent;
                } else {
                    result.options = options.widgetOptions;
                    result.widgetName = options.widgetName;
                }
                return exporter.toJSON(result, function (key, val) {
                    if (key === "type") {
                        switch (val) {
                            case 6 /* Bmp */:
                                return "bmp";
                            case 7 /* Gif */:
                                return "gif";
                            case 5 /* Jpg */:
                                return "jpg";
                            case 3 /* Pdf */:
                                return "pdf";
                            case 8 /* Tiff */:
                                return "tiff";
                            default:
                                return "png";
                        }
                    }
                    return val;
                });
            };

            chartExport.prototype._handleExportOption = function () {
                var o = this.options;
                if (o.widget) {
                    if (this.method == 0 /* Content */) {
                        o.HTMLContent = o.widget.chartElement[0].outerHTML;
                    } else {
                        o.widgetName = this._getWidgetName();
                        o.widgetOptions = exporter.toJSON(this._handleChartOptions(o.widget, o.widgetName), function (k, v) {
                            if (v != null) {
                                return v;
                            }
                        });
                    }
                    o.width = o.widget.chartElement.width();
                    o.height = o.widget.chartElement.height();
                }
            };

            chartExport.prototype._getWidgetName = function () {
                return this.options.widget ? this.options.widget.widgetName : "";
            };

            chartExport.prototype._handleChartOptions = function (widget, widgetName) {
                var chartoptions = widget.options, options = $.extend(true, {}, chartoptions, {
                    animation: {
                        enabled: false
                    },
                    seriesTransition: {
                        enabled: false
                    },
                    hint: {
                        enable: false
                    }
                });

                delete options.wijCSS;
                delete options.seriesHoverStyles;

                if (widgetName === "wijbarchart") {
                    this._handleBarChartOptions(options);
                } else if (widgetName === "wijcandlestickchart") {
                    this._handleCandlestickChartOptions(options, widget);
                } else if (widgetName === "wijcompositechart") {
                    this._handleCompositeChartOptions(options, widget);
                }

                this._handleAxis(options);
                return options;
            };

            chartExport.prototype._handleAxis = function (options) {
                var _this = this;
                this._removeAuto(options.axis.x);
                if ($.isArray(options.axis.y)) {
                    $.each(options.axis.y, function (i, axis) {
                        _this._removeAuto(axis);
                    });
                } else {
                    this._removeAuto(options.axis.y);
                }
            };

            chartExport.prototype._handleBarChartOptions = function (options) {
                if (options.horizontal) {
                    var compass = options.axis.x.compass;
                    options.axis.x.compass = options.axis.y.compass;
                    options.axis.y.compass = compass;
                }
            };

            chartExport.prototype._handleCandlestickChartOptions = function (options, widget) {
                $.each(options.seriesList, function (i, series) {
                    if (series.data && series.data.x) {
                        $.each(series.data.x, function (j, val) {
                            if (typeof (val) === "number") {
                                series.data.x[j] = widget.timeUtil.getTime(val);
                            }
                        });
                    }
                });
            };

            chartExport.prototype._handleCompositeChartOptions = function (options, widget) {
                if (widget.isContainsCandlestick && widget.timeUtil) {
                    $.each(options.seriesList, function (i, series) {
                        if (series.data && series.data.x) {
                            $.each(series.data.x, function (j, val) {
                                if (typeof (val) === "number") {
                                    series.data.x[j] = widget.timeUtil.getTime(val);
                                }
                            });
                        }
                    });
                }
            };

            chartExport.prototype._removeAuto = function (axis) {
                if (axis.autoMax) {
                    delete axis.max;
                }
                if (axis.autoMin) {
                    delete axis.min;
                }
                if (axis.autoMajor) {
                    delete axis.unitMajor;
                }
                if (axis.autoMinor) {
                    delete axis.unitMinor;
                }
            };
            return chartExport;
        })();
        exporter.chartExport = chartExport;

        

        /** @ignore */
        function innerExportChart(exportSettings, type, settings, serviceUrl, exportMethod) {
            var t, mode, pdfSetting = {}, sUrl, chartExportSettings;
            t = type === undefined ? "png" : type;
            t = t.substr(0, 1).toUpperCase() + t.substr(1);
            mode = exportMethod === undefined ? "Options" : exportMethod;
            mode = mode.substr(0, 1).toUpperCase() + mode.substr(1);
            if (typeof settings === "string" && arguments.length === 3) {
                sUrl = settings;
            } else {
                sUrl = serviceUrl === undefined ? "http://demos.componentone.com/ASPNET/ExportService/exportapi/chart" : serviceUrl;
                pdfSetting = settings;
            }

            if (!$.isPlainObject(exportSettings)) {
                chartExportSettings = {
                    serviceUrl: sUrl,
                    fileName: exportSettings === undefined ? "export" : exportSettings,
                    pdf: pdfSetting,
                    method: ChartExportMethod[mode],
                    chart: this,
                    exportFileType: wijmo.exporter.ExportFileType[t]
                };
            } else {
                chartExportSettings = exportSettings;
            }
            wijmo.exporter.exportChart(chartExportSettings);
        }
        exporter.innerExportChart = innerExportChart;

        if (wijmo.chart && wijmo.chart.wijchartcore) {
            wijmo.chart.wijchartcore.prototype.exportChart = innerExportChart;
        }

        //wijmo.chart
        var charts = ["wijbarchart", "wijbubblechart", "wijcandlestickchart", "wijcompositechart", "wijlinechart", "wijpiechart", "wijscatterchart"];
        $.each(charts, function (idx, chart) {
            if (!$.wijmo[chart]) {
                return;
            }
            $.wijmo[chart].prototype.exportChart = innerExportChart;
        });
    })(wijmo.exporter || (wijmo.exporter = {}));
    var exporter = wijmo.exporter;
})(wijmo || (wijmo = {}));
;
/// <reference path="../external/declarations/jquery.d.ts" />
var wijmo;
(function (wijmo) {
    (function (exporter) {
        var $ = jQuery;

        function toJSON(obj, replacer) {
            var originDateToJSON = Date.prototype.toJSON;

            // Use local time to json instead of UTC time.
            Date.prototype.toJSON = _localDateTimeToJSON;
            try  {
                return JSON.stringify(obj, replacer);
            } finally {
                Date.prototype.toJSON = originDateToJSON;
            }
        }
        exporter.toJSON = toJSON;

        function _formatUint(uint, length) {
            // Format unsigned integer to have at least specified digits.
            var uintStr = uint.toString();
            while (uintStr.length < length) {
                uintStr = '0' + uintStr;
            }

            return uintStr;
        }

        function _localDateTimeToJSON() {
            var date = this;
            return _formatUint(date.getFullYear(), 4) + '-' + _formatUint(date.getMonth() + 1, 2) + '-' + _formatUint(date.getDate(), 2) + 'T' + _formatUint(date.getHours(), 2) + ':' + _formatUint(date.getMinutes(), 2) + ':' + _formatUint(date.getSeconds(), 2) + "." + _formatUint(date.getMilliseconds(), 3);
        }

        function exportFile(setting, content) {
            var sender = setting.sender, contentType = setting.contentType, serviceUrl = setting.serviceUrl;
            if (sender) {
                sender(content, setting);
            } else if (contentType == "application/json") {
                _exportByXMLHttpRequest(content, serviceUrl, setting);
            } else {
                _exportByForm(content, serviceUrl);
            }
        }
        exporter.exportFile = exportFile;

        function exportChunk(setting, content, success) {
            var serviceUrl = setting.serviceUrl + '/exportchunk';
            _exportChunk(content, serviceUrl, success);
        }
        exporter.exportChunk = exportChunk;

        function exportAllPages(serviceUrl, content, token) {
            var url = serviceUrl + '/exportallpages/' + token;
            _exportByForm(content, url);
        }
        exporter.exportAllPages = exportAllPages;

        function _exportChunk(content, serviceUrl, success) {
            var xmlhttp = new XMLHttpRequest();
            xmlhttp.open('POST', serviceUrl, true);
            xmlhttp.onload = function () {
                var txt = JSON.parse(xmlhttp.responseText);
                success(txt);
            };
            xmlhttp.send(content);
            return xmlhttp;
        }

        function _exportByForm(content, serviceUrl) {
            var formInnerHtml = '<input type="hidden" name="type" value="application/json"/>';
            formInnerHtml += '<input type="hidden" name="data" value="' + _htmlSpecialCharsEntityEncode(content) + '" />';
            var $iframe = $("<iframe style='display: none' src='about:blank'></iframe>").appendTo("body");
            $iframe.ready(function () {
                var formDoc = _getiframeDocument($iframe);
                formDoc.write("<html><head><meta http-equiv='Content-Type' content='text/html; charset=utf-8'></head><body><form method='Post' accept-charset='utf-8' action='" + serviceUrl + "'>" + formInnerHtml + "</form>dummy windows for postback</body></html>");
                var $form = $(formDoc).find('form');
                $form.submit();
            });
        }

        function _getiframeDocument($iframe) {
            var iframeDoc = $iframe[0].contentWindow || $iframe[0].contentDocument;
            if (iframeDoc.document) {
                iframeDoc = iframeDoc.document;
            }
            return iframeDoc;
        }

        var _htmlSpecialCharsRegEx = /[<>&\r\n"']/gm;
        var _htmlSpecialCharsPlaceHolders = {
            '<': 'lt;',
            '>': 'gt;',
            '&': 'amp;',
            '\r': "#13;",
            '\n': "#10;",
            '"': 'quot;',
            "'": 'apos;'
        };

        function _htmlSpecialCharsEntityEncode(str) {
            return str.replace(_htmlSpecialCharsRegEx, function (match) {
                return '&' + _htmlSpecialCharsPlaceHolders[match];
            });
        }

        function _exportByXMLHttpRequest(content, serviceUrl, setting) {
            var xmlhttp = new XMLHttpRequest();
            xmlhttp.open("post", serviceUrl);
            xmlhttp.send(content);
            xmlhttp.responseType = "blob";
            xmlhttp.onreadystatechange = function () {
                if (xmlhttp.response && setting.receiver) {
                    setting.receiver(xmlhttp.response, setting);
                }
            };
        }

        /** Export file type options: Xls, Xlsx, Cvs, Pdf, Png, Jpg,Bmp,Gif and Tiff. */
        (function (ExportFileType) {
            ExportFileType[ExportFileType["Xls"] = 0] = "Xls";
            ExportFileType[ExportFileType["Xlsx"] = 1] = "Xlsx";
            ExportFileType[ExportFileType["Csv"] = 2] = "Csv";
            ExportFileType[ExportFileType["Pdf"] = 3] = "Pdf";
            ExportFileType[ExportFileType["Png"] = 4] = "Png";
            ExportFileType[ExportFileType["Jpg"] = 5] = "Jpg";
            ExportFileType[ExportFileType["Bmp"] = 6] = "Bmp";
            ExportFileType[ExportFileType["Gif"] = 7] = "Gif";
            ExportFileType[ExportFileType["Tiff"] = 8] = "Tiff";
        })(exporter.ExportFileType || (exporter.ExportFileType = {}));
        var ExportFileType = exporter.ExportFileType;

        /** Export mode */
        (function (ExportMethod) {
            /** Sending markup to the service for exporting. */
            ExportMethod[ExportMethod["Content"] = 0] = "Content";

            /** Sending widget options to the service for exporting. */
            ExportMethod[ExportMethod["Options"] = 1] = "Options";
        })(exporter.ExportMethod || (exporter.ExportMethod = {}));
        var ExportMethod = exporter.ExportMethod;

        

        /**  The font type */
        (function (FontType) {
            /**  Use only standard Pdf fonts (Helvetica, Times, Symbol). */
            FontType[FontType["Standard"] = 0] = "Standard";

            /**  Use TrueType fonts, no embedding (viewer must have fonts installed). */
            FontType[FontType["TrueType"] = 1] = "TrueType";

            /**  Use embedded TrueType fonts. */
            FontType[FontType["Embedded"] = 2] = "Embedded";
        })(exporter.FontType || (exporter.FontType = {}));
        var FontType = exporter.FontType;

        /**  The image quality. */
        (function (ImageQuality) {
            /**  Low quality, small file size. */
            ImageQuality[ImageQuality["Low"] = 0] = "Low";

            /**  Medium quality, medium file size. */
            ImageQuality[ImageQuality["Medium"] = 1] = "Medium";

            /**  High quality, medium/large file size. */
            ImageQuality[ImageQuality["Default"] = 2] = "Default";

            /**  Highest quality, largest file size. */
            ImageQuality[ImageQuality["High"] = 3] = "High";
        })(exporter.ImageQuality || (exporter.ImageQuality = {}));
        var ImageQuality = exporter.ImageQuality;

        /**  The compression type. */
        (function (CompressionType) {
            /**  High compression, fast save. */
            CompressionType[CompressionType["Default"] = -1] = "Default";

            /**  No compression (useful for debugging). */
            CompressionType[CompressionType["None"] = 0] = "None";

            /**  Low compression, fastest save. */
            CompressionType[CompressionType["BestSpeed"] = 1] = "BestSpeed";

            /**  Highest compression, slowest save. */
            CompressionType[CompressionType["BestCompression"] = 9] = "BestCompression";
        })(exporter.CompressionType || (exporter.CompressionType = {}));
        var CompressionType = exporter.CompressionType;

        /** The Pdf encryption type. */
        (function (PdfEncryptionType) {
            /**  Encryption is unavailable due to FIPS compliance (MD5 and AES128 are not FIPS-compliant). */
            PdfEncryptionType[PdfEncryptionType["NotPermit"] = 0] = "NotPermit";

            /**  Standard 40 bit encryption algorithm. */
            PdfEncryptionType[PdfEncryptionType["Standard40"] = 2] = "Standard40";

            /**  Standard 128 bit encryption algorithm. */
            PdfEncryptionType[PdfEncryptionType["Standard128"] = 3] = "Standard128";

            /**  AES 128 bit encryption algorithm. */
            PdfEncryptionType[PdfEncryptionType["Aes128"] = 4] = "Aes128";
        })(exporter.PdfEncryptionType || (exporter.PdfEncryptionType = {}));
        var PdfEncryptionType = exporter.PdfEncryptionType;

        

        

        /**  Specifies the standard paper sizes. */
        (function (PaperKind) {
            /**  The paper size is defined by the user.*/
            PaperKind[PaperKind["Custom"] = 0] = "Custom";

            /** Letter paper (8.5 in. by 11 in.).*/
            PaperKind[PaperKind["Letter"] = 1] = "Letter";

            /** Letter small paper (8.5 in. by 11 in.).*/
            PaperKind[PaperKind["LetterSmall"] = 2] = "LetterSmall";

            /** Tabloid paper (11 in. by 17 in.).*/
            PaperKind[PaperKind["Tabloid"] = 3] = "Tabloid";

            /** Ledger paper (17 in. by 11 in.).*/
            PaperKind[PaperKind["Ledger"] = 4] = "Ledger";

            /** Legal paper (8.5 in. by 14 in.).*/
            PaperKind[PaperKind["Legal"] = 5] = "Legal";

            /** Statement paper (5.5 in. by 8.5 in.).*/
            PaperKind[PaperKind["Statement"] = 6] = "Statement";

            /** Executive paper (7.25 in. by 10.5 in.).*/
            PaperKind[PaperKind["Executive"] = 7] = "Executive";

            /** A3 paper (297 mm by 420 mm).*/
            PaperKind[PaperKind["A3"] = 8] = "A3";

            /** A4 paper (210 mm by 297 mm).*/
            PaperKind[PaperKind["A4"] = 9] = "A4";

            /** A4 small paper (210 mm by 297 mm).*/
            PaperKind[PaperKind["A4Small"] = 10] = "A4Small";

            /** A5 paper (148 mm by 210 mm).*/
            PaperKind[PaperKind["A5"] = 11] = "A5";

            /** B4 paper (250 mm by 353 mm).*/
            PaperKind[PaperKind["B4"] = 12] = "B4";

            /** B5 paper (176 mm by 250 mm).*/
            PaperKind[PaperKind["B5"] = 13] = "B5";

            /** Folio paper (8.5 in. by 13 in.).*/
            PaperKind[PaperKind["Folio"] = 14] = "Folio";

            /**  Quarto paper (215 mm by 275 mm).*/
            PaperKind[PaperKind["Quarto"] = 15] = "Quarto";

            /** Standard paper (10 in. by 14 in.).*/
            PaperKind[PaperKind["Standard10x14"] = 16] = "Standard10x14";

            /** Standard paper (11 in. by 17 in.).*/
            PaperKind[PaperKind["Standard11x17"] = 17] = "Standard11x17";

            /** Note paper (8.5 in. by 11 in.).*/
            PaperKind[PaperKind["Note"] = 18] = "Note";

            /**  #9 envelope (3.875 in. by 8.875 in.).*/
            PaperKind[PaperKind["Number9Envelope"] = 19] = "Number9Envelope";

            /** #10 envelope (4.125 in. by 9.5 in.).*/
            PaperKind[PaperKind["Number10Envelope"] = 20] = "Number10Envelope";

            /** #11 envelope (4.5 in. by 10.375 in.).*/
            PaperKind[PaperKind["Number11Envelope"] = 21] = "Number11Envelope";

            /** #12 envelope (4.75 in. by 11 in.).*/
            PaperKind[PaperKind["Number12Envelope"] = 22] = "Number12Envelope";

            /** #14 envelope (5 in. by 11.5 in.).*/
            PaperKind[PaperKind["Number14Envelope"] = 23] = "Number14Envelope";

            /** C paper (17 in. by 22 in.).*/
            PaperKind[PaperKind["CSheet"] = 24] = "CSheet";

            /** D paper (22 in. by 34 in.).*/
            PaperKind[PaperKind["DSheet"] = 25] = "DSheet";

            /** E paper (34 in. by 44 in.).*/
            PaperKind[PaperKind["ESheet"] = 26] = "ESheet";

            /** DL envelope (110 mm by 220 mm).*/
            PaperKind[PaperKind["DLEnvelope"] = 27] = "DLEnvelope";

            /**  C5 envelope (162 mm by 229 mm).*/
            PaperKind[PaperKind["C5Envelope"] = 28] = "C5Envelope";

            /** C3 envelope (324 mm by 458 mm). */
            PaperKind[PaperKind["C3Envelope"] = 29] = "C3Envelope";

            /** C4 envelope (229 mm by 324 mm). */
            PaperKind[PaperKind["C4Envelope"] = 30] = "C4Envelope";

            /** C6 envelope (114 mm by 162 mm). */
            PaperKind[PaperKind["C6Envelope"] = 31] = "C6Envelope";

            /** C65 envelope (114 mm by 229 mm). */
            PaperKind[PaperKind["C65Envelope"] = 32] = "C65Envelope";

            /** B4 envelope (250 mm by 353 mm). */
            PaperKind[PaperKind["B4Envelope"] = 33] = "B4Envelope";

            /** B5 envelope (176 mm by 250 mm). */
            PaperKind[PaperKind["B5Envelope"] = 34] = "B5Envelope";

            /**  B6 envelope (176 mm by 125 mm). */
            PaperKind[PaperKind["B6Envelope"] = 35] = "B6Envelope";

            /** Italy envelope (110 mm by 230 mm). */
            PaperKind[PaperKind["ItalyEnvelope"] = 36] = "ItalyEnvelope";

            /** Monarch envelope (3.875 in. by 7.5 in.). */
            PaperKind[PaperKind["MonarchEnvelope"] = 37] = "MonarchEnvelope";

            /** 6 3/4 envelope (3.625 in. by 6.5 in.). */
            PaperKind[PaperKind["PersonalEnvelope"] = 38] = "PersonalEnvelope";

            /** US standard fanfold (14.875 in. by 11 in.). */
            PaperKind[PaperKind["USStandardFanfold"] = 39] = "USStandardFanfold";

            /** German standard fanfold (8.5 in. by 12 in.). */
            PaperKind[PaperKind["GermanStandardFanfold"] = 40] = "GermanStandardFanfold";

            /** German legal fanfold (8.5 in. by 13 in.). */
            PaperKind[PaperKind["GermanLegalFanfold"] = 41] = "GermanLegalFanfold";

            /** ISO B4 (250 mm by 353 mm). */
            PaperKind[PaperKind["IsoB4"] = 42] = "IsoB4";

            /** Japanese postcard (100 mm by 148 mm). */
            PaperKind[PaperKind["JapanesePostcard"] = 43] = "JapanesePostcard";

            /** Standard paper (9 in. by 11 in.). */
            PaperKind[PaperKind["Standard9x11"] = 44] = "Standard9x11";

            /** Standard paper (10 in. by 11 in.). */
            PaperKind[PaperKind["Standard10x11"] = 45] = "Standard10x11";

            /** Standard paper (15 in. by 11 in.). */
            PaperKind[PaperKind["Standard15x11"] = 46] = "Standard15x11";

            /** Invitation envelope (220 mm by 220 mm). */
            PaperKind[PaperKind["InviteEnvelope"] = 47] = "InviteEnvelope";

            /** Letter extra paper (9.275 in. by 12 in.). This value is specific to the PostScript
            *  driver and is used only by Linotronic printers in order to conserve paper. */
            PaperKind[PaperKind["LetterExtra"] = 50] = "LetterExtra";

            /** Legal extra paper (9.275 in. by 15 in.). This value is specific to the PostScript
            *  driver and is used only by Linotronic printers in order to conserve paper. */
            PaperKind[PaperKind["LegalExtra"] = 51] = "LegalExtra";

            /** Tabloid extra paper (11.69 in. by 18 in.). This value is specific to the
            *   PostScript driver and is used only by Linotronic printers in order to conserve
            *   paper. */
            PaperKind[PaperKind["TabloidExtra"] = 52] = "TabloidExtra";

            /** A4 extra paper (236 mm by 322 mm). This value is specific to the PostScript
            *    driver and is used only by Linotronic printers to help save paper. */
            PaperKind[PaperKind["A4Extra"] = 53] = "A4Extra";

            /** Letter transverse paper (8.275 in. by 11 in.). */
            PaperKind[PaperKind["LetterTransverse"] = 54] = "LetterTransverse";

            /** A4 transverse paper (210 mm by 297 mm). */
            PaperKind[PaperKind["A4Transverse"] = 55] = "A4Transverse";

            /** Letter extra transverse paper (9.275 in. by 12 in.). */
            PaperKind[PaperKind["LetterExtraTransverse"] = 56] = "LetterExtraTransverse";

            /** SuperA/SuperA/A4 paper (227 mm by 356 mm). */
            PaperKind[PaperKind["APlus"] = 57] = "APlus";

            /** SuperB/SuperB/A3 paper (305 mm by 487 mm). */
            PaperKind[PaperKind["BPlus"] = 58] = "BPlus";

            /** Letter plus paper (8.5 in. by 12.69 in.). */
            PaperKind[PaperKind["LetterPlus"] = 59] = "LetterPlus";

            /** A4 plus paper (210 mm by 330 mm). */
            PaperKind[PaperKind["A4Plus"] = 60] = "A4Plus";

            /** A5 transverse paper (148 mm by 210 mm). */
            PaperKind[PaperKind["A5Transverse"] = 61] = "A5Transverse";

            /** JIS B5 transverse paper (182 mm by 257 mm). */
            PaperKind[PaperKind["B5Transverse"] = 62] = "B5Transverse";

            /** A3 extra paper (322 mm by 445 mm). */
            PaperKind[PaperKind["A3Extra"] = 63] = "A3Extra";

            /** A5 extra paper (174 mm by 235 mm). */
            PaperKind[PaperKind["A5Extra"] = 64] = "A5Extra";

            /** ISO B5 extra paper (201 mm by 276 mm). */
            PaperKind[PaperKind["B5Extra"] = 65] = "B5Extra";

            /** A2 paper (420 mm by 594 mm). */
            PaperKind[PaperKind["A2"] = 66] = "A2";

            /** A3 transverse paper (297 mm by 420 mm). */
            PaperKind[PaperKind["A3Transverse"] = 67] = "A3Transverse";

            /** A3 extra transverse paper (322 mm by 445 mm). */
            PaperKind[PaperKind["A3ExtraTransverse"] = 68] = "A3ExtraTransverse";

            /** Japanese double postcard (200 mm by 148 mm). Requires Windows 98, Windows
            *    NT 4.0, or later. */
            PaperKind[PaperKind["JapaneseDoublePostcard"] = 69] = "JapaneseDoublePostcard";

            /** A6 paper (105 mm by 148 mm). Requires Windows 98, Windows NT 4.0, or later. */
            PaperKind[PaperKind["A6"] = 70] = "A6";

            /** Japanese Kaku #2 envelope. Requires Windows 98, Windows NT 4.0, or later. */
            PaperKind[PaperKind["JapaneseEnvelopeKakuNumber2"] = 71] = "JapaneseEnvelopeKakuNumber2";

            /** Japanese Kaku #3 envelope. Requires Windows 98, Windows NT 4.0, or later. */
            PaperKind[PaperKind["JapaneseEnvelopeKakuNumber3"] = 72] = "JapaneseEnvelopeKakuNumber3";

            /** Japanese Chou #3 envelope. Requires Windows 98, Windows NT 4.0, or later. */
            PaperKind[PaperKind["JapaneseEnvelopeChouNumber3"] = 73] = "JapaneseEnvelopeChouNumber3";

            /** Japanese Chou #4 envelope. Requires Windows 98, Windows NT 4.0, or later. */
            PaperKind[PaperKind["JapaneseEnvelopeChouNumber4"] = 74] = "JapaneseEnvelopeChouNumber4";

            /** Letter rotated paper (11 in. by 8.5 in.). */
            PaperKind[PaperKind["LetterRotated"] = 75] = "LetterRotated";

            /** A3 rotated paper (420 mm by 297 mm). */
            PaperKind[PaperKind["A3Rotated"] = 76] = "A3Rotated";

            /**  A4 rotated paper (297 mm by 210 mm). Requires Windows 98, Windows NT 4.0,
            *   or later. */
            PaperKind[PaperKind["A4Rotated"] = 77] = "A4Rotated";

            /** A5 rotated paper (210 mm by 148 mm). Requires Windows 98, Windows NT 4.0,
            *   or later. */
            PaperKind[PaperKind["A5Rotated"] = 78] = "A5Rotated";

            /** JIS B4 rotated paper (364 mm by 257 mm). Requires Windows 98, Windows NT
            *   4.0, or later. */
            PaperKind[PaperKind["B4JisRotated"] = 79] = "B4JisRotated";

            /** JIS B5 rotated paper (257 mm by 182 mm). Requires Windows 98, Windows NT
            *   4.0, or later. */
            PaperKind[PaperKind["B5JisRotated"] = 80] = "B5JisRotated";

            /** Japanese rotated postcard (148 mm by 100 mm). Requires Windows 98, Windows
            *   NT 4.0, or later.*/
            PaperKind[PaperKind["JapanesePostcardRotated"] = 81] = "JapanesePostcardRotated";

            /** Japanese rotated double postcard (148 mm by 200 mm). Requires Windows 98,
            *  Windows NT 4.0, or later.*/
            PaperKind[PaperKind["JapaneseDoublePostcardRotated"] = 82] = "JapaneseDoublePostcardRotated";

            /** A6 rotated paper (148 mm by 105 mm). Requires Windows 98, Windows NT 4.0,
            *   or later.*/
            PaperKind[PaperKind["A6Rotated"] = 83] = "A6Rotated";

            /** Japanese rotated Kaku #2 envelope. Requires Windows 98, Windows NT 4.0, or
            *   later.*/
            PaperKind[PaperKind["JapaneseEnvelopeKakuNumber2Rotated"] = 84] = "JapaneseEnvelopeKakuNumber2Rotated";

            /** Japanese rotated Kaku #3 envelope. Requires Windows 98, Windows NT 4.0, or
            *   later.*/
            PaperKind[PaperKind["JapaneseEnvelopeKakuNumber3Rotated"] = 85] = "JapaneseEnvelopeKakuNumber3Rotated";

            /** Japanese rotated Chou #3 envelope. Requires Windows 98, Windows NT 4.0, or
            *   later.*/
            PaperKind[PaperKind["JapaneseEnvelopeChouNumber3Rotated"] = 86] = "JapaneseEnvelopeChouNumber3Rotated";

            /** Japanese rotated Chou #4 envelope. Requires Windows 98, Windows NT 4.0, or
            *   later.*/
            PaperKind[PaperKind["JapaneseEnvelopeChouNumber4Rotated"] = 87] = "JapaneseEnvelopeChouNumber4Rotated";

            /** JIS B6 paper (128 mm by 182 mm). Requires Windows 98, Windows NT 4.0, or
            *   later.*/
            PaperKind[PaperKind["B6Jis"] = 88] = "B6Jis";

            /** JIS B6 rotated paper (182 mm by 128 mm). Requires Windows 98, Windows NT
            *   4.0, or later.*/
            PaperKind[PaperKind["B6JisRotated"] = 89] = "B6JisRotated";

            /** Standard paper (12 in. by 11 in.). Requires Windows 98, Windows NT 4.0, or
            *   later.*/
            PaperKind[PaperKind["Standard12x11"] = 90] = "Standard12x11";

            /** Japanese You #4 envelope. Requires Windows 98, Windows NT 4.0, or later.*/
            PaperKind[PaperKind["JapaneseEnvelopeYouNumber4"] = 91] = "JapaneseEnvelopeYouNumber4";

            /** Japanese You #4 rotated envelope. Requires Windows 98, Windows NT 4.0, or
            *   later.*/
            PaperKind[PaperKind["JapaneseEnvelopeYouNumber4Rotated"] = 92] = "JapaneseEnvelopeYouNumber4Rotated";

            /** People's Republic of China 16K paper (146 mm by 215 mm). Requires Windows
            98, Windows NT 4.0, or later.*/
            PaperKind[PaperKind["Prc16K"] = 93] = "Prc16K";

            /** People's Republic of China 32K paper (97 mm by 151 mm). Requires Windows
            98, Windows NT 4.0, or later.*/
            PaperKind[PaperKind["Prc32K"] = 94] = "Prc32K";

            /** People's Republic of China 32K big paper (97 mm by 151 mm). Requires Windows
            *   98, Windows NT 4.0, or later.*/
            PaperKind[PaperKind["Prc32KBig"] = 95] = "Prc32KBig";

            /** People's Republic of China #1 envelope (102 mm by 165 mm). Requires Windows
            *   98, Windows NT 4.0, or later.*/
            PaperKind[PaperKind["PrcEnvelopeNumber1"] = 96] = "PrcEnvelopeNumber1";

            /** People's Republic of China #2 envelope (102 mm by 176 mm). Requires Windows
            98, Windows NT 4.0, or later.*/
            PaperKind[PaperKind["PrcEnvelopeNumber2"] = 97] = "PrcEnvelopeNumber2";

            /** People's Republic of China #3 envelope (125 mm by 176 mm). Requires Windows
            *   98, Windows NT 4.0, or later.*/
            PaperKind[PaperKind["PrcEnvelopeNumber3"] = 98] = "PrcEnvelopeNumber3";

            /** People's Republic of China #4 envelope (110 mm by 208 mm). Requires Windows
            *   98, Windows NT 4.0, or later.*/
            PaperKind[PaperKind["PrcEnvelopeNumber4"] = 99] = "PrcEnvelopeNumber4";

            /** People's Republic of China #5 envelope (110 mm by 220 mm). Requires Windows
            98, Windows NT 4.0, or later.*/
            PaperKind[PaperKind["PrcEnvelopeNumber5"] = 100] = "PrcEnvelopeNumber5";

            /** People's Republic of China #6 envelope (120 mm by 230 mm). Requires Windows
            *   98, Windows NT 4.0, or later.
            PrcEnvelopeNumber6 = 101,
            /** People's Republic of China #7 envelope (160 mm by 230 mm). Requires Windows
            *   98, Windows NT 4.0, or later.*/
            PaperKind[PaperKind["PrcEnvelopeNumber7"] = 102] = "PrcEnvelopeNumber7";

            /** People's Republic of China #8 envelope (120 mm by 309 mm). Requires Windows
            *   98, Windows NT 4.0, or later.*/
            PaperKind[PaperKind["PrcEnvelopeNumber8"] = 103] = "PrcEnvelopeNumber8";

            /** People's Republic of China #9 envelope (229 mm by 324 mm). Requires Windows
            *   98, Windows NT 4.0, or later.*/
            PaperKind[PaperKind["PrcEnvelopeNumber9"] = 104] = "PrcEnvelopeNumber9";

            /** People's Republic of China #10 envelope (324 mm by 458 mm). Requires Windows
            *   98, Windows NT 4.0, or later.*/
            PaperKind[PaperKind["PrcEnvelopeNumber10"] = 105] = "PrcEnvelopeNumber10";

            /** People's Republic of China 16K rotated paper (146 mm by 215 mm). Requires
            *   Windows 98, Windows NT 4.0, or later.*/
            PaperKind[PaperKind["Prc16KRotated"] = 106] = "Prc16KRotated";

            /** People's Republic of China 32K rotated paper (97 mm by 151 mm). Requires
            *   Windows 98, Windows NT 4.0, or later.*/
            PaperKind[PaperKind["Prc32KRotated"] = 107] = "Prc32KRotated";

            /** People's Republic of China 32K big rotated paper (97 mm by 151 mm). Requires
            *   Windows 98, Windows NT 4.0, or later.*/
            PaperKind[PaperKind["Prc32KBigRotated"] = 108] = "Prc32KBigRotated";

            /**  People's Republic of China #1 rotated envelope (165 mm by 102 mm). Requires
            *    Windows 98, Windows NT 4.0, or later.*/
            PaperKind[PaperKind["PrcEnvelopeNumber1Rotated"] = 109] = "PrcEnvelopeNumber1Rotated";

            /** People's Republic of China #2 rotated envelope (176 mm by 102 mm). Requires
            *  Windows 98, Windows NT 4.0, or later.*/
            PaperKind[PaperKind["PrcEnvelopeNumber2Rotated"] = 110] = "PrcEnvelopeNumber2Rotated";

            /** People's Republic of China #3 rotated envelope (176 mm by 125 mm). Requires
            *   Windows 98, Windows NT 4.0, or later.*/
            PaperKind[PaperKind["PrcEnvelopeNumber3Rotated"] = 111] = "PrcEnvelopeNumber3Rotated";

            /** People's Republic of China #4 rotated envelope (208 mm by 110 mm). Requires
            *   Windows 98, Windows NT 4.0, or later.*/
            PaperKind[PaperKind["PrcEnvelopeNumber4Rotated"] = 112] = "PrcEnvelopeNumber4Rotated";

            /** People's Republic of China Envelope #5 rotated envelope (220 mm by 110 mm).
            *   Requires Windows 98, Windows NT 4.0, or later.*/
            PaperKind[PaperKind["PrcEnvelopeNumber5Rotated"] = 113] = "PrcEnvelopeNumber5Rotated";

            /** People's Republic of China #6 rotated envelope (230 mm by 120 mm). Requires
            *   Windows 98, Windows NT 4.0, or later.*/
            PaperKind[PaperKind["PrcEnvelopeNumber6Rotated"] = 114] = "PrcEnvelopeNumber6Rotated";

            /** People's Republic of China #7 rotated envelope (230 mm by 160 mm). Requires
            Windows 98, Windows NT 4.0, or later.*/
            PaperKind[PaperKind["PrcEnvelopeNumber7Rotated"] = 115] = "PrcEnvelopeNumber7Rotated";

            /** People's Republic of China #8 rotated envelope (309 mm by 120 mm). Requires
            *   Windows 98, Windows NT 4.0, or later.*/
            PaperKind[PaperKind["PrcEnvelopeNumber8Rotated"] = 116] = "PrcEnvelopeNumber8Rotated";

            /** People's Republic of China #9 rotated envelope (324 mm by 229 mm). Requires
            *   Windows 98, Windows NT 4.0, or later.*/
            PaperKind[PaperKind["PrcEnvelopeNumber9Rotated"] = 117] = "PrcEnvelopeNumber9Rotated";

            /** People's Republic of China #10 rotated envelope (458 mm by 324 mm). Requires
            *   Windows 98, Windows NT 4.0, or later.*/
            PaperKind[PaperKind["PrcEnvelopeNumber10Rotated"] = 118] = "PrcEnvelopeNumber10Rotated";
        })(exporter.PaperKind || (exporter.PaperKind = {}));
        var PaperKind = exporter.PaperKind;
    })(wijmo.exporter || (wijmo.exporter = {}));
    var exporter = wijmo.exporter;
})(wijmo || (wijmo = {}));
;
/// <reference path="../wijgrid/Grid.ts/Grid/interfaces.ts" />
/// <reference path="../wijgrid/Grid.ts/Grid/wijgrid.ts" />
/// <reference path="exportUtil.ts" />
/// <reference path="../data/src/dataView.ts"/>

var wijmo;
(function (wijmo) {
    (function (exporter) {
        var $ = jQuery;

        

        

        

        

        

        

        

        

        

        

        /** @ignore */
        (function (RowTemplateType) {
            RowTemplateType[RowTemplateType["None"] = 0] = "None";
            RowTemplateType[RowTemplateType["Template"] = 1] = "Template";
            RowTemplateType[RowTemplateType["AltTemplate"] = 2] = "AltTemplate";
            RowTemplateType[RowTemplateType["HeaderTemplate"] = 3] = "HeaderTemplate";
            RowTemplateType[RowTemplateType["FooterTemplate"] = 4] = "FooterTemplate";
            RowTemplateType[RowTemplateType["GroupHeaderTemplate"] = 5] = "GroupHeaderTemplate";
            RowTemplateType[RowTemplateType["GroupFooterTemplate"] = 6] = "GroupFooterTemplate";
        })(exporter.RowTemplateType || (exporter.RowTemplateType = {}));
        var RowTemplateType = exporter.RowTemplateType;

        /** @ignore */
        (function (SectionType) {
            SectionType[SectionType["Header"] = 0] = "Header";
            SectionType[SectionType["Body"] = 1] = "Body";
            SectionType[SectionType["Footer"] = 2] = "Footer";
        })(exporter.SectionType || (exporter.SectionType = {}));
        var SectionType = exporter.SectionType;

        /** @ignore */
        (function (RowType) {
            RowType[RowType["Data"] = 0] = "Data";
            RowType[RowType["Header"] = 1] = "Header";
            RowType[RowType["Footer"] = 2] = "Footer";
            RowType[RowType["GroupHeader"] = 3] = "GroupHeader";
            RowType[RowType["GroupFooter"] = 4] = "GroupFooter";
        })(exporter.RowType || (exporter.RowType = {}));
        var RowType = exporter.RowType;

        /** @ignore */
        (function (ColType) {
            ColType[ColType["Text"] = 1] = "Text";
            ColType[ColType["Image"] = 2] = "Image";
            ColType[ColType["Link"] = 3] = "Link";
            ColType[ColType["Checkbox"] = 4] = "Checkbox";
            ColType[ColType["Html"] = 5] = "Html";
        })(exporter.ColType || (exporter.ColType = {}));
        var ColType = exporter.ColType;
        ;

        

        

        

        

        /** @ignore */
        var exportContext = (function () {
            function exportContext(grid, environmentInfo) {
                this.createdGroupHeaderTemplates = [];
                this.createdGroupFooterTemplates = [];
                var self = this;
                self.environmentInfo = environmentInfo;
                self._init(grid);
            }
            exportContext.prototype._init = function (grid) {
                var self = this, dataView = grid.dataView(), $cols = $(grid.element).find(">colgroup>col");
                self.grid = grid;
                self.showRowHeader = grid.options.showRowHeader;
                self.dataView = dataView;
                self.dataCount = dataView.count();
                if (self.dataCount > 0) {
                    var first = dataView.item(0);
                    self.isArrayData = $.type(first) == "array";
                }

                self._initColInfos($cols);
            };

            exportContext.prototype._initColInfos = function ($cols) {
                var self = this;
                self.colLeaves = $.grep(self.grid.columns(), function (element) {
                    return element.options._isLeaf;
                });
                self.colWidths = [];
                self.colInfos = $cols.map(function (colIndex) {
                    if (colIndex < 0 || colIndex > self.colLeaves.length - 1)
                        return null;

                    var col = self.colLeaves[colIndex], type = 1 /* Text */, dataTypeQualifier = col.options.dataTypeQualifier;

                    if (self.isHtmlCol(col)) {
                        type = 5 /* Html */;
                    } else if (self.isLinkCol(col)) {
                        type = 3 /* Link */;
                    } else if (self.isImageCol(col)) {
                        type = 2 /* Image */;
                    } else if (self.isCheckBoxCol(col)) {
                        type = 4 /* Checkbox */;
                    }
                    self.colWidths.push(self.computedWidthToPt($(this).css("width")));
                    var colInfo = {
                        formatString: col.options.dataFormatString,
                        dataType: col.options.dataType,
                        type: type
                    };
                    if (dataTypeQualifier) {
                        colInfo.dataTypeQualifier = dataTypeQualifier;
                    }
                    return colInfo;
                }).get();
            };

            exportContext.prototype.computedWidthToPt = function (lengthStr) {
                return gridExporter.pxToPt(lengthStr, this.environmentInfo.dpiX);
            };

            exportContext.prototype.computedHeightToPt = function (lengthStr) {
                return gridExporter.pxToPt(lengthStr, this.environmentInfo.dpiY);
            };

            exportContext.prototype._getVisibleColumnIndex = function (colIndex) {
                var result = this._findInColumns(this.grid.options.columns, colIndex);
                if (result.found) {
                    return result.index;
                }
                return colIndex;
            };

            exportContext.prototype._findInColumns = function (columns, colIndex, index) {
                if (typeof index === "undefined") { index = 0; }
                var totalColumns = columns.length;
                var result = { index: index, col: colIndex, found: false };
                for (var i = 0; i < totalColumns; i++) {
                    result = this._findInColumn(columns[i], result.col, result.index);
                    if (result.found) {
                        return result;
                    }
                }
                return result;
            };

            exportContext.prototype._getColumnCount = function (column) {
                var _this = this;
                var subColumns = column.columns;
                if (!subColumns) {
                    return 1;
                }
                var count = 0;
                subColumns.forEach(function (item, index, arr) {
                    count += _this._getColumnCount(item);
                });
                return count;
            };

            exportContext.prototype._findInColumn = function (column, colIndex, index) {
                var result = { index: index, col: colIndex, found: false };
                if (!column.visible) {
                    var count = this._getColumnCount(column);
                    result.col += count;
                    result.index += count;
                } else if (!column.columns) {
                    if (result.index == result.col) {
                        result.found = true;
                    } else {
                        result.index++;
                    }
                } else {
                    result = this._findInColumns(column.columns, colIndex, index);
                }
                return result;
            };

            exportContext.prototype.getDataValue = function (rowIndex, colIndex) {
                var self = this;
                colIndex = this._getVisibleColumnIndex(colIndex);
                if (rowIndex >= self.dataCount || rowIndex < 0 || colIndex < 0)
                    return null;
                var data = self.grid.dataView().item(rowIndex);
                if (self.isArrayData) {
                    if (self.showRowHeader)
                        colIndex--;
                    if (colIndex < 0 || colIndex >= data.length)
                        return null;
                    return data[colIndex];
                }
                var cols = self.colLeaves;
                if (colIndex >= cols.length)
                    return null;
                var dataKey = cols[colIndex].options.dataKey;
                return data[dataKey];
            };

            exportContext.prototype.isCheckBoxCol = function (col) {
                return col instanceof wijmo.grid.c1booleanfield;
            };

            exportContext.prototype.isHtmlCol = function (col) {
                return col.options.cellFormatter != null;
            };

            exportContext.prototype.isImageCol = function (col) {
                return false;
            };

            exportContext.prototype.isLinkCol = function (col) {
                return (col instanceof wijmo.grid.c1buttonfield) && (col.options.buttonType === "link");
            };
            return exportContext;
        })();
        exporter.exportContext = exportContext;

        /** @ignore */
        function exportGrid(setting) {
            gridExporter.exportFile(setting);
        }
        exporter.exportGrid = exportGrid;

        /** @ignore */
        var gridExporter = (function () {
            function gridExporter() {
            }
            gridExporter.exportFile = function (setting) {
                var exportAction = function (exportSetting) {
                    return exporter.exportFile(exportSetting, exporter.toJSON(gridExporter._exportSource(exportSetting)));
                }, needNewSingleTable = gridExporter._needNewSingleTable(setting), needRequestAllData = gridExporter._needRequestAllData(setting);

                if (!needNewSingleTable && !needRequestAllData) {
                    exportAction(setting);
                    return;
                }

                var grid = setting.grid, totalRowCount = gridExporter._getTotalRowCount(grid);

                setting.rowCountPerRequest = setting.rowCountPerRequest || totalRowCount;
                if (grid.options.allowPaging && setting.rowCountPerRequest > 0 && setting.rowCountPerRequest < totalRowCount && !setting.onlyCurrentPage) {
                    var pageCount = Math.ceil(totalRowCount * 1.0 / setting.rowCountPerRequest);
                    gridExporter.exportChunk(setting, 0, pageCount);
                    return;
                }

                var newOptions = gridExporter.createGridOptionsForAllData(setting, needRequestAllData);
                gridExporter.createGridWithExport(setting, newOptions, exportAction);
            };

            gridExporter._getTotalRowCount = function (grid) {
                return grid.options.allowPaging ? grid.pageCount() * grid.options.pageSize : -1;
            };

            gridExporter.exportChunk = function (setting, pageIndex, pageCount, token) {
                var exportAction = function (exportSetting) {
                    var exportSource = gridExporter._exportSource(exportSetting);
                    if (pageIndex + 1 == pageCount) {
                        exporter.exportAllPages(setting.serviceUrl, exporter.toJSON(exportSource), token);
                    } else {
                        var data = {
                            token: token,
                            rows: exportSource.grid.body.rows
                        };
                        exporter.exportChunk(exportSetting, exporter.toJSON(data), function (token) {
                            return gridExporter.exportChunk(setting, pageIndex + 1, pageCount, token);
                        });
                    }
                };

                var newOptions = gridExporter.createGridOptionsForChunkData(setting, pageIndex);
                gridExporter.createGridWithExport(setting, newOptions, exportAction);
            };

            gridExporter.createGridOptionsForChunkData = function (setting, pageIndex) {
                var grid = setting.grid, oldOptions = grid.options, data, newOptions = $.extend(true, {}, oldOptions, {
                    scrollMode: "none",
                    allowPaging: oldOptions.allowPaging,
                    allowVirtualScrolling: false,
                    selectionMode: "none",
                    scrollingSettings: {
                        mode: "none",
                        freezingMode: "none",
                        staticColumnIndex: -1,
                        staticColumnsAlignment: "left",
                        staticRowIndex: -1,
                        virtualizationSettings: {
                            mode: "none",
                            rowHeight: 0,
                            columnWidth: 0
                        }
                    }
                });

                newOptions.pageIndex = pageIndex;
                newOptions.pageSize = setting.rowCountPerRequest;
                data = gridExporter._createChunkData(setting, pageIndex);

                wijmo.grid.traverse(newOptions.columns, function (column, columns) {
                    if (column._dynamic) {
                        // remove autogenerated columns
                        var idx = $.inArray(column, columns);
                        if (idx >= 0) {
                            columns.splice(idx, 1);
                        }
                    } else {
                        // restore original values
                        column.dataKey = column._originalDataKey;
                        column.headerText = column._originalHeaderText;
                    }
                });

                newOptions.data = data;
                return newOptions;
            };

            gridExporter._createChunkData = function (setting, pageIndex) {
                var grid = setting.grid, options = grid.options, oldData = options.data, newDataOptions;

                if (!oldData || !wijmo || !wijmo.data || !options.allowPaging || setting.onlyCurrentPage) {
                    return null;
                }

                newDataOptions = $.extend(true, {}, oldData.options || {}, { pageIndex: pageIndex, pageSize: setting.rowCountPerRequest, sort: oldData.sort(), filter: oldData.filter() });
                if (wijmo.data.ArrayDataView && oldData instanceof wijmo.data.ArrayDataView) {
                    return new wijmo.data.ArrayDataView($.extend(true, [], oldData.getSource()), newDataOptions);
                }

                if (wijmo.data["AjaxDataView"] && oldData instanceof wijmo.data["AjaxDataView"]) {
                    return new wijmo.data["AjaxDataView"](oldData.url, newDataOptions);
                }

                if (wijmo.data["ODataView"] && oldData instanceof wijmo.data["ODataView"]) {
                    return new wijmo.data["ODataView"](oldData.url, newDataOptions);
                }

                if (wijmo.data["BreezeDataView"] && oldData instanceof wijmo.data["BreezeDataView"]) {
                    return new wijmo.data["BreezeDataView"](oldData.query, oldData.manager, newDataOptions);
                }

                return null;
            };

            gridExporter.createGridOptionsForAllData = function (setting, needRequestAllData) {
                var grid = setting.grid, oldOptions = grid.options, data, newOptions = $.extend(true, {}, oldOptions, {
                    scrollMode: "none",
                    allowPaging: oldOptions.allowPaging,
                    allowVirtualScrolling: false,
                    selectionMode: "none",
                    scrollingSettings: {
                        mode: "none",
                        freezingMode: "none",
                        staticColumnIndex: -1,
                        staticColumnsAlignment: "left",
                        staticRowIndex: -1,
                        virtualizationSettings: {
                            mode: "none",
                            rowHeight: 0,
                            columnWidth: 0
                        }
                    }
                });

                if (needRequestAllData) {
                    newOptions.pageSize = grid.pageCount() * oldOptions.pageSize;
                    newOptions.pageIndex = 0;
                    data = gridExporter._createAllData(setting);
                }

                wijmo.grid.traverse(newOptions.columns, function (column, columns) {
                    if (column._dynamic) {
                        // remove autogenerated columns
                        var idx = $.inArray(column, columns);
                        if (idx >= 0) {
                            columns.splice(idx, 1);
                        }
                    } else {
                        // restore original values
                        column.dataKey = column._originalDataKey;
                        column.headerText = column._originalHeaderText;
                    }
                });

                newOptions.data = data || gridExporter._cloneData(setting.grid.dataView());
                return newOptions;
            };

            gridExporter.createGridWithExport = function (setting, options, exportAction) {
                options.rendered = gridExporter.createGridRendered(setting, exportAction);
                $("<table>").appendTo($(document.body)).wijgrid(options);
            };

            gridExporter.createGridRendered = function (setting, exportAction, container) {
                return function () {
                    var $e = $(this), newSetting = $.extend({}, setting);
                    newSetting.grid = $e.data(setting.grid.widgetFullName);
                    exportAction(newSetting);
                    setTimeout(function () {
                        newSetting.grid.destroy();
                        container = container || $e.closest(".wijmo-wijgrid");
                        $e.remove();
                        container.remove();
                    });
                };
            };

            gridExporter._createAllData = function (setting) {
                var grid = setting.grid, options = grid.options, oldData = options.data, newPageSize = grid.pageCount() * options.pageSize, newDataOptions;

                if (!oldData || !wijmo || !wijmo.data || !options.allowPaging || grid.pageCount() <= 1 || setting.onlyCurrentPage) {
                    return null;
                }

                newDataOptions = $.extend(true, {}, oldData.options || {}, { pageIndex: 0, pageSize: newPageSize, sort: oldData.sort(), filter: oldData.filter() });
                if (wijmo.data.ArrayDataView && oldData instanceof wijmo.data.ArrayDataView) {
                    return new wijmo.data.ArrayDataView($.extend(true, [], oldData.getSource()), newDataOptions);
                }

                if (wijmo.data["AjaxDataView"] && oldData instanceof wijmo.data["AjaxDataView"]) {
                    return new wijmo.data["AjaxDataView"](oldData.url, newDataOptions);
                }

                if (wijmo.data["ODataView"] && oldData instanceof wijmo.data["ODataView"]) {
                    return new wijmo.data["ODataView"](oldData.url, newDataOptions);
                }

                if (wijmo.data["BreezeDataView"] && oldData instanceof wijmo.data["BreezeDataView"]) {
                    return new wijmo.data["BreezeDataView"](oldData.query, oldData.manager, newDataOptions);
                }

                return null;
            };

            gridExporter._cloneData = function (dataView) {
                var newData = [], count = dataView.count(), i;
                for (i = 0; i < count; i++) {
                    newData.push($.extend(true, {}, dataView.item(i)));
                }
                ;
                return newData;
            };

            gridExporter._exportSource = function (setting) {
                var environmentInfo = wijmo.exporter.gridExporter._generateEnvironmentInfo();
                var exportSource = {
                    grid: wijmo.exporter.gridExporter._generateTemplate(new exportContext(setting.grid, environmentInfo)),
                    environmentInfo: environmentInfo,
                    exportFileType: setting.exportFileType
                };
                if (setting.fileName)
                    exportSource.fileName = setting.fileName;
                if (setting.pdf)
                    exportSource.pdf = setting.pdf;
                if (setting.excel)
                    exportSource.excel = setting.excel;
                return exportSource;
            };

            gridExporter._needRequestAllData = function (setting) {
                var grid = setting.grid, o = grid.options, isVirtualScrolling = o.allowVirtualScrolling, virtualScrollMode;
                if (!isVirtualScrolling && o.scrollingSettings && o.scrollingSettings.virtualizationSettings) {
                    virtualScrollMode = o.scrollingSettings.virtualizationSettings.mode;
                    if (virtualScrollMode === "both" || virtualScrollMode === "rows") {
                        isVirtualScrolling = true;
                    }
                }

                return (isVirtualScrolling && grid.options.totalRows > grid.dataView().getSource().length) || (o.allowPaging && grid.pageCount() > 1 && setting.onlyCurrentPage === false);
            };

            gridExporter._needNewSingleTable = function (setting) {
                return setting.grid.options.scrollMode !== "none";
            };

            // the length string's pattern should be like 0px
            gridExporter.pxToPt = function (lengthStr, dpi) {
                if (lengthStr == null)
                    return 0;
                lengthStr = $.trim(lengthStr).toLowerCase();
                var suffix = "px";
                if (lengthStr.indexOf(suffix, lengthStr.length - suffix.length) == -1) {
                    return 0;
                }
                var numberPart = parseFloat(lengthStr);
                if (isNaN(numberPart))
                    return 0;
                return numberPart / dpi * wijmo.exporter.gridExporter.pointPerInch;
            };

            gridExporter._generateEnvironmentInfo = function () {
                var location = window.location, baseUrl = location.protocol + "//" + location.hostname + (location.port && ":" + location.port) + "/", dpiTestDiv = $("<div style='height:1in;left:-100%;position: absolute;top:-100%;width:1in;'></div>").appendTo($(document.body));
                return {
                    baseUrl: baseUrl,
                    dpiX: dpiTestDiv.outerWidth(),
                    dpiY: dpiTestDiv.outerHeight(),
                    culture: navigator.language ? navigator.language : navigator.browserLanguage
                };
            };

            gridExporter._generateTemplate = function (context) {
                var $element = $(context.grid.element), style = wijmo.exporter.gridExporter._readStyle(context, $element), header = wijmo.exporter.gridExporter._readSection(context, $element.find(">thead"), 0 /* Header */), body = wijmo.exporter.gridExporter._readSection(context, $element.find(">tbody"), 1 /* Body */), footer = wijmo.exporter.gridExporter._readSection(context, $element.find(">tfoot"), 2 /* Footer */), $parent = $element.parent();
                if ($parent.hasClass("wijmo-wijgrid")) {
                    var combinedStyle = {};
                    $.extend(combinedStyle, wijmo.exporter.gridExporter._readStyle(context, $parent), style);
                    style = combinedStyle;
                }
                return {
                    colWidths: context.colWidths,
                    style: style,
                    header: header,
                    footer: footer,
                    body: body,
                    width: context.computedWidthToPt($element.css('width'))
                };
            };

            gridExporter._readSection = function (context, $section, sectionType) {
                context.currentSectionType = sectionType;
                return {
                    colInfos: sectionType === 1 /* Body */ ? context.colInfos : null,
                    style: wijmo.exporter.gridExporter._readStyle(context, $section),
                    rows: wijmo.exporter.gridExporter._readRows(context, $section),
                    height: context.computedHeightToPt($section.css('height'))
                };
            };

            gridExporter._getGroupLevel = function ($row) {
                var levelStr = $row.attr("aria-level");
                if (!levelStr) {
                    return 0;
                }

                return parseInt(levelStr);
            };

            gridExporter._isGroupHeader = function ($row) {
                return $row.hasClass("wijmo-wijgrid-groupheaderrow");
            };

            gridExporter._isGroupFooter = function ($row) {
                return $row.hasClass("wijmo-wijgrid-groupfooterrow");
            };

            gridExporter._readRows = function (context, $section) {
                if (!$section || !$section.length)
                    return null;
                var dataRowIndex = -1;
                return $section.find(">tr").map(function () {
                    var $row = $(this), rowType, templateType, row = { height: context.computedHeightToPt($row.css("height")) };

                    if (context.currentSectionType === 0 /* Header */) {
                        rowType = 1 /* Header */;
                        templateType = 3 /* HeaderTemplate */;
                    } else if (context.currentSectionType === 2 /* Footer */) {
                        rowType = 2 /* Footer */;
                        templateType = 4 /* FooterTemplate */;
                    } else if (gridExporter._isGroupHeader($row)) {
                        rowType = 3 /* GroupHeader */;
                        row.groupLevel = gridExporter._getGroupLevel($row);
                        templateType = context.createdGroupHeaderTemplates[row.groupLevel] ? 0 /* None */ : 5 /* GroupHeaderTemplate */;
                        context.createdGroupHeaderTemplates[row.groupLevel] = true;
                    } else if (gridExporter._isGroupFooter($row)) {
                        rowType = 4 /* GroupFooter */;
                        row.groupLevel = gridExporter._getGroupLevel($row);
                        templateType = context.createdGroupFooterTemplates[row.groupLevel] ? 0 /* None */ : 6 /* GroupFooterTemplate */;
                        context.createdGroupFooterTemplates[row.groupLevel] = true;
                    } else {
                        ++dataRowIndex;
                        rowType = 0 /* Data */;
                        if (dataRowIndex === 0) {
                            templateType = 1 /* Template */;
                        } else if (dataRowIndex === 1) {
                            templateType = 2 /* AltTemplate */;
                        } else {
                            templateType = 0 /* None */;
                        }
                    }

                    context.currentRowType = rowType;
                    context.currentRowTemplateType = templateType;

                    if (rowType != 0 /* Data */) {
                        row.type = rowType;
                    }

                    if (templateType != 0 /* None */) {
                        row.style = wijmo.exporter.gridExporter._readStyle(context, $row);
                        row.templateType = templateType;
                    }

                    row.cells = gridExporter._readCells(context, $row, dataRowIndex);
                    return row;
                }).get();
            };

            gridExporter._readCells = function (context, $row, rowIndex) {
                return $row.find(">th,>td").map(function (index) {
                    var $cell = $(this), cell = {}, cspan = wijmo.exporter.gridExporter._getSpan($cell, "colspan"), rspan = wijmo.exporter.gridExporter._getSpan($cell, "rowspan"), colIndex = wijmo.exporter.gridExporter._cellPos($cell).left, colInfo = context.colInfos[colIndex], innerCell = $cell.find(">.wijmo-wijgrid-innercell");

                    if (innerCell.length == 0)
                        innerCell = $cell;

                    if (colIndex != index)
                        cell.colIndex = colIndex;

                    if (rspan != 1)
                        cell.rowSpan = rspan;

                    if (cspan != 1)
                        cell.colSpan = cspan;

                    if (context.currentRowType === 0 /* Data */ && rowIndex > -1) {
                        switch (colInfo.type) {
                            case 2 /* Image */:
                                var $img = $cell.find("img");
                                if ($img.length != 0) {
                                    var imageInfo = {
                                        src: $img.attr("src"),
                                        height: context.computedHeightToPt($img.css("height")),
                                        width: context.computedWidthToPt($img.css("width"))
                                    };
                                    cell.value = imageInfo;
                                }
                                break;
                            case 3 /* Link */:
                                var $link = $cell.find("a");
                                if ($link.length != 0) {
                                    var linkInfo = {
                                        href: $link.attr("href"),
                                        text: $link.text()
                                    };
                                    cell.value = linkInfo;
                                }
                                break;
                            case 5 /* Html */:
                                cell.value = $cell.html();
                                break;
                            case 1 /* Text */:
                            case 4 /* Checkbox */:
                                cell.value = context.getDataValue(rowIndex, colIndex);
                                cell.text = $cell.text().replace(/\xA0/g, " ");
                                break;
                            default:
                                throw "Wrong column type!";
                        }
                    } else {
                        cell.text = $cell.text();
                    }

                    if (context.currentRowTemplateType != 0 /* None */) {
                        cell.style = wijmo.exporter.gridExporter._readStyle(context, $cell);
                        $.extend(cell.style, wijmo.exporter.gridExporter._readFontStyle(context, innerCell));
                    }

                    return cell;
                }).get();
            };

            gridExporter._readStyle = function (context, $element) {
                var style = {
                    backgroundColor: $element.css("backgroundColor"),
                    verticalAlign: $element.css("verticalAlign")
                };
                $.extend(style, wijmo.exporter.gridExporter._readBorderStyle(context, "Top", $element), wijmo.exporter.gridExporter._readBorderStyle(context, "Right", $element), wijmo.exporter.gridExporter._readBorderStyle(context, "Bottom", $element), wijmo.exporter.gridExporter._readBorderStyle(context, "Left", $element));
                return style;
            };

            gridExporter._readBorderStyle = function (context, borderType, $element) {
                var style = {}, colorProp = "border" + borderType + "Color", styleProp = "border" + borderType + "Style", widthProp = "border" + borderType + "Width", borderStyle = $element.css(styleProp);
                if (borderStyle != "none") {
                    var borderWidth = context.computedWidthToPt($element.css(widthProp));
                    if (borderWidth != 0) {
                        style[colorProp] = $element.css(colorProp);
                        style[styleProp] = borderStyle;
                        style[widthProp] = borderWidth;
                    }
                }
                return style;
            };

            gridExporter._readFontStyle = function (context, $element) {
                return {
                    paddingLeft: context.computedHeightToPt($element.css("paddingLeft")),
                    textAlign: $element.css("textAlign"),
                    color: $element.css("color"),
                    fontFamily: $element.css("fontFamily"),
                    fontWeight: $element.css("fontWeight"),
                    fontStyle: $element.css("fontStyle"),
                    fontSize: context.computedHeightToPt($element.css("fontSize")),
                    textDecoration: $element.css("textDecoration")
                };
            };

            gridExporter._cellPos = function ($cell, rescan) {
                var pos = $cell.data("cellPos");
                if (!pos || rescan) {
                    var $table = $cell.closest("table, thead, tbody, tfoot");
                    wijmo.exporter.gridExporter._scanTable($table);
                }
                pos = $cell.data("cellPos");
                return pos;
            };

            gridExporter._getSpan = function ($cell, spanName) {
                var span = $cell.attr(spanName);
                if (span) {
                    var spanNumber = parseInt(span);
                    if (!isNaN(spanNumber)) {
                        return spanNumber;
                    }
                }
                return 1;
            };

            gridExporter._scanTable = function ($table) {
                var m = [];
                $table.children("tr").each(function (y, row) {
                    $(row).children("td, th").each(function (x, cell) {
                        var $cell = $(cell), cspan = wijmo.exporter.gridExporter._getSpan($cell, "colspan"), rspan = wijmo.exporter.gridExporter._getSpan($cell, "rowspan"), tx, ty;
                        cspan = cspan ? cspan : 1;
                        rspan = rspan ? rspan : 1;
                        for (; m[y] && m[y][x]; ++x)
                            ;
                        for (tx = x; tx < x + cspan; ++tx) {
                            for (ty = y; ty < y + rspan; ++ty) {
                                if (!m[ty]) {
                                    m[ty] = [];
                                }
                                m[ty][tx] = true;
                            }
                        }
                        var pos = { top: y, left: x };
                        $cell.data("cellPos", pos);
                    });
                });
            };
            gridExporter.pointPerInch = 72;
            return gridExporter;
        })();
        exporter.gridExporter = gridExporter;

        var innerExportGrid = function (exportSettings, type, settings, serviceUrl) {
            var t, typeSetting = {}, sUrl, gridExportSetting;
            t = type === undefined ? "csv" : type;
            t = t.substr(0, 1).toUpperCase() + t.substr(1);
            if (typeof settings === "string" && arguments.length === 3) {
                sUrl = settings;
            } else {
                sUrl = serviceUrl === undefined ? "http://demos.componentone.com/ASPNET/ExportService/exportapi/grid" : serviceUrl;
                typeSetting = settings;
            }

            if (!$.isPlainObject(exportSettings)) {
                gridExportSetting = {
                    fileName: exportSettings === undefined ? "export" : exportSettings,
                    serviceUrl: sUrl,
                    grid: this,
                    exportFileType: wijmo.exporter.ExportFileType[t]
                };
                if (gridExportSetting.exportFileType === 3 /* Pdf */) {
                    gridExportSetting.pdf = typeSetting;
                }
                if (gridExportSetting.exportFileType === 0 /* Xls */ || gridExportSetting.exportFileType === 1 /* Xlsx */) {
                    gridExportSetting.excel = typeSetting;
                }
            } else {
                gridExportSetting = exportSettings;
            }
            gridExporter.exportFile(gridExportSetting);
        };

        if (wijmo.grid && wijmo.grid.wijgrid) {
            wijmo.grid.wijgrid.prototype.exportGrid = innerExportGrid;
        }

        if ($.wijmo.wijgrid) {
            $.wijmo.wijgrid.prototype.exportGrid = innerExportGrid;
        }
    })(wijmo.exporter || (wijmo.exporter = {}));
    var exporter = wijmo.exporter;
})(wijmo || (wijmo = {}));
;
/// <reference path="../wijevcal/jquery.wijmo.wijevcal.ts"/>
/// <reference path="exportUtil.ts" />
var wijmo;
(function (wijmo) {
    (function (exporter) {
        

        /** @ignore */
        var EventsCalendarExport = (function () {
            function EventsCalendarExport(serviceUrl, method) {
                this.serviceUrl = serviceUrl;
                this.method = method;
            }
            EventsCalendarExport.prototype.getExportData = function (options) {
                var result;
                this.options = options;
                this._handleExportOption();
                result = {
                    fileName: options.fileName,
                    width: options.width,
                    height: options.height,
                    type: options.type,
                    pdfSettings: options.pdfSetting,
                    styleString: options.styleString,
                    linkList: options.linkList,
                    theme: options.theme
                };
                if (this.method === 0 /* Content */) {
                    result.content = options.HTMLContent;
                } else {
                    result.options = options.widgetOptions;
                    result.widgetName = options.widgetName;
                }
                return exporter.toJSON(result, function (key, val) {
                    if (key === "type") {
                        switch (val) {
                            case 6 /* Bmp */:
                                return "bmp";
                            case 7 /* Gif */:
                                return "gif";
                            case 5 /* Jpg */:
                                return "jpg";
                            case 3 /* Pdf */:
                                return "pdf";
                            case 8 /* Tiff */:
                                return "tiff";
                            default:
                                return "png";
                        }
                    }
                    return val;
                });
            };

            EventsCalendarExport.prototype._handleExportOption = function () {
                var o = this.options, styleString, linkList = new Array();
                if (o.widget) {
                    if (this.method === 0 /* Content */) {
                        o.HTMLContent = o.widget.element[0].outerHTML;
                    } else {
                        o.widgetName = this._getWidgetName();
                        o.widgetOptions = exporter.toJSON(o.widget.options, function (k, v) {
                            if (v != null) {
                                if (k === "webServiceUrl") {
                                    return "";
                                }
                                return v;
                            }
                        });
                    }

                    $.each($("head").children(), function (index, element) {
                        if (element.tagName === "STYLE") {
                            if ($(element).text()) {
                                styleString += $(element).text();
                            }
                        } else if (element.tagName === "LINK") {
                            linkList.push({
                                className: element.className,
                                href: element.href,
                                rel: element.rel,
                                linkType: element.type
                            });
                        }
                    });
                    o.styleString = styleString;
                    o.linkList = linkList;
                    o.width = o.widget.element.width();
                    o.height = o.widget.element.height();
                }
            };

            EventsCalendarExport.prototype._getWidgetName = function () {
                return this.options.widget ? "wijevcal" : "";
            };
            return EventsCalendarExport;
        })();
        exporter.EventsCalendarExport = EventsCalendarExport;

        

        /** @ignore */
        function innerExportEventsCalendar(exportSettings, type, settings, serviceUrl, exportMethod) {
            var t, mode, pdfSetting = {}, sUrl, data, self = this, o = self.options, eventsCalendarExporter, options, eventsCalendarExportSettings;
            t = type === undefined ? "png" : type;
            t = t.substr(0, 1).toUpperCase() + t.substr(1);
            mode = exportMethod === undefined ? "Options" : exportMethod;
            mode = mode.substr(0, 1).toUpperCase() + mode.substr(1);
            if (typeof settings === "string" && arguments.length === 3) {
                sUrl = settings;
            } else {
                sUrl = serviceUrl === undefined ? "http://demos.componentone.com/ASPNET/ExportService/exportapi/EventsCalendar" : serviceUrl;
                pdfSetting = settings;
            }

            if (!$.isPlainObject(exportSettings)) {
                eventsCalendarExportSettings = {
                    serviceUrl: sUrl,
                    fileName: exportSettings === undefined ? "export" : exportSettings,
                    pdf: pdfSetting,
                    method: exporter.ExportMethod[mode],
                    exportFileType: wijmo.exporter.ExportFileType[t]
                };
            } else {
                eventsCalendarExportSettings = exportSettings;
            }

            eventsCalendarExporter = new EventsCalendarExport(eventsCalendarExportSettings.serviceUrl, eventsCalendarExportSettings.method);
            options = {
                fileName: eventsCalendarExportSettings.fileName,
                widget: self,
                type: eventsCalendarExportSettings.exportFileType,
                pdfSetting: eventsCalendarExportSettings.pdf,
                theme: !!o.theme ? o.theme : eventsCalendarExportSettings.theme
            };
            data = eventsCalendarExporter.getExportData(options);
            exporter.exportFile(eventsCalendarExportSettings, data);
        }
        exporter.innerExportEventsCalendar = innerExportEventsCalendar;

        if (wijmo.evcal && wijmo.evcal.wijevcal) {
            wijmo.evcal.wijevcal.prototype.exportEventsCalendar = innerExportEventsCalendar;
        }

        if ($.wijmo.wijevcal) {
            $.wijmo.wijevcal.prototype.exportEventsCalendar = innerExportEventsCalendar;
        }
    })(wijmo.exporter || (wijmo.exporter = {}));
    var exporter = wijmo.exporter;
})(wijmo || (wijmo = {}));
;
/// <reference path="../Base/jquery.wijmo.widget.ts"/>
/// <reference path="../wijgrid/Grid.ts/Grid/wijgrid.ts"/>
/// <reference path="../wijmenu/jquery.wijmo.wijmenu.ts"/>
/// <reference path="../wijdialog/jquery.wijmo.wijdialog.ts"/>
/// <reference path="../wijsplitter/jquery.wijmo.wijsplitter.ts"/>
/// <reference path="../wijtree/jquery.wijmo.wijtree.ts"/>
/// <reference path="../wijpager/jquery.wijmo.wijpager.ts"/>
/// <reference path="../external/declarations/globalize.d.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /** @ignore */
    (function (_tilelist) {
        var $ = jQuery, tilelistCssSuffix = "wijmo-wijtilelist", tilelistCss = $.extend(new wijmo.wijmo_css(), {
            tilelist: tilelistCssSuffix,
            tilelistList: tilelistCssSuffix + "-list",
            tilelistItem: tilelistCssSuffix + "-item",
            tilelistItemStateDefault: "",
            tilelistLink: tilelistCssSuffix + "-link",
            tilelistContent: tilelistCssSuffix + "-content",
            tilelistIconContainer: tilelistCssSuffix + "-iconcontainer"
        });

        

        

        

        /**
        * @ignore
        */
        var wijtilelist = (function (_super) {
            __extends(wijtilelist, _super);
            function wijtilelist() {
                _super.apply(this, arguments);
            }
            wijtilelist.prototype._create = function () {
                var self = this;

                _super.prototype._create.call(this);

                self._createTileList();
                self._attachEvents();
            };

            wijtilelist.prototype._setOption = function (key, value) {
                if (key === "data") {
                    this._setData(value);
                    return;
                }

                _super.prototype._setOption.call(this, key, value);
            };

            wijtilelist.prototype._createTile = function (tile) {
                var self = this, $tile = $("<li>"), $link = $("<a>"), $icon = $("<img>"), $iconcontainer = $("<div>"), realTile = $.extend(true, {}, tile), css = self.options.wijCSS, iconFormat, stateHover = css.stateHover;

                $tile.hover(function () {
                    $(this).addClass(stateHover);
                }, function () {
                    $(this).removeClass(stateHover);
                });

                //fire tileCreating event.
                if (self._onTileCreating({
                    tile: realTile,
                    element: $tile
                }) === false) {
                    return $tile;
                }

                $tile.addClass(css.tilelistItem + " " + css.tilelistItemStateDefault).attr("title", realTile.hint);
                $link.addClass(css.tilelistLink).attr("href", "javascript:void(0)").appendTo($tile);
                $iconcontainer.addClass(css.tilelistIconContainer).appendTo($link);

                if (iconFormat = realTile.iconFormat) {
                    $icon = iconFormat();
                } else {
                    $icon.attr("alt", realTile.text).attr("src", realTile.path).attr("align", "bottom");
                }

                $icon.appendTo($iconcontainer);

                $("<span>").addClass(css.tilelistContent).text(realTile.text).appendTo($link);

                //fire tileCreated event.
                self._onTileCreated({
                    tile: tile,
                    element: $tile
                });

                return $tile;
            };

            wijtilelist.prototype._createTiles = function (tiles) {
                var self = this, $tiles = $("<ul>");

                $tiles.addClass(self.options.wijCSS.tilelistList);

                if (tiles) {
                    $.each(tiles, function (idx, tile) {
                        $tiles.append(self._createTile(tile));
                    });
                }

                return $tiles;
            };

            wijtilelist.prototype._createTileList = function () {
                var self = this, o = self.options, css = o.wijCSS, ele = self.element;

                ele.addClass(css.widget + " " + css.tilelist);

                if (o.data && o.data.length) {
                    ele.append(self._createTiles(o.data));
                }
            };

            wijtilelist.prototype._disposeTiles = function ($tilelist) {
                $tilelist && $tilelist.remove();
            };

            wijtilelist.prototype._setData = function (data) {
                var self = this, $tilelist = self.element.find("ul:first");

                self.options.data = data;
                self._$focusTile = null;

                //dispose the old tile list("ul").
                if ($tilelist) {
                    self._disposeTiles($tilelist);
                }

                //generate tile list again("ul").
                $tilelist = self._createTiles(data);
                self.element.append($tilelist);
            };

            wijtilelist.prototype._setTileFocus = function ($tile) {
                var self = this, css = self.options.wijCSS, stateFocus = css.stateFocus;

                //remove focus state from the old focus tile.
                self.element.find("li." + stateFocus).removeClass(stateFocus);

                //set focus state to current tile and set focus to its link element
                //(only link element can get focus).
                $tile && $tile.addClass(stateFocus).find("." + css.tilelistLink).focus();

                self._$focusTile = $tile;
            };

            wijtilelist.prototype._attachEvents = function () {
                var self = this, widgetName = self.widgetName;

                //select tile
                self.element.on("click." + widgetName, $.proxy(self._handleClick, self)).on("keydown." + widgetName, $.proxy(self._handleKeyDown, self));
            };

            wijtilelist.prototype._handleClick = function (e) {
                var self = this;

                self.selectTile(self._getTileElement($(e.target)), e.ctrlKey);
            };

            wijtilelist.prototype._handleKeyDown = function (e) {
                var self = this, keyCode = $.ui.keyCode;

                switch (e.keyCode) {
                    case keyCode.LEFT:
                        self._movePrev();
                        break;
                    case keyCode.UP:
                        self._moveUp();
                        break;
                    case keyCode.RIGHT:
                        self._moveNext();
                        break;
                    case keyCode.DOWN:
                        self._moveDown();
                        break;
                    default:
                        return;
                }

                e.preventDefault();
            };

            wijtilelist.prototype._getTileElement = function (element) {
                return element.closest("li." + this.options.wijCSS.tilelistItem);
            };

            /**
            * @ignore
            */
            wijtilelist.prototype.selectTile = function ($tile, ctrlKey) {
                var self = this, ele = self.element, o = self.options, stateHighlight = o.wijCSS.stateHighlight, $oldSelection = ele.find("li").filter(function () {
                    return $(this).hasClass(stateHighlight);
                }), $newSelection;

                if (!$tile || !$tile.length) {
                    return;
                }

                if (!o.allowMultipleSelection || !ctrlKey) {
                    $oldSelection.removeClass(stateHighlight);
                    $tile.addClass(stateHighlight);
                } else {
                    $tile.toggleClass(stateHighlight);
                }

                $newSelection = ele.find("li").filter(function () {
                    return $(this).hasClass(stateHighlight);
                });

                if ($oldSelection !== $newSelection) {
                    self._onSelectionChanged({
                        oldSelection: self._createSelectionArgs($oldSelection),
                        newSelection: self._createSelectionArgs($newSelection)
                    });
                }

                self._setTileFocus($tile);
            };

            wijtilelist.prototype._createSelectionArgs = function ($selection) {
                var self = this, data = self.options.data, selectionArgs = [], $tiles = self.element.find("li." + self.options.wijCSS.tilelistItem);

                $.each($selection, function (idx, val) {
                    selectionArgs.push({
                        tile: data[$tiles.index(val)],
                        element: $(val)
                    });
                });

                return selectionArgs;
            };

            wijtilelist.prototype._getVSiblingTile = function ($curFocusTile, above) {
                var self = this, ele = self.element, css = self.options.wijCSS, $tiles = ele.find("li." + css.tilelistItem), width = ele.find("ul." + css.tilelistList).width(), oldTileIdx, tileWidth, rowCount, tileIdx;

                if (!$curFocusTile || !width) {
                    return null;
                }

                oldTileIdx = $tiles.index($curFocusTile);
                tileWidth = $curFocusTile.outerWidth(true);
                rowCount = Math.floor(width / tileWidth);

                tileIdx = oldTileIdx + (above ? -1 : 1) * rowCount;

                //current tile is on the top row or bottom row.
                if (tileIdx < 0 || tileIdx >= Math.ceil($tiles.length / rowCount) * rowCount) {
                    return $curFocusTile;
                } else if (tileIdx >= $tiles.length) {
                    tileIdx = $tiles.length - 1;
                }

                return $tiles.eq(tileIdx);
            };

            wijtilelist.prototype._movePrev = function () {
                var self = this, $oldFocusTile = self._$focusTile;

                self.selectTile($oldFocusTile && $oldFocusTile.prev());
            };

            wijtilelist.prototype._moveNext = function () {
                var self = this, $oldFocusTile = self._$focusTile;

                self.selectTile($oldFocusTile && $oldFocusTile.next());
            };

            wijtilelist.prototype._moveUp = function () {
                var self = this, $oldFocusTile = self._$focusTile, $tile = $oldFocusTile && self._getVSiblingTile($oldFocusTile, true);

                if ($tile == $oldFocusTile) {
                    return;
                }

                self.selectTile($tile);
            };

            wijtilelist.prototype._moveDown = function () {
                var self = this, $oldFocusTile = self._$focusTile, $tile = $oldFocusTile && self._getVSiblingTile($oldFocusTile, false);

                if ($tile == $oldFocusTile) {
                    return;
                }

                self.selectTile($tile);
            };

            wijtilelist.prototype._onTileCreating = function (args) {
                return this._trigger("tileCreating", null, args);
            };

            wijtilelist.prototype._onTileCreated = function (args) {
                return this._trigger("tileCreated", null, args);
            };

            wijtilelist.prototype._onSelectionChanged = function (args) {
                return this._trigger("selectionChanged", null, args);
            };

            /**
            * @ignore
            */
            wijtilelist.prototype.setFocus = function () {
                var self = this, $oldFocusTile = self._$focusTile;

                if ($oldFocusTile && $oldFocusTile.length > 0) {
                    self._setTileFocus($oldFocusTile);
                } else {
                    self.selectTile(self.element.find("li." + self.options.wijCSS.tilelistItem).first());
                }
            };
            return wijtilelist;
        })(wijmo.wijmoWidget);
        _tilelist.wijtilelist = wijtilelist;

        var wijtilelist_options = (function () {
            function wijtilelist_options() {
                this.data = null;
                this.allowMultipleSelection = false;
                this.tileCreating = undefined;
                this.tileCreated = undefined;
                this.selectionChanged = undefined;
                this.wijCSS = tilelistCss;
            }
            return wijtilelist_options;
        })();

        wijtilelist.prototype.widgetEventPrefix = "wijtilelist";
        wijtilelist.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijtilelist_options());
        $.wijmo.registerWidget("wijtilelist", wijtilelist.prototype);
    })(wijmo.tilelist || (wijmo.tilelist = {}));
    var tilelist = wijmo.tilelist;
})(wijmo || (wijmo = {}));



var wijmo;
(function (wijmo) {
    (function (fileexplorer) {
        var $ = jQuery, cssFileExplorer = "wijmo-wijfileexplorer", eventNameSpaceSuffix = ".wijfileexplorer", commandDataName = "wijfileexplorercommand", dragItemsDataName = "wijfileexplorerDragItems", css = $.extend(new wijmo.wijmo_css(), {
            fileExplorer: cssFileExplorer,
            loadingOverlay: cssFileExplorer + "-overlay",
            loadingText: cssFileExplorer + "-loadingtext",
            itemsViewContainer: cssFileExplorer + "-itemsviewcontainer",
            emptyFolderTip: cssFileExplorer + "-emptyfoldertip",
            //splitter
            splitterV: "wijmo-wijsplitter-vertical",
            splitterVPanel1: "wijmo-wijsplitter-v-panel1",
            splitterVPanel2: "wijmo-wijsplitter-v-panel2",
            splitterVPanel1Content: "wijmo-wijsplitter-v-panel1-content",
            splitterVPanel2Content: "wijmo-wijsplitter-v-panel2-content",
            //fileExplorer
            folderExpandedIcon: 'ui-icon-folder-open',
            folderCollapsedIcon: 'ui-icon-folder-collapsed',
            documentIcon: 'ui-icon-document',
            folderItem: cssFileExplorer + "-folder",
            fileItem: cssFileExplorer + "-file",
            //toolbar
            toolbar: cssFileExplorer + "-toolbar",
            toolbarBack: cssFileExplorer + "-back",
            toolbarForward: cssFileExplorer + "-forward",
            toolbarOpen: cssFileExplorer + "-open",
            toolbarRefresh: cssFileExplorer + "-refresh",
            toolbarNewFolder: cssFileExplorer + "-newfolder",
            toolbarDelete: cssFileExplorer + "-delete",
            toolbarSetDetailViewMode: cssFileExplorer + "-grid",
            toolbarSetThumbnailViewMode: cssFileExplorer + "-thumbnail",
            toolbarUploader: cssFileExplorer + "-uploader",
            //addressbar
            address: cssFileExplorer + "-address",
            addressPanel: cssFileExplorer + "-addresspanel",
            addressBar: cssFileExplorer + "-addressbar",
            filter: cssFileExplorer + "-filter",
            filterPanel: cssFileExplorer + "-filterpanel",
            addressBarFullWidth: cssFileExplorer + "-addressbar-fullwidth",
            //filetree
            fileTree: cssFileExplorer + "-filetree",
            tvLink: "wijmo-wijtree-link",
            //container
            gridContainer: cssFileExplorer + "-gvContainer",
            listViewContainer: cssFileExplorer + "-lvContainer",
            //gridview
            grid: cssFileExplorer + "-gridview",
            sizeContent: cssFileExplorer + "-sizecontent",
            gridRow: "wijmo-wijgrid-row",
            gridInnerCell: "wijmo-wijgrid-innercell",
            //thumbnail view
            thumbnailView: cssFileExplorer + "-listview",
            tileItem: "wijmo-wijtilelist-item",
            tileContent: "wijmo-wijtilelist-content",
            contentItem: cssFileExplorer + "-content",
            contentItemContainer: cssFileExplorer + "-contentcontainer",
            link: cssFileExplorer + "-link",
            dragContent: cssFileExplorer + "-dragcontent"
        }), viewMode = {
            detail: "detail",
            thumbnail: "thumbnail"
        }, explorerMode = {
            "default": "default",
            fileTree: "fileTree"
        }, hostRootOperator = "~", forwardSlash = "/", backwardSlash = "\\", backwardSlashRegExp = /\\/g, visibleControls = {
            toolbar: "toolbar",
            addressBox: "addressBox",
            filterBox: "filterTextBox",
            treeView: "treeView",
            detailView: "grid",
            thumbnailView: "listView",
            contextMenu: "contextMenu"
        }, ajaxCommands = {
            getHostUri: "GetHostUri",
            getItems: "GetItems",
            paste: "Paste",
            move: "Move",
            "delete": "Delete",
            newFolder: "CreateDirectory",
            rename: "Rename"
        }, columnNames = {
            name: "name",
            size: "size"
        }, nameColumnIndex = 0, sizeColumnIndex = 1, sortDirectionNames = {
            ascending: "ascending",
            descending: "descending"
        }, filterTimeout = 300, showLoadingTimout = 500, defaultFilterExpression = "", defaultSortDirection = sortDirectionNames.ascending, defaultPageIndex = 0, defaultPageCount = 1, defaultSortExpression = columnNames.name, defaultSearchPatterns = ["*.*"], defaultShortcuts = {
            focusFileExplorer: "Ctrl+F2",
            focusTreeView: "Shift+3",
            focusToolBar: "Shift+1",
            focusGrid: "Shift+4",
            focusAddressBar: "Shift+2",
            popupWindowClose: "Esc",
            focusPager: "Shift+5",
            contextMenu: "Shift+M",
            back: "Ctrl+K",
            forward: "Ctrl+L",
            open: "Enter",
            refresh: "Ctrl+F3",
            newFolder: "Shift+N",
            "delete": "Delete",
            uploadFile: "Ctrl+U"
        };

        function arraysEqual(a, b) {
            if (a === b) {
                return true;
            }

            if (a == null || b == null) {
                return false;
            }

            if (a.length != b.length) {
                return false;
            }

            for (var i = 0; i < a.length; ++i) {
                if ($.inArray(a[i], b) === -1) {
                    return false;
                }
            }

            return true;
        }

        function findItemByPath(items, path) {
            for (var index = 0, length = items.length; index < length; index++) {
                if (items[index].path === path) {
                    return items[index];
                }
            }

            return null;
        }

        function ensureFolderSeparator(path) {
            var folderSeparator = getFolderSeparator(path);

            return path[path.length - 1] === folderSeparator ? path : path + folderSeparator;
        }

        function removeLastFolderSeparator(path) {
            var folderSeparator = getFolderSeparator(path);

            return path[path.length - 1] === folderSeparator ? path.substring(0, path.length - 1) : path;
        }

        function getFolderSeparator(path) {
            return path && path.indexOf(forwardSlash) !== -1 ? forwardSlash : backwardSlash;
        }

        function combinePaths(items) {
            var resultItems = [], index = 0, length = items.length, item, existParentPath;
            items.sort(function (a, b) {
                return a.path > b.path ? 1 : (a.path > b.path ? -1 : 0);
            });
            for (; index < length; index++) {
                item = items[index];
                if (!item.isFolder) {
                    resultItems.push(item);
                    continue;
                }

                existParentPath = false;
                for (var resultIndex = 0, resultLength = resultItems.length; resultIndex < resultLength; resultIndex++) {
                    var resultItem = resultItems[resultIndex];
                    if (!resultItem.isFolder) {
                        continue;
                    }

                    if (resultItem.path.indexOf(item.path) > -1) {
                        existParentPath = true;
                        break;
                    }
                }

                if (!existParentPath) {
                    resultItems.push(item);
                }
            }

            return resultItems;
        }

        function isAncestorFolder(mayAncestorPath, mayDescendantPath) {
            return mayDescendantPath.indexOf(ensureFolderSeparator(mayAncestorPath)) === 0;
        }

        function isParentFolder(mayParentPath, mayChildPath) {
            var leftPath, folderSeparator = getFolderSeparator(mayParentPath);
            mayParentPath = ensureFolderSeparator(mayParentPath);
            if (!isAncestorFolder(mayParentPath, mayChildPath)) {
                return false;
            }

            leftPath = removeLastFolderSeparator(mayChildPath.substring(mayParentPath.length));
            return leftPath.indexOf(folderSeparator) === -1;
        }

        function isFolder(element) {
            return $(element).hasClass(css.folderItem);
        }

        function resolveUri(uri) {
            return !uri ? "" : uri.replace(backwardSlashRegExp, forwardSlash);
        }

        function getUriWithHostUri(hostUri, path) {
            var folderSeparator = getFolderSeparator(path);
            if (path[0] !== hostRootOperator || path[1] !== folderSeparator) {
                return resolveUri(path);
            }

            if (hostUri == null) {
                hostUri = "";
            }

            if (hostUri.length > 0) {
                hostUri = ensureFolderSeparator(hostUri);
            }

            // replace the first 2 chars "~/" with host uri
            return resolveUri(hostUri + path.substring(2));
        }

        function getItemName(path, withoutFileExtension) {
            var index, folderSeparator = getFolderSeparator(path), name = removeLastFolderSeparator(path).split(folderSeparator).pop();
            if (!withoutFileExtension) {
                return name;
            }

            index = getItemName(path).indexOf(".");
            return index === -1 ? name : name.substring(0, index);
        }

        function getFileExtension(path) {
            var name = getItemName(path), index = getItemName(path).indexOf(".");
            return index === -1 ? "" : name.substring(index + 1);
        }

        function getParentPath(path) {
            var folderSeparator = getFolderSeparator(path);

            return path.substring(0, removeLastFolderSeparator(path).lastIndexOf(folderSeparator));
        }

        /** Convert a string to camelCase */
        function toCamelCase(text) {
            return $.map(text.split("-"), function (item, index) {
                if (!item) {
                    return "";
                }
                return (index === 0 ? item.charAt(0).toLowerCase() : item.charAt(0).toUpperCase()) + item.substring(1);
            }).join("");
        }

        // get the width of element's padding, border and margin
        function getBoxOuterAreaWidth(elem) {
            if (!elem) {
                return 0;
            }

            var $elem = $(elem);
            if (!$elem.length) {
                return 0;
            }

            return $elem.outerWidth(true) - $elem.width();
        }

        /** @widget */
        var wijfileexplorer = (function (_super) {
            __extends(wijfileexplorer, _super);
            function wijfileexplorer() {
                _super.apply(this, arguments);
            }
            // Begin Init
            wijfileexplorer.prototype._create = function () {
                var self = this;
                _super.prototype._create.call(this);
                self._initDataOptions();
                self._initCommands();
                self._createInnerControls();
                self._optionsUpdated();
                self._initMembers();
                self._attachEvents();
            };

            wijfileexplorer.prototype._getGlobalEventNameSpaceSuffix = function () {
                var self = this;
                return self._globalEventNameSpaceSuffix || (self._globalEventNameSpaceSuffix = "." + self.element.uniqueId().attr("id"));
            };

            wijfileexplorer.prototype._attachEvents = function () {
                var self = this, globalEventNameSpaceSuffix = self._getGlobalEventNameSpaceSuffix();

                //listerning shortcuts events
                $(document).on("keydown" + globalEventNameSpaceSuffix, function (e) {
                    //Don't handle keyDown when contextmenu is opened.
                    if (self._contextMenu && self._contextMenu.is(":visible")) {
                        return;
                    }

                    //Move focus
                    if (e.keyCode === $.ui.keyCode.TAB) {
                        if (self._moveFocus(!e.shiftKey)) {
                            e.preventDefault();
                        }
                        return;
                    } else if (e.keyCode === $.ui.keyCode.ENTER) {
                        if (self._handleEnterKeyDown()) {
                            return;
                        }
                    }

                    return self._processShortcut(e);
                }).on("mousedown" + globalEventNameSpaceSuffix, function (e) {
                    if (!self._isChildElement($(e.target))) {
                        self.element.find("." + self._focusCss).removeClass(self._focusCss);
                    }
                });
            };

            wijfileexplorer.prototype._isChildElement = function ($el) {
                return $el.closest("." + css.fileExplorer).length > 0;
            };

            wijfileexplorer.prototype._handleEnterKeyDown = function () {
                var self = this, $focusedEl;

                $focusedEl = self.element.find("li." + self._focusCss);
                if ($focusedEl.parents("." + css.toolbar).length || $focusedEl.parents("div.wijmo-wijpager").length > 0) {
                    $focusedEl.find("a").click();
                    return true;
                }

                return false;
            };

            wijfileexplorer.prototype._getCurrentFocusedItem = function () {
                var self = this, $focusedEl = self.element.find("li." + self._focusCss).first();

                if (!$focusedEl.length || (!$focusedEl.parentsUntil("." + css.toolbar).length && !$focusedEl.parentsUntil(".wijmo-wijpager").length)) {
                    return null;
                }

                return $focusedEl;
            };

            wijfileexplorer.prototype._getNextFocusableItem = function (forward) {
                var self = this, $focusedEl = self._getCurrentFocusedItem();

                if ($focusedEl && $focusedEl.length) {
                    return $focusedEl[forward ? "next" : "prev"]();
                }

                return null;
            };

            wijfileexplorer.prototype._moveFocus = function (forward) {
                var self = this, $sibling = self._getNextFocusableItem(forward);

                if ($sibling && $sibling.length) {
                    self._setFocus($sibling, $sibling, $sibling.parent());
                    return true;
                }

                return false;
            };

            wijfileexplorer.prototype._initMembers = function () {
                var self = this, wijCSS = self.options.wijCSS;

                self._focusCss = wijCSS.stateFocus;
                self._activeCss = wijCSS.stateActive;
            };

            wijfileexplorer.prototype._optionsUpdated = function () {
                var self = this;
                self._layoutOptionsUpdated();
                self._enableOpenFileUpdated();
                self._enableCreateNewFolderUpdated();
                self._enableCopyUpdated();
                self._allowMultipleSelectionUpdated();
                self._disabledUpdated();
                self._createRootNodes();
                self._executeWithHostUri();
                self._loadCurrentFolder();
            };

            wijfileexplorer.prototype._loadCurrentFolder = function () {
                var self = this, showItemsView = self._showingControls[visibleControls.detailView] || self._showingControls[visibleControls.thumbnailView];

                if (showItemsView && !self._data()) {
                    self._openFolder(self._createCurrentStateRequest(), function () {
                        return self._expand(self._getNodeByPath(self.options.currentFolder));
                    });
                    return;
                }

                self._currentFolderUpdated();
                self._expand(self._getNodeByPath(self.options.currentFolder));
            };

            wijfileexplorer.prototype._createRootNodes = function () {
                var self = this, rootItems = self._getTreeInitData();

                self._updateTreeViewData(null, rootItems);
            };

            /**
            * @ignore
            */
            wijfileexplorer.prototype._getTreeInitData = function () {
                var self = this;
                return self._enableAjax() ? $.map(self._getRootPaths(), function (path) {
                    return { path: path, isFolder: true, hasSubFolders: true, hasChildren: true };
                }) : self._data();
            };

            wijfileexplorer.prototype._selectCurrentFolderTreeNode = function () {
                this._selectTreeNode(this.options.currentFolder);
            };

            wijfileexplorer.prototype._selectTreeNode = function (path) {
                var self = this, node = self._getNodeByPath(path);
                if (!node) {
                    return;
                }

                self._setSelection({
                    path: node.options.value,
                    isFolder: isFolder(node.element),
                    hasChildren: node.options.hasChildren,
                    operatingArea: 0 /* TreeView */
                });

                if (!node.options.selected) {
                    node.select(true);
                }
            };

            wijfileexplorer.prototype.destroy = function () {
                var self = this, wijCSS = self.options.wijCSS, globalEventNameSpaceSuffix = self._getGlobalEventNameSpaceSuffix();

                if (self._filterTimer) {
                    clearTimeout(self._filterTimer);
                    self._filterTimer = null;
                }

                if (self._showLoadingLayerTimer) {
                    clearTimeout(self._showLoadingLayerTimer);
                    self._showLoadingLayerTimer = null;
                }

                self._contextMenu && self._contextMenu.data("wijmo-wijmenu") && self._contextMenu.wijmenu("destroy");
                self._dialog && self._dialog.data("wijmo-wijdialog") && self._dialog.wijdialog("destroy");
                self._treeView && self._treeView.data("wijmo-wijtree") && self._treeView.wijtree("destroy");
                self._pager && self._pager.data("wijmo-wijpager") && self._pager.wijpager("destroy");
                self._detailView && self._detailView.data("wijmo-wijgrid") && self._detailView.wijgrid("destroy");
                self._thumbnailView && self._thumbnailView.data("wijmo-wijtilelist") && self._thumbnailView.wijtilelist("destroy");
                self._splitter && self._splitter.data("wijmo-wijsplitter") && self._splitter.wijsplitter("destroy");

                $(document).off(globalEventNameSpaceSuffix);
                $(window).off(globalEventNameSpaceSuffix);

                self.element.removeClass(wijCSS.widget + " " + css.fileExplorer + " " + wijCSS.helperReset).attr("tabindex", "").off(eventNameSpaceSuffix).empty().removeUniqueId();

                _super.prototype.destroy.call(this);
            };

            wijfileexplorer.prototype._initCommands = function () {
                var self = this;
                self._commands = {
                    open: new fileExplorerCommand("open", function () {
                        return self._open();
                    }, self.localizeString("commandOpen", "Open")),
                    "delete": new fileExplorerCommand("delete", function () {
                        return self._delete();
                    }, self.localizeString("commandDelete", "Delete")),
                    refresh: new fileExplorerCommand("refresh", function () {
                        return self.refresh();
                    }, self.localizeString("commandRefresh", "Refresh")),
                    rename: new fileExplorerCommand("rename", function () {
                        return self._rename();
                    }, self.localizeString("commandRename", "Rename")),
                    newFolder: new fileExplorerCommand("newFolder", function () {
                        return self._newFolder();
                    }, self.localizeString("commandNewFolder", "New Folder")),
                    copy: new fileExplorerCommand("copy", function () {
                        return self._copy();
                    }, self.localizeString("commandCopy", "Copy")),
                    paste: new fileExplorerCommand("paste", function () {
                        return self._paste();
                    }, self.localizeString("commandPaste", "Paste")),
                    back: new fileExplorerCommand("back", function () {
                        return self._back();
                    }, self.localizeString("commandBack", "Back")),
                    forward: new fileExplorerCommand("forward", function () {
                        return self._forward();
                    }, self.localizeString("commandForward", "Forward")),
                    setDetailViewMode: new fileExplorerCommand("setDetailViewMode", function () {
                        return self._setOption("viewMode", viewMode.detail);
                    }, self.localizeString("commandSetDetailViewMode", "Detail View Mode")),
                    setThumbnailViewMode: new fileExplorerCommand("setThumbnailViewMode", function () {
                        return self._setOption("viewMode", viewMode.thumbnail);
                    }, self.localizeString("commandSetThumbnailViewMode", "Thumbnail View Mode")),
                    focusFileExplorer: new fileExplorerCommand("focusFileExplorer", function () {
                        return self._focusFileExplorer();
                    }),
                    focusToolBar: new fileExplorerCommand("focusToolBar", function () {
                        return self._focusToolBar();
                    }),
                    focusTreeView: new fileExplorerCommand("focusTreeView", function () {
                        return self._focusTreeView();
                    }),
                    focusGrid: new fileExplorerCommand("focusGrid", function () {
                        return self._focusGrid();
                    }),
                    focusPager: new fileExplorerCommand("focusPager", function () {
                        return self._focusPager();
                    }),
                    focusAddressBar: new fileExplorerCommand("focusAddressBar", function () {
                        return self._focusAddressBar();
                    }),
                    popupWindowClose: new fileExplorerCommand("popupWindowClose", function () {
                        return self._popupWindowClose();
                    }),
                    contextMenu: new fileExplorerCommand("contextMenu", function () {
                        return self._openContextMenu();
                    })
                };
            };

            wijfileexplorer.prototype._createInnerControls = function () {
                var self = this, wijCSS = self.options.wijCSS;

                self._showingControls = {};
                self.element.addClass(wijCSS.widget + " " + css.fileExplorer + " " + wijCSS.helperReset).attr("tabindex", "-1");

                self._createToolbar();
                self._createAddressBar();
                self._createSplitter();
                self._createDialog();
                self._createContextMenu();
            };

            wijfileexplorer.prototype._setDialogButtons = function (showButtons) {
                var self = this, buttons = null;
                if (showButtons) {
                    buttons = [
                        {
                            text: self.localizeString("dialogOK", "OK"), click: function () {
                                self._dialogOk && self._dialogOk(self._dialogInput.val());
                                $(this).wijdialog("close");
                            }
                        },
                        {
                            text: self.localizeString("dialogCancel", "Cancel"), click: function () {
                                $(this).wijdialog("close");
                            }
                        }
                    ];
                }
                self._dialog.wijdialog({ buttons: buttons });
            };

            wijfileexplorer.prototype._createDialog = function () {
                var self = this, ele = self.element;

                self._dialog = $('<div>').css('overflow', 'hidden').appendTo(ele);
                self._dialog.wijdialog({
                    autoOpen: false,
                    modal: true,
                    resizable: true,
                    buttons: {
                        Ok: function () {
                            self._dialogOk && self._dialogOk(self._dialogInput.val());
                            $(this).wijdialog("close");
                        },
                        Cancel: function () {
                            $(this).wijdialog("close");
                        }
                    },
                    captionButtons: {
                        pin: { visible: false },
                        refresh: { visible: false },
                        toggle: { visible: false },
                        minimize: { visible: false },
                        maximize: { visible: false }
                    }
                });

                self._dialogInput = $('<input aria-label="input">').css('width', '100%').hide().appendTo(self._dialog);
                self._dialog.on("keydown" + eventNameSpaceSuffix, function (e) {
                    if (e.keyCode === $.ui.keyCode.ENTER) {
                        self._dialogOk && self._dialogOk(self._dialogInput.val());
                        self._dialog.wijdialog("close");
                        e.stopPropagation();
                    }
                });
                self._dialogContent = $('<div>').css('width', '100%').css('height', '100%').css('overflow', 'hidden').appendTo(self._dialog);
            };

            wijfileexplorer.prototype._createContextMenu = function () {
                var self = this, o = self.options, ele = self.element, commands = self._commands, $menu = $('<ul>').attr("tabindex", "-1").appendTo(ele), menuCommands = [commands.open, commands.newFolder, commands.copy, commands.paste, commands["delete"], commands.rename], element, globalEventNameSpaceSuffix = self._getGlobalEventNameSpaceSuffix(), cmd;

                $.each(menuCommands, function (index, item) {
                    element = $('<li>').data(commandDataName, item).append($('<a>').attr('href', '#').text(item.text)).appendTo($menu);
                    item.addBindElement(element);
                });

                $menu.wijmenu({
                    orientation: 'vertical',
                    trigger: ele,
                    disabled: o.disabled,
                    triggerEvent: 'rtclick',
                    animation: {
                        easing: 'easeOutCubic'
                    },
                    showing: function (e, sublist) {
                        if (!self._isActived() || self._isLoading() || !self._showingControls[visibleControls.contextMenu]) {
                            self._setContextItem(null);
                            return false;
                        }

                        // clear previous menu's selection
                        self._contextMenu.wijmenu("deactivate");

                        // If right click, use the event object as the position.of option.
                        // If keyboard event, use originalEvent's target.
                        var positionOf = (e.which === 3 || !e.originalEvent) ? e : e.originalEvent.target;
                        sublist.options.position = {
                            my: 'left2 top2',
                            at: 'left center',
                            of: positionOf,
                            collision: 'fit'
                        };
                    },
                    shown: function () {
                        return self._focusContextMenu();
                    },
                    hidden: function () {
                        self._setContextItem(null);
                    },
                    select: function (e, d) {
                        cmd = d.item.element.data(commandDataName);

                        //this is a just a workaround for the wijmenu's issue.
                        $menu.find("." + css.stateFocus).removeClass(o.wijCSS.stateFocus).removeClass(o.wijCSS.stateHover);
                        if (cmd) {
                            cmd.execute();
                        }
                    }
                }).on("mousedown" + eventNameSpaceSuffix, function (e) {
                    // Menu is hidden dn document mousedown. So we need cancel mousedown event bubble here.
                    e.stopPropagation();
                }).on("keydown" + eventNameSpaceSuffix, function (e) {
                    if (e.keyCode === $.ui.keyCode.ESCAPE) {
                        self._hideContextItem();
                    }
                });

                self._contextMenu = $menu;

                // Hide menu in right click
                $(document).on("contextmenu" + globalEventNameSpaceSuffix, function (e) {
                    self._hideContextItem();
                    // Hide menu in left click. If also process right click here, menu
                    // cannot show correct layout when right click several times quickly.
                }).on("mousedown" + globalEventNameSpaceSuffix, function (e) {
                    if (e.which === 3) {
                        return;
                    }
                    self._hideContextItem();
                });

                self.element.on('contextmenu' + eventNameSpaceSuffix, function (e) {
                    if (!self._isActived()) {
                        return;
                    }

                    var target = e.target, contextItem = target && self._getItemFromElement(target);

                    self._setContextItem(null);

                    if (!target || contextItem == null) {
                        return;
                    }

                    if (contextItem.operatingArea === 0 /* TreeView */ || self._isSelected(contextItem)) {
                        self._setContextItem(contextItem);
                        return;
                    }

                    if (!e.ctrlKey) {
                        self._selectItemsViewItem($(target));
                        self._setContextItem(contextItem);
                    }
                });
            };

            wijfileexplorer.prototype._focusContextMenu = function () {
                var self = this, contextMenu = self._contextMenu;
                if (!contextMenu || !contextMenu.length) {
                    return;
                }

                contextMenu.focus();
            };

            wijfileexplorer.prototype._hideContextItem = function () {
                var self = this;
                if (self._contextMenu) {
                    self._contextMenu.wijmenu("hideAllMenus");
                    self._setContextItem(null);
                }
            };

            wijfileexplorer.prototype._selectItemsViewItem = function ($element) {
                var self = this;
                if (self._showingControls[visibleControls.detailView]) {
                    self._selectDetailViewItem($element);
                    return;
                }

                if (self._showingControls[visibleControls.thumbnailView]) {
                    self._selectThumbnailViewItem($element);
                }
            };

            wijfileexplorer.prototype._selectThumbnailViewItem = function ($cell) {
                this._thumbnailView.wijtilelist("selectTile", $cell.closest("li"));
            };

            wijfileexplorer.prototype._selectDetailViewItem = function ($cell) {
                if (!$cell || $cell.length === 0) {
                    return;
                }

                var self = this, dv = self._detailView, selection = dv.wijgrid("selection"), cellInfo = dv.wijgrid("getCellInfo", $cell[0]);

                if (!selection || !cellInfo) {
                    return;
                }

                self._selectionUpdating = true;
                selection.clear();
                self._selectionUpdating = false;
                selection.addRows(cellInfo.rowIndex());
            };

            wijfileexplorer.prototype._showDialog = function (title, content, resizable, width, height, showButtons) {
                if (typeof showButtons === "undefined") { showButtons = true; }
                var self = this, opts = { 'title': title, 'resizable': resizable, 'width': width, 'height': height };
                if (!showButtons) {
                    self._setDialogButtons(false);
                }
                self._dialogContent.empty().append(content).show();
                self._dialogInput.hide();
                self._dialog.wijdialog(opts).wijdialog("open");
                self._dialogOk = null;
            };

            wijfileexplorer.prototype._showInputDialog = function (title, value, ok) {
                var self = this, txt, length, range;
                self._setDialogButtons(true);
                self._dialogContent.hide();
                self._dialogInput.val(value).show();
                self._dialog.wijdialog({ 'title': title, 'resizable': false, 'width': '300', 'height': '200' }).wijdialog("open");

                txt = self._dialogInput[0];
                length = txt.value.length;
                if (length > 0) {
                    if (txt.setSelectionRange)
                        txt.setSelectionRange(0, length);
                    else if (txt.createTextRange) {
                        range = txt.createTextRange();
                        range.collapse(true);
                        range.moveStart('character', 0);
                        range.moveEnd('character', length);
                        range.select();
                    }
                }

                self._dialogOk = ok;
            };

            wijfileexplorer.prototype._showConfirmDialog = function (title, msg, ok) {
                var self = this;
                self._setDialogButtons(true);
                self._dialogContent.empty().append(msg).show();
                self._dialogInput.hide();
                self._dialog.wijdialog({ 'title': title, 'resizable': false, 'width': '300', 'height': '200' }).wijdialog("open");
                self._dialogOk = ok;
            };

            wijfileexplorer.prototype._hideDialog = function () {
                this._dialog.wijdialog("close");
            };

            wijfileexplorer.prototype._isVisibleControl = function (control) {
                var controls = this.options.visibleControls;
                return !controls || controls.indexOf(control) > -1;
            };

            wijfileexplorer.prototype._createToolbar = function () {
                var self = this, options = self.options, wijCSS = options.wijCSS, commands = self._commands, toolbarCommands = [
                    commands.back,
                    commands.forward,
                    commands.open,
                    commands.refresh,
                    commands.newFolder,
                    commands["delete"],
                    commands.setDetailViewMode,
                    commands.setThumbnailViewMode
                ], toolbarContainer = $("<div>").attr("tabindex", "-1").addClass(wijCSS.helperReset).appendTo(self.element), toolbar = $("<ul>").addClass(wijCSS.widget).addClass(wijCSS.helperReset).addClass(wijCSS.helperClearFix).addClass(wijCSS.stateDefault).addClass(css.toolbar).appendTo(toolbarContainer);

                self._toolbar = toolbar;

                $.each(toolbarCommands, function (index, item) {
                    var innerSpan = $("<span>").addClass(wijCSS.icon), innerLink = $("<a>").attr("herf", "#").addClass(css.link).append(innerSpan), element = $("<li>").data(commandDataName, item).attr("title", item.text).addClass(css[toCamelCase("toolbar-" + item.name)]).addClass(wijCSS.stateDefault).addClass(wijCSS.cornerAll).append(innerLink).appendTo(toolbar);
                    item.addBindElement(element);
                });

                toolbar.on("click" + eventNameSpaceSuffix, function (event) {
                    if (!self._isActived()) {
                        return;
                    }

                    var command = $(event.target).closest("li").data(commandDataName);
                    if (command) {
                        command.execute();
                    }
                }).on("mouseenter" + eventNameSpaceSuffix, "li", function () {
                    if (!options.disabled && !$(this).hasClass(wijCSS.stateDisabled)) {
                        $(this).addClass(wijCSS.stateHover);
                    }
                }).on("mouseleave" + eventNameSpaceSuffix, "li", function () {
                    $(this).removeClass(wijCSS.stateHover);
                });

                self._showingControls[visibleControls.toolbar] = true;
            };

            wijfileexplorer.prototype._createAddressBar = function () {
                var self = this, wijCSS = self.options.wijCSS, container = $("<div>").addClass(css.addressBar).addClass(wijCSS.helperClearFix).addClass(wijCSS.content).appendTo(self.element);
                self._createAddressBox(container);
                self._createFilterBox(container);
            };

            wijfileexplorer.prototype._createAddressBox = function (container) {
                var self = this, addressPanel = $("<div>").addClass(css.addressPanel).appendTo(container);
                self._addressBox = $("<div>").addClass(css.address).addClass(self.options.wijCSS.content).appendTo(addressPanel);
                self._showingControls[visibleControls.addressBox] = true;
            };

            wijfileexplorer.prototype._createFilterBox = function (container) {
                var self = this, o = self.options, filterPanel = $("<div>").addClass(css.filterPanel).appendTo(container), filterBox = $("<input type='text' aria-label='filterBox' />"), resetTimer = function () {
                    if (self._filterTimer != undefined) {
                        clearTimeout(self._filterTimer);
                        self._filterTimer = null;
                    }
                }, textChangedEventName = "input" + eventNameSpaceSuffix + " propertychange" + eventNameSpaceSuffix + " keyup" + eventNameSpaceSuffix, filterExpression = self._filterExpression() || defaultFilterExpression;

                self._filterBox = filterBox.addClass(css.filter).addClass(o.wijCSS.content).appendTo(filterPanel).on("keydown" + eventNameSpaceSuffix, function (e) {
                    e.stopPropagation();

                    if (e.keyCode === $.ui.keyCode.ENTER) {
                        if (o.enableFilteringOnEnterPressed) {
                            self._filter(filterBox.val());
                        }

                        e.preventDefault();
                    }
                }).on(textChangedEventName, function (event) {
                    if (o.enableFilteringOnEnterPressed) {
                        return;
                    }

                    //IE < 9, only listen value's propertchange event
                    if (event.type === "propertychange" && event.originalEvent.propertyName !== "value") {
                        return;
                    }

                    resetTimer();
                    self._filterTimer = setTimeout(function () {
                        self._filter(filterBox.val());
                        resetTimer();
                    }, filterTimeout);
                }).on("focus" + eventNameSpaceSuffix, function () {
                    self._restoreFocus = function () {
                        filterBox && filterBox.focus();
                    };
                });

                self._showingControls[visibleControls.filterBox] = true;

                if (filterExpression !== filterBox.val()) {
                    filterBox.val(filterExpression);
                }
            };

            wijfileexplorer.prototype._createSplitter = function () {
                var self = this, leftPanel = $("<div>"), rightPanel = $("<div>"), splitter = $("<div style='height:100%;'>"), adjustItemsViewWidth = function () {
                    self._adjustDetailViewWidth();
                    self.options.treePanelWidth = splitter.wijsplitter("option", "splitterDistance");
                };

                self._splitter = splitter.append(leftPanel).append(rightPanel).appendTo(self.element).wijsplitter({
                    orientation: "vertical",
                    sized: adjustItemsViewWidth,
                    collapsed: adjustItemsViewWidth,
                    expanded: adjustItemsViewWidth,
                    fullSplit: true
                });

                self._createTreeView(leftPanel);
                self._createItemsView(rightPanel);
            };

            wijfileexplorer.prototype._createTreeView = function (container) {
                var self = this, item;
                self._treeView = $("<ul>").appendTo(container).wijtree({
                    selectedNodeChanged: function (e, data) {
                        item = self._getItemFromElement(data.element);
                        if (self._sameWithSelection(item)) {
                            return;
                        }

                        if (self.options.viewMode === "detail") {
                            self._detailView.wijgrid("selection").clear();
                        }

                        self._setSelection(item);
                        if (self.options.mode === explorerMode["default"]) {
                            self._open();
                            return;
                        }

                        if (item.isFolder) {
                            self._setCurrentFolder(item.path);
                        }
                    }
                });
                self._treeView.parent().addClass(css.fileTree);
                self._attachTreeViewEvents();
                self._showingControls[visibleControls.treeView] = true;
            };

            wijfileexplorer.prototype._attachTreeViewEvents = function () {
                var self = this, o = self.options, parentNodeSelector = ".wijmo-wijtree-parent";

                self._treeView.on("click" + eventNameSpaceSuffix, parentNodeSelector, function (e) {
                    if (!self._isActived()) {
                        return;
                    }

                    if ($(e.target).is("." + css.icon)) {
                        var treeNode = $(this).data("wijmo-wijtreenode");
                        if (treeNode && (!treeNode.$nodes || !treeNode.$nodes.length)) {
                            if (!treeNode.options.expanded) {
                                self._expandWithNewNodes(treeNode.options.value);
                            }
                        }
                    }
                }).on("dblclick" + eventNameSpaceSuffix, parentNodeSelector, function (e) {
                    if (!self._isActived()) {
                        return;
                    }

                    var treeNode = $(this).data("wijmo-wijtreenode"), selectTreeNode = function () {
                        return treeNode.select(true);
                    }, $leaf = $(e.target).parents(".wijmo-wijtree-item." + css.folderItem);

                    //this nonde doesn't have child nodes.
                    if ($leaf.length || !treeNode) {
                        if ($leaf.length) {
                            // select the leaf node
                            treeNode = $leaf.data("wijmo-wijtreenode");
                            selectTreeNode();
                        }
                        return;
                    }

                    if (o.mode === explorerMode["default"]) {
                        if (treeNode.options.expanded) {
                            treeNode.collapse();
                            selectTreeNode();
                        } else {
                            self._expand(treeNode, selectTreeNode);
                        }
                    } else {
                        self._open(selectTreeNode);
                    }

                    e.stopPropagation();
                }).on("keydown" + eventNameSpaceSuffix, function (e) {
                    if (o.disabled) {
                        return;
                    }

                    //When pressing Right key, expand focused tree node.
                    if (e.keyCode === $.ui.keyCode.RIGHT) {
                        self._onTreeViewRightKeyDown();
                        return;
                    }

                    //When pressing Enter key, change currentFolder to current focused node.
                    if (e.keyCode === $.ui.keyCode.ENTER) {
                        e.stopPropagation();
                        return;
                    }

                    //When pressing Tab key, move focus to the items view.
                    if (e.keyCode === $.ui.keyCode.TAB && !e.shiftKey) {
                        self._focusGrid();
                        e.preventDefault();
                        e.stopPropagation();
                        return;
                    }

                    return self._processShortcut(e);
                });

                //bind mousedown event to file tree's parent(container).
                self._treeView.parents("." + css.fileTree).first().parent().on("mouseup" + eventNameSpaceSuffix, function () {
                    if (o.disabled) {
                        return;
                    }

                    self._focusTreeView();
                });
            };

            wijfileexplorer.prototype._initNodeHasChildren = function (node, hasChildren) {
                node._setOption("hasChildren", hasChildren);
                if (node._initNodeClass) {
                    node._initNodeClass();
                }
                if (!hasChildren && node.options.expanded) {
                    node.collapse();
                }
            };

            wijfileexplorer.prototype._setTreeViewNodes = function (items, parentNode) {
                var self = this, o = self.options, isFileTreeMode = o.mode === explorerMode.fileTree, nodeCount = parentNode.options.nodes.length;

                if (!items) {
                    return;
                }

                self._initNodeHasChildren(parentNode, !!items.length);
                while (nodeCount > 0) {
                    parentNode.remove(nodeCount - 1);
                    nodeCount--;
                }

                $.each(items, function (i, item) {
                    if (!isFileTreeMode && !item.isFolder) {
                        return;
                    }

                    var nodeOption = {
                        text: getItemName(item.path),
                        value: item.path,
                        hasChildren: undefined,
                        expandedIconClass: undefined,
                        collapsedIconClass: undefined,
                        itemIconClass: undefined,
                        nodes: []
                    };

                    if (item.isFolder) {
                        nodeOption.hasChildren = (isFileTreeMode ? item.hasChildren : item.hasSubFolders) || false;
                        nodeOption.expandedIconClass = css.folderExpandedIcon;
                        nodeOption.collapsedIconClass = css.folderCollapsedIcon;
                    } else {
                        nodeOption.hasChildren = false;
                        nodeOption.itemIconClass = css.documentIcon;
                    }

                    parentNode.add(nodeOption);
                    parentNode.element.find("li:last").addClass(item.isFolder ? css.folderItem : css.fileItem);

                    if (nodeOption.hasChildren) {
                        var childNodes = parentNode.getNodes(), addedNodes = $(childNodes).filter(function () {
                            return this.options.value == nodeOption.value;
                        });
                        if (addedNodes.length > 0) {
                            self._setTreeViewNodes(item.children, addedNodes[0]);
                        }
                    }
                });
            };

            wijfileexplorer.prototype._createItemsView = function (container) {
                var self = this, innerContainer = $("<div>").addClass(css.itemsViewContainer).appendTo(container);
                self._itemsViewContainer = innerContainer;
                self._createDetailView(innerContainer);
                self._createThumbnailView(innerContainer);
                self._createEmptyFolderTip(innerContainer);
                self._createPager(container);
                self._attachItemsViewContainerEvents();
            };

            wijfileexplorer.prototype._attachItemsViewContainerEvents = function () {
                var self = this, o = self.options;

                self._itemsViewContainer.on("click" + eventNameSpaceSuffix, function () {
                    if (o.disabled) {
                        return;
                    }

                    self._focusGrid();
                }).on("keydown" + eventNameSpaceSuffix, function (e) {
                    if (o.disabled) {
                        return;
                    }

                    if (e.keyCode === $.ui.keyCode.TAB && e.shiftKey) {
                        self._focusTreeView();
                        e.preventDefault();
                        e.stopPropagation();
                        return;
                    }
                });
            };

            wijfileexplorer.prototype._createEmptyFolderTip = function (container) {
                var self = this, emptyFolderTip = $("<div>").text(self.localizeString("emptyFolder", "This folder is empty.")).addClass(css.emptyFolderTip).appendTo(container).hide();
                self._emptyFolderTip = emptyFolderTip;
            };

            wijfileexplorer.prototype._createPager = function (container) {
                var self = this, wijCSS = self.options.wijCSS, pager = $("<div>").wijpager({
                    mode: "numeric",
                    pageIndexChanged: function (e, args) {
                        self._page(args.newPageIndex);
                    }
                }).addClass(wijCSS.stateDefault).addClass(wijCSS.widget).addClass("wijmo-wijpager ui-helper-clearfix").appendTo(container);

                self._pager = pager;
            };

            // For fix bug 92769: when grid's container width is auto and grid's table width is bigger than container,
            // grid will not display completely. This method is used to adjust grid's container to wider to
            // make scrollbar show. It is invoked when splitter resizing, grid column resizing and window resizing.
            wijfileexplorer.prototype._adjustDetailViewWidth = function () {
                var self = this, detailView = self._detailView, originalScrollLeft, tableMinWidth, outerContainer;

                if (!detailView || !detailView.length) {
                    return;
                }

                self._cancelDetailViewSelectionChange = !self._getDetailViewSelectedCells().length();

                tableMinWidth = self._getDetailViewMinWidth();
                originalScrollLeft = self._itemsViewContainer.scrollLeft();
                outerContainer = detailView.parent();
                outerContainer.css("width", "");
                if (tableMinWidth > outerContainer.width()) {
                    outerContainer.width(detailView.outerWidth(true));
                }

                self._detailView.wijgrid("doRefresh");
                self._itemsViewContainer.scrollLeft(originalScrollLeft);

                self._cancelDetailViewSelectionChange = false;
            };

            wijfileexplorer.prototype._getDetailViewMinWidth = function () {
                var self = this, nameColumnWidth = self._detailView.wijgrid("option", "columns")[0].width || self._getNameColumnMinWidth();
                return nameColumnWidth + self._getSizeColumnMinWidth() + self._getDetailViewOuterAreaWidth();
            };

            wijfileexplorer.prototype._getDetailViewOuterAreaWidth = function () {
                var self = this;

                if (self._detailViewOuterAreaWidth === undefined) {
                    self._detailViewOuterAreaWidth = getBoxOuterAreaWidth(self._detailView);
                }

                return self._detailViewOuterAreaWidth;
            };

            wijfileexplorer.prototype._getSizeColumnMinWidth = function () {
                var self = this;

                if (self._sizeColumnMinWidth === undefined) {
                    self._sizeColumnMinWidth = self._getColumnMinWidth(sizeColumnIndex, "." + css.sizeContent);
                }

                return self._sizeColumnMinWidth;
            };

            wijfileexplorer.prototype._getNameColumnMinWidth = function () {
                var self = this;

                if (self._nameColumnMinWidth === undefined) {
                    self._nameColumnMinWidth = self._getColumnMinWidth(nameColumnIndex, "tbody>tr>td ." + css.contentItem);
                }

                return self._nameColumnMinWidth;
            };

            wijfileexplorer.prototype._getColumnMinWidth = function (columnIndex, cellSelector) {
                var self = this, detailView = self._detailView, columnHeader = detailView.find("th>." + css.gridInnerCell).eq(columnIndex), orignalColumnHeaderDisplay = columnHeader.css("display"), $elem, cellOuterAreaWidth, columnMinWidth;

                columnHeader.css("display", "inline-block");
                columnMinWidth = columnHeader.outerWidth(true) + getBoxOuterAreaWidth(columnHeader.closest("th"));
                columnHeader.css("display", orignalColumnHeaderDisplay);

                detailView.find(cellSelector).each(function (index, elem) {
                    $elem = $(elem);
                    if (cellOuterAreaWidth === undefined) {
                        cellOuterAreaWidth = getBoxOuterAreaWidth($elem.closest("td")) + getBoxOuterAreaWidth($elem.closest("." + css.gridInnerCell));
                    }

                    columnMinWidth = Math.max(columnMinWidth, $elem.outerWidth(true) + cellOuterAreaWidth);
                });

                return columnMinWidth;
            };

            wijfileexplorer.prototype._createDetailView = function (container) {
                var self = this, o = self.options, wijCSS = o.wijCSS, toggleSortIcon = function ($container, name) {
                    var icon = $container.find(".wijmo-wijgrid-sort-icon");
                    if (self._sortExpression() === name) {
                        if (!icon || !icon.length) {
                            icon = $("<span>").addClass("wijmo-wijgrid-sort-icon  ui-icon").css("cursor", "pointer").appendTo($container);
                        }

                        if (self._sortDirection() === sortDirectionNames.descending) {
                            icon.removeClass(wijCSS.iconArrowUp);
                            icon.addClass(wijCSS.iconArrowDown);
                        } else {
                            icon.removeClass(wijCSS.iconArrowDown);
                            icon.addClass(wijCSS.iconArrowUp);
                        }
                    } else {
                        icon.remove();
                    }
                }, detailView = $("<table>").appendTo(container).wijgrid({
                    rendered: function () {
                        if (self._updatingDetailViewData) {
                            self._sizeColumnMinWidth = undefined;
                            self._nameColumnMinWidth = undefined;
                            self._detailViewOuterAreaWidth = undefined;
                        }

                        var headers = $(this).find("th .wijmo-wijgrid-innercell");
                        toggleSortIcon(headers.eq(0), columnNames.name);
                        toggleSortIcon(headers.eq(1), columnNames.size);
                    },
                    sorting: function (e, args) {
                        var sortExpression = args.column.dataKey === columnNames.size ? columnNames.size : columnNames.name, sortDirection = self._sortDirection() === sortDirectionNames.descending ? sortDirectionNames.ascending : sortDirectionNames.descending;
                        self._sort(sortExpression, sortDirection);
                        return false;
                    },
                    columnsAutogenerationMode: "none",
                    allowSorting: true,
                    allowColSizing: true,
                    columnResized: function () {
                        self._adjustDetailViewWidth();
                    },
                    columns: [
                        {
                            dataKey: "path",
                            dataType: "string",
                            headerText: self.localizeString("detailViewColumnNameTitle", "Name"),
                            cellFormatter: function (args) {
                                var rowData = args.row.data;
                                if ((rowData && rowData.path) && (args.row.type & $.wijmo.wijgrid.rowType.data)) {
                                    var iconCss = o.wijCSS.icon, text = $("<span>"), icon = $("<span>");
                                    text.addClass(css.contentItem).text(getItemName(rowData.path));
                                    if (rowData.isFolder) {
                                        icon.addClass(iconCss + " " + css.folderCollapsedIcon);
                                        $(args.row.$rows).addClass(css.folderItem);
                                    } else {
                                        icon.addClass(iconCss + " " + css.documentIcon);
                                        $(args.row.$rows).addClass(css.fileItem);
                                    }
                                    args.$container.empty().append(icon).append(text).addClass(css.contentItemContainer);
                                    return true;
                                }
                            }
                        },
                        {
                            allowSizing: false,
                            dataKey: "size",
                            dataType: "number",
                            headerText: self.localizeString("detailViewColumnSizeTitle", "Size"),
                            cellFormatter: function (args) {
                                if (args.row.type & $.wijmo.wijgrid.rowType.data) {
                                    var size = args.row.data.size, text = "", $container = args.$container;
                                    $container.empty();
                                    if (size != null) {
                                        var sizeInKb = size / 1000;
                                        text = Globalize.format(sizeInKb, "n") + " " + self.localizeString("detailViewColumnSizeUnit", "KB");
                                        $container.append($("<span>").addClass(css.contentItemContainer).addClass(css.sizeContent).text(text));
                                    }
                                    return true;
                                }
                            }
                        }
                    ]
                });

                self._detailView = detailView;
                self._attachDetailViewEvent();
                self._showingControls[visibleControls.detailView] = true;
            };

            wijfileexplorer.prototype._attachDetailViewEvent = function () {
                var self = this, rowSelector = "." + css.gridRow, eventPrefix = "wijgrid";

                //cancel grid auto select the first row
                self._detailView.on(eventPrefix + "currentcellchanging", function () {
                    return !(self._cancelDetailViewSelectionChange || self._updatingDetailViewData);
                });

                self.element.on('dblclick' + eventNameSpaceSuffix, rowSelector, function () {
                    self._open();
                }).on(eventPrefix + "selectionchanged" + eventNameSpaceSuffix, function () {
                    self._onDetailViewSelectionChanged();
                    self._setItemsViewDrag(self._detailView);
                });

                $(window).on("resize" + self._getGlobalEventNameSpaceSuffix(), function () {
                    self._adjustDetailViewWidth();
                });
            };

            wijfileexplorer.prototype._createThumbnailView = function (container) {
                var self = this, o = self.options, wijCSS = o.wijCSS;

                self._thumbnailView = $("<div>").addClass(css.thumbnailView).appendTo(container).wijtilelist({
                    allowMultipleSelection: o.allowMultipleSelection,
                    tileCreating: function (e, args) {
                        var tile = args.tile, ele = args.element;

                        tile.text = getItemName(tile.path);
                        tile.hint = tile.text;

                        //the item is folder and should use default folder image to display.
                        if (tile.isFolder) {
                            tile.iconFormat = function () {
                                return $("<span>").attr("alt", tile.text).addClass(wijCSS.icon).addClass(css.folderCollapsedIcon);
                            };
                            ele.addClass(css.folderItem);
                        } else {
                            tile.path = getUriWithHostUri(o.hostUri, tile.path);
                            ele.addClass(css.fileItem);
                        }
                    },
                    selectionChanged: function (e, args) {
                        var selection = [];

                        $.each(args && args.newSelection, function (idx, tileInfo) {
                            selection.push({
                                path: tileInfo.tile.path,
                                isFolder: tileInfo.tile.isFolder,
                                operatingArea: 1 /* ItemsView */
                            });
                        });

                        self._setSelection(selection);
                        self._setItemsViewDrag(self._thumbnailView);
                    }
                }).hide();

                self._attachThumbnailViewEvent();
                self._showingControls[visibleControls.thumbnailView] = false;
            };

            wijfileexplorer.prototype._attachThumbnailViewEvent = function () {
                var self = this;

                self.element.on('dblclick' + eventNameSpaceSuffix, "." + css.tileItem, function () {
                    self._open();
                });
            };

            //End Init
            //Begin Operation
            wijfileexplorer.prototype._back = function () {
                this._moveHistory(-1);
            };

            wijfileexplorer.prototype._moveHistory = function (step) {
                var self = this;
                if (!self._isActived() || !step || (!self._canBack() && step < 0) || (!self._canForward() && step > 0)) {
                    return;
                }

                self._updatingHistoryStep = step;
                self._openFolder(self._histories[self._currentHistoryIndex + step]);
            };

            wijfileexplorer.prototype._forward = function () {
                this._moveHistory(1);
            };

            wijfileexplorer.prototype._expand = function (treeNode, callback) {
                var self = this;
                if (!treeNode) {
                    if (callback) {
                        callback();
                    }
                    return;
                }

                if (treeNode.$nodes && treeNode.$nodes.length) {
                    self._expandWithExistedNodes(treeNode);
                    if (callback) {
                        callback();
                    }
                } else {
                    self._expandWithNewNodes(treeNode.options.value, callback);
                }
            };

            wijfileexplorer.prototype._open = function (openFolderCallback) {
                var self = this;
                if (!self._isActived()) {
                    return;
                }

                var item = self._getOperatingItem();
                if (item.isFolder) {
                    if (item.path === self.options.currentFolder) {
                        self._expand(self._getNodeByPath(item.path), openFolderCallback);
                        return;
                    }

                    self._openFolder(item.path, function () {
                        self._updateHistory();
                        if (openFolderCallback) {
                            openFolderCallback();
                        }
                    });
                    return;
                }

                self._openFile(item.path);
            };

            wijfileexplorer.prototype._openFile = function (path) {
                var self = this, fileName = getItemName(path), src, content;
                if (self.options.enableOpenFile) {
                    if (self._triggerFileOpening({ path: path }) === false) {
                        return;
                    }

                    self._executeWithHostUri(function () {
                        src = getUriWithHostUri(self.options.hostUri, path);
                        content = $("<iframe src='" + src + "' style='border:none; width:100%; height:100%' frameborder='no'></iframe>");
                        self._showDialog(self.localizeString("openFileDialogTitle", "View file: ") + fileName, content, true, '480', '480', false);
                        self._triggerFileOpened({ path: path });
                    });
                }
            };

            wijfileexplorer.prototype._executeWithHostUri = function (callback) {
                var self = this;
                if (self.options.hostUri != null) {
                    if (callback) {
                        callback();
                    }
                    return;
                }

                self._getHostUriCall(callback);
            };

            wijfileexplorer.prototype._getHostUriCall = function (callback) {
                var self = this;
                self._tryAjax(ajaxCommands.getHostUri, null, null, function (result) {
                    self._setOption("hostUri", result.hostUri || "");

                    if (callback) {
                        callback();
                    }
                });
            };

            /** @ignore */
            wijfileexplorer.prototype._sortDirection = function (value) {
                if (value === undefined) {
                    return this._sortDirectionValue || defaultSortDirection;
                }

                this._sortDirectionValue = value;
            };

            /** @ignore */
            wijfileexplorer.prototype._sortExpression = function (value) {
                if (value === undefined) {
                    return this._sortExpressionValue || defaultSortExpression;
                }

                this._sortExpressionValue = value;
            };

            /** @ignore */
            wijfileexplorer.prototype._filterExpression = function (value) {
                if (value === undefined) {
                    return this._filterExpressionValue || defaultFilterExpression;
                }

                this._filterExpressionValue = value;
            };

            /** @ignore */
            wijfileexplorer.prototype._pageCount = function (value) {
                if (value === undefined) {
                    return this._pageCountValue || defaultPageCount;
                }

                this._pageCountValue = value;
            };

            /** @ignore */
            wijfileexplorer.prototype._pageIndex = function (value) {
                if (value === undefined) {
                    return this._pageIndexValue || defaultPageIndex;
                }

                this._pageIndexValue = value;
            };

            /** @ignore */
            wijfileexplorer.prototype._data = function (value) {
                var self = this;
                if (value === undefined) {
                    return self._dataValue;
                }

                self._dataValue = value;

                if (!self._enableAjax()) {
                    self._resolveData();
                    self._sortData();
                }
            };

            wijfileexplorer.prototype._removeDefaultInRequest = function (data) {
                var result = $.extend({}, data);
                if (!result.filterExpression || result.filterExpression === defaultFilterExpression) {
                    delete result.filterExpression;
                }

                if (!result.sortExpression || result.sortExpression === defaultSortExpression) {
                    delete result.sortExpression;
                }

                if (!result.sortDirection && result.sortDirection === defaultSortDirection) {
                    delete result.sortDirection;
                }

                if (!result.pageIndex && result.pageIndex === defaultPageIndex) {
                    delete result.pageIndex;
                }

                return result;
            };

            wijfileexplorer.prototype._createDefaultRequest = function (path) {
                var self = this, o = self.options, requestData = {
                    path: path || self.options.currentFolder,
                    filterExpression: defaultFilterExpression,
                    sortExpression: defaultSortExpression,
                    sortDirection: defaultSortDirection
                };

                if (o.allowPaging) {
                    requestData.pageIndex = defaultPageIndex;
                    requestData.pageSize = o.pageSize;
                }

                return requestData;
            };

            wijfileexplorer.prototype._createCurrentStateRequest = function (path) {
                var self = this, o = self.options, requestData = {
                    path: path || self.options.currentFolder,
                    filterExpression: self._filterExpression(),
                    sortExpression: self._sortExpression(),
                    sortDirection: self._sortDirection()
                };

                if (o.allowPaging) {
                    requestData.pageIndex = self._pageIndex();
                    requestData.pageSize = o.pageSize;
                }

                return requestData;
            };

            wijfileexplorer.prototype._applyRequestData = function (data, responseData) {
                var self = this, o = self.options;

                if (data.filterExpression != null) {
                    self._filterExpression(data.filterExpression);
                }

                if (o.allowPaging) {
                    if (responseData && responseData.pageIndex) {
                        self._pageIndex(responseData.pageIndex);
                    } else {
                        self._pageIndex(defaultPageIndex);
                    }

                    if (responseData && responseData.pageCount) {
                        self._pageCount(responseData.pageCount);
                    } else {
                        self._pageCount(defaultPageCount);
                    }
                }

                if (data.sortExpression != null) {
                    self._sortExpression(data.sortExpression);
                }

                if (data.sortDirection != null) {
                    self._sortDirection(data.sortDirection);
                }
            };

            wijfileexplorer.prototype._updateItemsViewCall = function (data, isFilterChanged, callback) {
                var self = this, requestData = $.extend(self._createCurrentStateRequest(), data);

                self._getItemsCall(requestData, function (result) {
                    self._data(result.itemOperationResults);
                    self._applyRequestData(requestData, result);
                    self._updateItemsView(isFilterChanged);
                    self._triggerFolderLoaded({ currentFolder: self.options.currentFolder });
                    self._selectCurrentFolderTreeNode();
                    if (callback) {
                        callback();
                    }
                });
            };

            wijfileexplorer.prototype._openFolder = function (data, success, error) {
                if (typeof data == "string") {
                    data = { path: data };
                }

                var self = this, requestData = $.extend({}, self._createDefaultRequest(), data);

                self._getItemsCall(requestData, function (result) {
                    self._data(result.itemOperationResults);
                    self._applyRequestData(requestData, result);
                    self._setCurrentFolder(requestData.path);

                    if (success) {
                        success();
                    }
                }, error);
            };

            wijfileexplorer.prototype._isDefaultSearchPattern = function () {
                return arraysEqual(this.options.searchPatterns, this._getDefaultSearchPattern());
            };

            /** @ignore */
            wijfileexplorer.prototype._getDefaultSearchPattern = function () {
                return defaultSearchPatterns;
            };

            wijfileexplorer.prototype._getItemsCall = function (data, success, error) {
                var self = this, o = self.options;
                data = $.isPlainObject(data) ? data : { path: data };

                if (data.path == null) {
                    return;
                }

                if (!data.onlyFolder && o.searchPatterns != null && !self._isDefaultSearchPattern()) {
                    data.searchPatterns = o.searchPatterns;
                }

                data = self._removeDefaultInRequest(data);
                self._tryAjax(ajaxCommands.getItems, data, null, function (result) {
                    if (success) {
                        success(result);
                    }
                }, function () {
                    if (error) {
                        error();
                    }

                    return false;
                }, function () {
                    if (success) {
                        success({ itemsOperationResults: self._data() });
                    }
                });
            };

            /**
            * The refresh method refreshes the content within the wijfileexplorer.
            * @param path - Optional. The path to refresh. The current folder is used if the path is not set.
            */
            wijfileexplorer.prototype.refresh = function (path) {
                var self = this;
                if (path && path !== self.options.currentFolder) {
                    if (self._getNodeByPath(path)) {
                        self._refreshTreeNode(path);
                    }
                    return;
                }

                self._openFolder(self._createCurrentStateRequest());
                self._refreshTreeNode(self.options.currentFolder, function () {
                    return self._selectCurrentFolderTreeNode();
                });
            };

            wijfileexplorer.prototype._newFolder = function () {
                var self = this, item = self._getOperatingItem(), newFolderTargetPath = item && item.operatingArea === 0 /* TreeView */ ? item.path : self.options.currentFolder;
                if (self.options.enableCreateNewFolder) {
                    self._showInputDialog(self.localizeString("newFolderDialogTitle", "Enter new folder name"), self.localizeString("defaultNewFolderName", "New Folder"), function (input) {
                        if (input) {
                            self._newFolderCall(input, newFolderTargetPath);
                        }
                    });
                }
            };

            wijfileexplorer.prototype._newFolderCall = function (newFolderName, targetPath) {
                var self = this, newFolderPath = ensureFolderSeparator(targetPath) + newFolderName;

                if (self._triggerNewFolderCreating({ path: newFolderPath }) === false) {
                    return;
                }

                self._tryAjax(ajaxCommands.newFolder, { path: newFolderPath }, null, function () {
                    self._triggerNewFolderCreated({ path: newFolderPath });
                    self._refreshAfterAdd(targetPath);
                }, null, function () {
                    self._addItemsInData({
                        path: newFolderPath,
                        isFolder: true,
                        hasChildren: false,
                        hasSubFolder: false,
                        children: []
                    }, self._getFolderData(targetPath));
                    self.refresh(targetPath);
                });
            };

            wijfileexplorer.prototype._refreshTreeNode = function (path, callback) {
                var self = this;
                self._getItemsCall({
                    path: path,
                    onlyFolder: self.options.mode === explorerMode["default"]
                }, function (result) {
                    self._updateTreeViewData(path, result.itemOperationResults);
                    if (callback) {
                        callback();
                    }
                });
            };

            wijfileexplorer.prototype._delete = function () {
                var self = this;
                if (!self._isActived()) {
                    return;
                }

                var items = combinePaths(self._getOperatingItems());
                if (self._hasRootPath(items)) {
                    return;
                }

                if (items && items.length) {
                    self._showConfirmDialog(self.localizeString("deleteDialogTitle", "Warning"), self.localizeString("deleteDialogAlertingText", "Are you sure to delete the selected item? This operation cannot be undone."), function () {
                        self._deleteCall(items);
                    });
                }
            };

            wijfileexplorer.prototype._deleteCall = function (items) {
                if (!items || !items.length) {
                    return;
                }

                var self = this, paths = [];
                $.each(items, function (i, item) {
                    if (self._triggerItemDeleting({ path: item.path }) === false) {
                        return;
                    }

                    paths.push(item.path);
                });

                self._tryAjax(ajaxCommands["delete"], { sourcePaths: paths }, null, function (result) {
                    if (!result.itemOperationResults || !result.itemOperationResults.length) {
                        return;
                    }

                    var successItems = [];
                    $.each(result.itemOperationResults, function (i, item) {
                        if (!item) {
                            return;
                        }

                        if (item.success) {
                            successItems.push(findItemByPath(items, item.path));
                            self._triggerItemDeleted({ path: item.path });
                            return;
                        }

                        self._processError(item.error);
                    });

                    self._refreshAfterDelete(successItems);
                }, function () {
                    self._refreshAfterDelete(items);
                }, function () {
                    self._removeItemsInData(items);
                    self.refresh();
                });
            };

            wijfileexplorer.prototype._rename = function () {
                var self = this, item = self._getOperatingItem(), showExtension = self.options.allowFileExtensionRename;
                if (item) {
                    if (self._isRootPath(item.path)) {
                        return;
                    }

                    var name = getItemName(item.path, !showExtension && !item.isFolder), fileSuffix = showExtension || item.isFolder ? "" : "." + getFileExtension(item.path);
                    self._showInputDialog(self.localizeString("renameDialogTitle", "Enter new name"), name, function (input) {
                        if (input && input !== name) {
                            if (self._triggerItemRenaming({ path: item.path, newName: input }) === false) {
                                return;
                            }
                            self._renameCall(item, input + fileSuffix);
                        }
                    });
                }
            };

            wijfileexplorer.prototype._renameCall = function (item, newName) {
                var self = this, parentPath = getParentPath(item.path), targetPath = ensureFolderSeparator(parentPath) + newName;

                self._tryAjax(ajaxCommands.rename, { path: targetPath, sourcePaths: [item.path] }, null, function () {
                    self._refreshAfterRename(item.path, ensureFolderSeparator(parentPath) + newName);
                    self._triggerItemRenamed({ path: item.path, newName: getItemName(newName, !self.options.allowFileExtensionRename) });
                }, null, function () {
                    self._removeItemsInData(item, true);
                    self._addItemsInData($.extend({}, item, { path: targetPath }), null, true);
                    self._data(self._data());
                    self.refresh();
                });
            };

            wijfileexplorer.prototype._refreshAfterRename = function (oldPath, newPath) {
                var self = this, parentPath = getParentPath(oldPath);
                if (parentPath === self.options.currentFolder) {
                    self.refresh();
                } else {
                    self._refreshTreeNode(parentPath);
                    if (oldPath === self.options.currentFolder) {
                        self._openFolder(newPath);
                    }
                }
            };

            wijfileexplorer.prototype._copy = function () {
                var self = this;
                if (!self._isActived() || !self.options.enableCopy) {
                    return;
                }
                var items = self._getOperatingItems(), copiedItems = [];
                $.each(items, function (i, item) {
                    if (self._triggerItemCopying({ path: item.path }) === false) {
                        return;
                    }

                    copiedItems.push(item);
                });

                self._copiedItems = copiedItems;
                self._commands.paste.disabled(false);

                $.each(copiedItems, function (i, item) {
                    self._triggerItemCopied({ path: item.path });
                });
            };

            wijfileexplorer.prototype._paste = function (items, targetPath) {
                var self = this, target = self._getOperatingItem(), pasteItems = [];
                targetPath = targetPath || (target.isFolder ? target.path : getParentPath(target.path));
                items = items || self._copiedItems;

                if (!targetPath) {
                    return;
                }

                $.each(items, function (i, item) {
                    if (self._triggerItemPasting({ sourcePath: item.path, targetFolder: targetPath }) === false) {
                        return;
                    }

                    pasteItems.push(item);
                });

                if (!pasteItems.length) {
                    return;
                }

                self._pasteCall(pasteItems, targetPath);
            };

            wijfileexplorer.prototype._expandWithNewNodes = function (path, callback) {
                var self = this;
                if (!path) {
                    return;
                }

                self._refreshTreeNode(path, function () {
                    self._expandWithExistedNodes(self._getNodeByPath(path));
                    if (callback) {
                        callback();
                    }
                });
            };

            wijfileexplorer.prototype._filter = function (filterExpression) {
                var self = this;
                if (!self._isActived() || filterExpression === self._filterExpression()) {
                    return;
                }

                if (self._triggerFiltering({ path: self.options.currentFolder, filterExpression: filterExpression }) === false) {
                    return;
                }

                self._updateItemsViewCall({ filterExpression: filterExpression }, true, function () {
                    self._triggerFiltered({ path: self.options.currentFolder, filterExpression: filterExpression });
                });
            };

            wijfileexplorer.prototype._sort = function (sortExpression, sortDirection) {
                var self = this;
                if (!self._isActived()) {
                    return;
                }

                self._updateItemsViewCall({ sortExpression: sortExpression, sortDirection: sortDirection });
            };

            wijfileexplorer.prototype._page = function (pageIndex) {
                var self = this;
                if (!self._isActived() || !self.options.allowPaging) {
                    return;
                }

                self._updateItemsViewCall({ pageIndex: pageIndex });
            };

            wijfileexplorer.prototype._getDetailViewSelectedCells = function () {
                return this._detailView.wijgrid("selection")["selectedCells"]();
            };

            wijfileexplorer.prototype._onDetailViewSelectionChanged = function () {
                if (!this._isActived()) {
                    return;
                }

                var self = this, selection = self._getDetailViewSelectedCells(), length = selection.length(), newSelection = [], i, item;
                for (i = 0; i < length; i++) {
                    item = selection.item(i);
                    if (item.cellIndex() === 0) {
                        newSelection.push({
                            path: item.value(),
                            isFolder: isFolder($(item.tableCell()).parent()),
                            operatingArea: 1 /* ItemsView */
                        });
                    }
                }

                self._setSelection(newSelection);
            };

            wijfileexplorer.prototype._getExtendedKeyCode = function () {
                var self = this;
                if (!self._extendedKeyCode) {
                    self._extendedKeyCode = $.extend({
                        BACK: 8,
                        ESC: 27,
                        PAGEUP: 33,
                        PAGEDOWN: 34,
                        F1: 112,
                        F2: 113,
                        F3: 114,
                        F4: 115,
                        F5: 116,
                        F6: 117,
                        F7: 118,
                        F8: 119,
                        F9: 120,
                        F10: 121,
                        F11: 122,
                        F12: 123
                    }, $.ui.keyCode);
                }

                return self._extendedKeyCode;
            };

            wijfileexplorer.prototype._getInnerShortcuts = function () {
                var self = this;
                if (!self._innerShortcuts) {
                    self._innerShortcuts = {};
                    $.each(self.options.shortcuts || {}, function (key, value) {
                        self._innerShortcuts[key] = value.split('+');
                    });
                }

                return self._innerShortcuts;
            };

            wijfileexplorer.prototype._matchShortcuts = function (e) {
                var self = this, shortcuts = self._getInnerShortcuts(), actionName, ctrlKey, key, ctrlKeyPressed, extendedKeyCode = self._getExtendedKeyCode(), char = String.fromCharCode(e.keyCode);

                //We only support two keys combination for shortcuts.
                //e.g.ctrl + A, shift + B etc. ctrl + A + B is invalid.
                $.each(shortcuts, function (name, keys) {
                    //Note, here ctrlKey includes ctrl, shift, alt key other than only ctrl key.
                    ctrlKey = (keys.length && keys[0]).toLowerCase() + "Key"; //"ctrlKey", "shiftKey", "altKey".
                    key = keys.length && (keys.length === 1 ? keys[0] : keys[1]).toUpperCase();
                    ctrlKeyPressed = e[ctrlKey];

                    //The key is among the extended keys(all keys except alphabet and numbers).
                    if (e.keyCode === extendedKeyCode[key]) {
                        if (keys.length === 1 || ctrlKeyPressed) {
                            actionName = name;
                            return false;
                        }

                        return true;
                    }

                    if (char && char === key) {
                        if (keys.length === 1 || ctrlKeyPressed) {
                            actionName = name;
                            return false;
                        }

                        return true;
                    }
                });

                return actionName || false;
            };

            wijfileexplorer.prototype._processShortcut = function (e) {
                var self = this, o = self.options, actionName, command;

                if (o.disabled) {
                    return;
                }

                actionName = self._matchShortcuts(e);

                //not a shortcut
                if (!actionName) {
                    return;
                }

                if (self._dialog.is(":visible")) {
                    //only popupWindowClose shortcut works when dialog is opened.
                    if (actionName !== "popupWindowClose") {
                        return;
                    }
                } else if (!self._isChildElement($(e.target)) && actionName !== "focusFileExplorer") {
                    //Only focusFileExplorer shortcut can be triggerred outside fileexplorer when dialog is closed,
                    //so for other shortcut we need judge whether the e.target is the child
                    //element of fileexplorer element.
                    return;
                }

                command = self._commands[actionName];

                if (command) {
                    command.execute();
                    e.stopPropagation();
                    e.preventDefault();
                }
            };

            wijfileexplorer.prototype._setFocus = function ($el, $focusedEl, $parentEl) {
                var self = this, focusCss = self._focusCss, $focusedElement = $focusedEl, $parent = $parentEl || self.element.parent();

                if (!$el || !$el.length) {
                    return;
                }

                if (!$focusedElement || !$focusedElement.length) {
                    $focusedElement = $el;
                }

                if ($focusedElement) {
                    $focusedElement.focus();
                }

                $parent.find("." + focusCss).removeClass(focusCss);
                $el.addClass(focusCss);
            };

            wijfileexplorer.prototype._focusFileExplorer = function () {
                var self = this;

                self._setFocus(self.element);
                self._restoreFocus = $.proxy(self._focusFileExplorer, self);
            };

            wijfileexplorer.prototype._focusToolBar = function () {
                var self = this, $toolBar = self.element.find("." + css.toolbar), $firstEl = $toolBar.find("li").first();

                if ($firstEl.length) {
                    self._setFocus($toolBar.parent());
                    $firstEl.addClass(self._focusCss);
                }
            };

            wijfileexplorer.prototype._focusTreeView = function () {
                var self = this, $tv = self._treeView, $focusedEl;

                if ($tv && $tv.length) {
                    //currently focus is already on treeview.
                    if ($tv.find(":focus").length) {
                        return;
                    }

                    $focusedEl = $tv.find("span." + self._activeCss).first();
                    if ($focusedEl && $focusedEl.length) {
                        $focusedEl = $focusedEl.find("a." + css.tvLink).first();
                    } else {
                        $focusedEl = $tv.find("li a." + css.tvLink).first();
                    }

                    //here $tv is "ul" and its parent is "div"(wijmo-wijtree).
                    //but we need add focus style to wijtree's container.
                    //So I need use the ugly code $tv.parent().parent().
                    self._setFocus($tv.parent().parent(), $focusedEl);
                }
                self._restoreFocus = $.proxy(self._focusTreeView, self);
            };

            wijfileexplorer.prototype._focusGrid = function () {
                var self = this, dv = self._detailView, tv = self._thumbnailView, showingDetialView = self._showingControls[visibleControls.detailView], showingThumbnailView = self._showingControls[visibleControls.thumbnailView], $tds, $focusedEl, $focusableContainer = self._itemsViewContainer.parent();

                //Currently focus is already on the detail/thumbnail view.
                if ($focusableContainer.hasClass(self._focusCss)) {
                    return;
                }

                if (showingDetialView) {
                    if (dv && dv.length) {
                        $tds = dv.find("tbody tr td");
                        $focusedEl = $tds.filter("." + css.stateHighlight).first();

                        self._setFocus($focusableContainer);

                        //Here we need use a trick(($first td).click()) to select the first row
                        //when no row is selected before this action.
                        if ($focusedEl.length === 0) {
                            $tds.first().click();
                        } else {
                            dv.parent().focus();
                        }
                    }
                } else if (showingThumbnailView) {
                    if (tv && tv.length) {
                        self._setFocus($focusableContainer);
                        tv.wijtilelist("setFocus");
                    }
                }

                self._restoreFocus = $.proxy(self._focusGrid, self);
            };

            wijfileexplorer.prototype._focusAddressBar = function () {
                var self = this, $addressBar = self.element.find("." + css.addressBar);

                if ($addressBar && $addressBar.length) {
                    self._setFocus($addressBar, $addressBar.find("." + css.address));
                }
            };

            wijfileexplorer.prototype._popupWindowClose = function () {
                var self = this;

                if (!self._dialog || !self._dialog.is(":visible")) {
                    return;
                }

                self._hideDialog();
                self._restoreFocus && self._restoreFocus();
            };

            wijfileexplorer.prototype._openContextMenu = function () {
                var self = this, activeItem = self._getOperatingItem(), $activeElement = activeItem && self._getElementByPath(activeItem.path, activeItem.operatingArea);

                if (!$activeElement || !$activeElement.length) {
                    $activeElement = self.element;
                }

                $activeElement.trigger("contextmenu");
            };

            wijfileexplorer.prototype._focusPager = function () {
                var self = this, o = self.options, $pager = self._pager, $firstPagerItem;

                if (!$pager || !$pager.length) {
                    return;
                }

                $firstPagerItem = $pager.find("a").first();

                if ($firstPagerItem && $firstPagerItem.length) {
                    self._setFocus($pager); //, $firstPagerItem);

                    //This is also a trick because current selected pager item has no anchor element.
                    $pager.find("li." + css.stateActive).addClass(self._focusCss).off(eventNameSpaceSuffix).on("keydown" + eventNameSpaceSuffix, function (e) {
                        if (o.disabled) {
                            return;
                        }
                        return self._processShortcut(e);
                    });
                }
            };

            wijfileexplorer.prototype._getElementByPath = function (path, operatingArea) {
                var self = this, node;

                if (operatingArea === 0 /* TreeView */) {
                    node = self._getNodeByPath(path);

                    if (node && node.element) {
                        return node.element;
                    }

                    return null;
                }

                return self._getViewItemByPath(path, self._showingControls[visibleControls.detailView]);
            };

            wijfileexplorer.prototype._getViewItemByPath = function (path, isDetailView) {
                var self = this;

                if (isDetailView) {
                    return self._getDetailViewItemByPath(path);
                }

                return self._getThumbnailViewItemByPath(path);
            };

            wijfileexplorer.prototype._getDetailViewItemByPath = function (path) {
                var self = this, $rows = self._detailView.find("tr"), $item = $rows.first();

                $rows.each(function (rowIdx, row) {
                    var $tds = $(row).find("td.wijgridtd"), matched = false;

                    $tds.each(function (cellIdx, cell) {
                        var $td = $(cell);

                        if ($td.text() === getItemName(path)) {
                            matched = true;
                            return false;
                        }
                    });

                    if (matched) {
                        $item = $(row);
                        return false;
                    }
                });

                return $item;
            };

            wijfileexplorer.prototype._getThumbnailViewItemByPath = function (path) {
                var self = this, $tiles = self._thumbnailView.find("li"), $item = $tiles.first();

                $tiles.each(function (tileIdx, tile) {
                    var $span = $(tile).find("span." + css.tileContent);

                    if ($span.text() === getItemName(path)) {
                        $item = $(tile);
                        return false;
                    }
                });

                return $item;
            };

            wijfileexplorer.prototype._onTreeViewRightKeyDown = function () {
                var self = this, focusedNode, $focusedEl, $tv = self._treeView;

                if ($tv) {
                    $focusedEl = $tv.find(":focus");

                    if (!$focusedEl || !$focusedEl.length) {
                        $focusedEl = $tv.find("." + self._focusCss);
                    }

                    focusedNode = $focusedEl.parents("li").first().data("wijmo-wijtreenode");
                    if (focusedNode && !focusedNode.options.expanded && (!focusedNode.$nodes || !focusedNode.$nodes.length)) {
                        self._expandWithNewNodes(focusedNode.options.value);
                    }
                }
            };

            wijfileexplorer.prototype._onTreeNodeClick = function (e, ui) {
                var self = this, o = self.options;

                if (!self._isActived())
                    return;

                // avoid dead loop;
                ui._isClick = false;
                if (!ui.options.selected) {
                    ui._selectNode(true);
                }

                self._setSelection({
                    path: ui.options.value,
                    isFolder: isFolder(ui.element),
                    operatingArea: 0 /* TreeView */
                }, e.ctrlKey);

                if (o.mode === explorerMode["default"]) {
                    self._openFolder(ui.options.value);
                }
            };

            wijfileexplorer.prototype._isActived = function () {
                var self = this, o = self.options, rootPaths = self._getRootPaths();
                return !!(!o.disabled && o.currentFolder && rootPaths && rootPaths.length);
            };

            wijfileexplorer.prototype._setDragDrop = function () {
                var self = this;
                self._setTreeViewDragDrop();
                self._setItemsViewDragDrop();
            };

            wijfileexplorer.prototype._setTreeViewDragDrop = function () {
                var self = this, $nodeDiv = self._treeView.find("div.wijmo-wijtree-node");
                self._setDraggable($nodeDiv);
                self._setDroppable($nodeDiv);
            };

            wijfileexplorer.prototype._setItemsViewDragDrop = function () {
                var self = this, itemsView;
                if (self._showingControls[visibleControls.detailView]) {
                    itemsView = self._detailView;
                } else if (self._showingControls[visibleControls.thumbnailView]) {
                    itemsView = self._thumbnailView;
                }

                if (itemsView == null) {
                    return;
                }

                self._setItemsViewDrag(itemsView);
                self._setDroppable(itemsView.find("." + css.folderItem));
            };

            wijfileexplorer.prototype._setItemsViewDrag = function (itemsView) {
                var self = this, options = self.options, wijCSS = options.wijCSS, $draggableItem = itemsView.find("." + css.fileItem + ",." + css.folderItem), isDetailView = $draggableItem.hasClass("wijmo-wijgrid-row"), $element, selected;

                if (!$draggableItem && !$draggableItem.length) {
                    return;
                }

                // first make all items be draggable
                self._setDraggable($draggableItem);

                if (!isDetailView) {
                    return;
                }

                // make the content in detailView's row be draggable
                self._setDraggable($draggableItem.find("td[headers='Name']").find(".wijmo-wijgrid-innercell").children());

                if (options.disabled) {
                    return;
                }

                // disable draggable of the unselected detailView row
                $draggableItem.each(function (index, element) {
                    $element = $(element);
                    selected = isDetailView ? $element.find("td").hasClass(wijCSS.stateHighlight) : $element.hasClass(wijCSS.stateActive);
                    $element.draggable("option", "disabled", !selected);
                });
            };

            wijfileexplorer.prototype._setDraggable = function ($element) {
                var self = this, $item;
                $element.each(function (index, item) {
                    $item = $(item);
                    if (!$item.data("ui-draggable")) {
                        $item.draggable(self._createDragOptions());
                    }
                });

                $element.draggable("option", "disabled", self.options.disabled);
            };

            wijfileexplorer.prototype._setDroppable = function ($element) {
                var self = this, $item;
                $element.each(function (index, item) {
                    $item = $(item);
                    if (!$item.data("ui-droppable")) {
                        $item.droppable({
                            drop: function (event, ui) {
                                self._onDrop(event, ui, this);
                            }
                        });
                    }
                });

                $element.droppable("option", "disabled", self.options.disabled);
            };

            wijfileexplorer.prototype._createDragOptions = function () {
                var self = this;
                return {
                    revert: "invalid",
                    helper: function (event) {
                        var dragItem = self._getItemFromElement(this), dragItems = [], helperElement = $("<ul>").addClass(self.options.wijCSS.helperReset), dragItemHeight = 20, wijgrid, fakeClickEvent, $element = $(this);

                        if (dragItem.operatingArea !== 0 /* TreeView */) {
                            // add the dragging item to selection
                            if (!self._isSelected(dragItem)) {
                                if ($element.hasClass(css.tileItem)) {
                                    self._thumbnailView.wijtilelist("selectTile", $element, event.ctrlKey);
                                } else {
                                    // wijgrid has no setting selection interface, here is a trick for setting selection
                                    fakeClickEvent = jQuery.Event("click");
                                    fakeClickEvent.ctrlKey = event.ctrlKey;
                                    fakeClickEvent.shiftKey = event.shiftKey;
                                    fakeClickEvent.target = event.target;
                                    wijgrid = self._detailView.data("wijmo-wijgrid");
                                    wijgrid._onClick(fakeClickEvent);
                                }
                            }

                            $.each(self._selection, function (i, item) {
                                dragItems.push(item);
                            });
                        } else {
                            dragItems.push(dragItem);
                        }

                        $.each(dragItems, function (i, item) {
                            var icon = $("<span>").addClass("ui-icon").addClass(item.isFolder ? css.folderCollapsedIcon : css.documentIcon), text = $("<span>").addClass(css.contentItem).addClass(css.dragContent).text(getItemName(item.path)), helperItem = $("<li>").append(icon).append(text).height(dragItemHeight);
                            helperElement.append(helperItem);
                            helperElement.data(dragItemsDataName, dragItems);
                        });

                        $element.draggable("option", "cursorAt", {
                            top: dragItemHeight * dragItems.length / 2,
                            left: 0
                        });

                        return helperElement;
                    }
                };
            };

            wijfileexplorer.prototype._onDrop = function (event, ui, target) {
                var self = this, items = ui.helper.data(dragItemsDataName), desPath = self._getItemFromElement(target).path, combinedItems, index = 0, count;

                if (!items || !items.length) {
                    return;
                }

                count = items.length;

                ui.helper.data(dragItemsDataName, null);

                for (; index < count; index++) {
                    if (items[index].path === desPath) {
                        return;
                    }
                }

                combinedItems = combinePaths(items);

                if (event.ctrlKey) {
                    self._paste(combinedItems, desPath);
                } else if (!self._hasRootPath(combinedItems)) {
                    self._move(combinedItems, desPath);
                }
            };

            wijfileexplorer.prototype._pasteCall = function (items, targetPath) {
                var self = this, addedPaths = $.map(items, function (item) {
                    return item.path;
                });
                self._tryAjax(ajaxCommands.paste, { sourcePaths: addedPaths, path: targetPath }, null, function (result) {
                    if (!result.itemOperationResults || !result.itemOperationResults.length) {
                        return;
                    }

                    $.each(result.itemOperationResults, function (i, item) {
                        if (!item) {
                            return;
                        }

                        if (item.success) {
                            self._triggerItemPasted({ path: item.path, targetFolder: targetPath });
                            return;
                        }

                        self._processError(item.error);
                    });

                    self._refreshAfterAdd(targetPath);
                }, function () {
                    self._refreshAfterAdd(targetPath);
                }, function () {
                    var newItems = $.map(items, function (item) {
                        return $.extend({}, item, { path: ensureFolderSeparator(targetPath) + getItemName(item.path) });
                    });
                    self._addItemsInData(newItems);
                    self._refreshAfterAdd(targetPath);
                });
            };

            wijfileexplorer.prototype._move = function (items, targetPath) {
                var self = this, movingItems = [];

                if (!items || !targetPath) {
                    return;
                }

                $.each(items, function (i, item) {
                    if (self._triggerItemMoving({ sourcePath: item.path, targetFolder: targetPath }) === false) {
                        return false;
                    }

                    movingItems.push(item);
                });

                if (!movingItems.length) {
                    return;
                }

                var paths = $.map(movingItems, function (item) {
                    return item.path;
                });
                self._tryAjax(ajaxCommands.move, { sourcePaths: paths, path: targetPath }, null, function (result) {
                    if (!result.itemOperationResults || !result.itemOperationResults.length) {
                        return;
                    }
                    var movedItems = [];
                    $.each(result.itemOperationResults, function (i, item) {
                        if (!item) {
                            return;
                        }

                        if (item.success) {
                            self._triggerItemMoved({ sourcePath: item.path, targetFolder: targetPath });
                            movedItems.push(findItemByPath(movingItems, item.path));
                            return;
                        }

                        self._processError(item.error);
                    });

                    self._refreshAfterMove(movedItems, targetPath);
                }, function () {
                    self._refreshAfterMove(items, targetPath);
                }, function () {
                    var newItems = $.map(items, function (item) {
                        return $.extend({}, item, { path: ensureFolderSeparator(targetPath) + getItemName(item.path) });
                    });
                    self._removeItemsInData(items, true);
                    self._addItemsInData(newItems);
                    self._refreshAfterMove(items, targetPath);
                });
            };

            wijfileexplorer.prototype._refreshAfterAdd = function (targetPath) {
                this.refresh(targetPath);
            };

            wijfileexplorer.prototype._refreshAfterMove = function (items, targetPath) {
                this._refreshAfterDelete(items);
                this.refresh(targetPath);
            };

            wijfileexplorer.prototype._refreshAfterDelete = function (items) {
                var self = this, parentPathMap = {}, currentFolder = self.options.currentFolder, refreshFolderTo, currentParentFolder = getParentPath(currentFolder);

                $.each(items, function (index, item) {
                    var path = item.path, parentPath = getParentPath(item.path);

                    parentPathMap[path] = parentPath;

                    if (!refreshFolderTo && parentPath === currentFolder) {
                        refreshFolderTo = currentFolder;
                    }

                    if (item.isFolder) {
                        if (!refreshFolderTo && (isAncestorFolder(item.path, currentFolder) || item.path === currentFolder)) {
                            refreshFolderTo = currentParentFolder;
                        } else if (refreshFolderTo && isAncestorFolder(item.path, refreshFolderTo)) {
                            refreshFolderTo = parentPath;
                        }
                    }
                });

                $.each(parentPathMap, function (key, value) {
                    self._deleteTreeNode(key, value);
                });

                if (refreshFolderTo === currentFolder) {
                    self.refresh();
                } else if (refreshFolderTo) {
                    self._openFolder(refreshFolderTo);
                }
            };

            wijfileexplorer.prototype._deleteTreeNode = function (path, parentPath) {
                var self = this, deletingNode = self._getNodeByPath(path), parentNode = self._getNodeByPath(parentPath), hasChildrenAfterDelete;

                if (parentNode && deletingNode) {
                    hasChildrenAfterDelete = !!(parentNode.options.nodes.length - 1);
                    self._initNodeHasChildren(parentNode, hasChildrenAfterDelete);
                    parentNode.remove(deletingNode.element);
                }
            };

            //End Operation
            //Begin Selection
            wijfileexplorer.prototype._getCurrentFolderItem = function () {
                var self = this, data = self._data() || [], index = 0, length = data.length, hasChildren = length > 0, hasSubFolders = false;
                for (; index < length; index++) {
                    if (data[index].isFolder) {
                        hasSubFolders = true;
                        break;
                    }
                }

                return {
                    path: self.options.currentFolder,
                    isFolder: true,
                    hasChildren: hasChildren,
                    hasSubFolders: hasSubFolders
                };
            };

            wijfileexplorer.prototype._operatingItemsChanged = function () {
                this._updateCommandsForOperatingItems();
            };

            wijfileexplorer.prototype._setOperatingItems = function (value) {
                var self = this;
                if (!$.isArray(value)) {
                    value = [value];
                }

                self._operatingItems = value;
                self._operatingItemsChanged();
            };

            wijfileexplorer.prototype._setContextItem = function (value) {
                var self = this;
                self._contextItem = value;
                self._setOperatingItems(value || self._selection);
            };

            wijfileexplorer.prototype._isSelected = function (item) {
                var selection = this._selection, found = false;
                if (selection) {
                    $.each(selection, function (index, value) {
                        if (value.path === item.path && value.operatingArea === item.operatingArea) {
                            found = true;
                            return false;
                        }
                    });
                }

                return found;
            };

            wijfileexplorer.prototype._sameWithSelection = function (items) {
                var selection = this._selection || [], isSame = false, item;
                if (!items) {
                    items = [];
                }

                if ($.isPlainObject(items)) {
                    items = [items];
                }

                if (items.length === selection.length) {
                    isSame = true;
                    $.each(selection, function (index, value) {
                        item = items[index];
                        if (value.path !== item.path || value.operatingArea !== item.operatingArea) {
                            isSame = false;
                            return false;
                        }
                    });
                }

                return isSame;
            };

            wijfileexplorer.prototype._setSelection = function (value, isAppend) {
                var self = this;
                if (self._selectionUpdating) {
                    return;
                }

                self._selection = self._selection || [];

                if (!isAppend) {
                    self._selection.length = 0;
                }

                if (!$.isArray(value)) {
                    value = [value];
                }

                if (!value) {
                    return;
                }

                $.each(value, function (i, e) {
                    if (e != null) {
                        self._selection.push(e);
                    }
                });
                self._setOperatingItems(self._contextItem || self._selection);
                self._triggerItemSelected({ path: (self._selection && self._selection.length) ? self._selection[0].path : null });
            };

            wijfileexplorer.prototype._getOperatingItems = function () {
                var self = this, contextItem = self._contextItem, items, selection = self._selection;

                if (!contextItem) {
                    return (selection && selection.length) ? selection : [self._getCurrentFolderItem()];
                }

                items = [contextItem];

                if (contextItem.operatingArea === 1 /* ItemsView */ && selection) {
                    $.each(selection, function (index, value) {
                        if (value.operatingArea === 1 /* ItemsView */ && value.path !== contextItem.path) {
                            items.push(value);
                        }
                    });
                }

                return items;
            };

            wijfileexplorer.prototype._getOperatingItem = function () {
                return this._getOperatingItems()[0];
            };

            wijfileexplorer.prototype._getFocusedItemElement = function () {
                var self = this, item = self._getOperatingItem(), cells;
                if (!item || !item.path) {
                    return null;
                }

                if (self._currentFocusArea === "detailGrid") {
                    cells = self._detailView.find("td.wijgridtd");
                } else if (self._currentFocusArea === "tileList") {
                    cells = self._thumbnailView.find("li.wijmo-wijtilelist-item");
                } else if (self._currentFocusArea === "treeView") {
                    cells = self._treeView.find("li");
                }

                if (!cells || !cells.length) {
                    return;
                }

                for (var index = 0, length = cells.length; index < length; index++) {
                    var cell = cells[index];
                    if (cell && cell.text() === item.path) {
                        return cell;
                    }
                }
            };

            wijfileexplorer.prototype._getItemFromElement = function (el) {
                var self = this, o = self.options, $item = self._getFileItem(el), path, operatingArea, pathSeparator = getFolderSeparator(o.currentFolder);

                if (!$item || $item.length === 0) {
                    return;
                }

                //item is treenode, then return node.value.
                if ($item.is(":wijmo-wijtreenode")) {
                    path = $item["wijtreenode"]("option", "value");
                    operatingArea = 0 /* TreeView */;
                } else {
                    path = o.currentFolder + pathSeparator + self._getItemText($item);
                    operatingArea = 1 /* ItemsView */;
                }

                return {
                    path: path,
                    isFolder: isFolder($item),
                    operatingArea: operatingArea
                };
            };

            wijfileexplorer.prototype._getFileItem = function (el) {
                return $(el).closest("." + css.folderItem + ",." + css.fileItem);
            };

            wijfileexplorer.prototype._isTreeviewNode = function (el) {
                return this._getFileItem(el).is(":wijmo-wijtreenode");
            };

            wijfileexplorer.prototype._getItemText = function ($item) {
                var $span = $item.find("span." + css.contentItem).filter(function (index, element) {
                    return !$(element).hasClass(css.dragContent);
                });

                if ($span.length > 0) {
                    return $span.text();
                }

                $span = $item.find("span.wijmo-wijtilelist-content");
                if ($span.length > 0) {
                    return $span.text();
                }
            };

            //End Selection
            //Begin Data
            wijfileexplorer.prototype._findItemInData = function (item, items) {
                if (!items) {
                    return -1;
                }

                item = $.isPlainObject(item) ? item.path : item;
                for (var index = 0, length = items.length; index < length; index++) {
                    if (item === items[index].path) {
                        return index;
                    }
                }

                return -1;
            };

            wijfileexplorer.prototype._addItemsInData = function (items, targetItem, preventRefreshData) {
                if (!$.isArray(items)) {
                    items = [items];
                }

                var self = this, data = targetItem ? ($.isArray(targetItem) ? targetItem : targetItem.children) : self._getFolderData(getParentPath(items[0].path));

                if (!data) {
                    return;
                }

                $.each(items, function (i, item) {
                    data.push(item);
                    if (!preventRefreshData) {
                        self._data(self._data());
                    }
                });
            };

            wijfileexplorer.prototype._removeItemsInData = function (items, preventRefreshData) {
                var self = this;

                if (!$.isArray(items)) {
                    items = [items];
                }

                $.each(items, function (i, item) {
                    var data = self._getFolderData(getParentPath(item.path));
                    if (data) {
                        var index = self._findItemInData(item, data);
                        if (index > -1) {
                            data.splice(index, 1);
                            if (!preventRefreshData) {
                                self._data(self._data());
                            }
                        }
                    }
                });
            };

            wijfileexplorer.prototype._getCurrentFolderData = function () {
                var self = this;
                return self._enableAjax() ? self._data() : self._getFolderData(self.options.currentFolder);
            };

            wijfileexplorer.prototype._getFolderData = function (path, data) {
                var self = this, result;

                if (arguments.length == 1) {
                    data = self._data();
                }

                data = data || [];
                if (!path) {
                    return data;
                }

                for (var index = 0, length = data.length; index < length; index++) {
                    var item = data[index], currentPath = item.path;

                    if (isParentFolder(path, currentPath)) {
                        result = data;
                        break;
                    }

                    if (!item.isFolder) {
                        continue;
                    }

                    if (currentPath === path) {
                        result = item.children;
                        break;
                    }

                    if (isParentFolder(currentPath, path)) {
                        result = self._getFolderData(path, item.children);
                        break;
                    }
                }

                return result || [];
            };

            wijfileexplorer.prototype._sortData = function (data, field, isDescending) {
                var self = this;
                if (!field) {
                    field = columnNames.name;
                }

                data = data || self._data();
                data.sort(function (a, b) {
                    return self._sortComparer(a, b, field, isDescending);
                });
                $.each(data, function (index, item) {
                    if (item.children) {
                        self._sortData(item.children);
                    }
                });
            };

            wijfileexplorer.prototype._sortComparer = function (a, b, field, isDescending) {
                return this._sortComparerInner(a, b, field) * (isDescending ? -1 : 1);
            };

            wijfileexplorer.prototype._sortComparerInner = function (a, b, field) {
                if (a.isFolder != b.isFolder) {
                    return a.isFolder ? -1 : 1;
                }

                var valueA = a[field], valueB = b[field];
                if (valueA === valueB) {
                    return 0;
                }

                return valueA > valueB ? 1 : -1;
            };

            wijfileexplorer.prototype._resolveData = function (data) {
                var self = this;

                if (arguments.length === 0) {
                    if (!self._data()) {
                        self._data([]);
                    }

                    data = self._data();
                }

                $.each(data, function (index, item) {
                    if (!item.hasChildren && !item.children) {
                        item.children = [];
                    }

                    if (item.children || item.children.length > 0) {
                        item.hasChildren = true;
                        var hasSubFolders = false;
                        for (var i = 0, length = item.children.length; i < length; i++) {
                            if (item.isFolder) {
                                hasSubFolders = true;
                                break;
                            }
                        }

                        item.hasSubFolders = hasSubFolders;
                        self._resolveData(item.children);
                    } else {
                        item.hasChildren = false;
                        item.hasSubFolders = false;
                    }
                });
            };

            //End Data
            // Begin Options
            wijfileexplorer.prototype._setCurrentFolder = function (value) {
                var self = this, oldCurrentFolder = self.options.currentFolder;

                self.options.currentFolder = value;
                self._currentFolderUpdated();
                if (oldCurrentFolder !== value) {
                    self._triggerFolderChanged({ newFolder: value, oldFolder: oldCurrentFolder });
                }
            };

            wijfileexplorer.prototype._setOption = function (key, value) {
                var self = this, o = self.options, modeChanged = false, needRefresh = false;

                if (key === "currentFolder") {
                    return;
                }

                if (key === "mode") {
                    modeChanged = value !== o.mode;
                } else if (key === "allowPaging" || (key === "pageSize" && o.allowPaging)) {
                    needRefresh = value !== o[key];
                }

                _super.prototype._setOption.call(this, key, value);

                if (key === "disabled") {
                    self._disabledUpdated();
                } else if (key === "viewMode" || key === "mode" || key === "visibleControls" || key === "allowPaging" || key === "treePanelWidth") {
                    self._layoutOptionsUpdated(modeChanged);
                } else if (key === "enableOpenFile") {
                    self._enableOpenFileUpdated();
                } else if (key === "enableCreateNewFolder") {
                    self._enableCreateNewFolderUpdated();
                } else if (key === "enableCopy") {
                    self._enableCopyUpdated();
                } else if (key === "allowMultipleSelection") {
                    self._allowMultipleSelectionUpdated();
                } else if (key === "actionUri") {
                    self._actionUriUpdated();
                } else if (key === "initPath" || key === "viewPaths") {
                    self._rootPathsUpdated();
                } else if (key === "shortcuts") {
                    self._innerShortcuts = null;
                }

                needRefresh && self.refresh();
            };

            wijfileexplorer.prototype._actionUriUpdated = function () {
                this.options.hostUri = null;
            };

            wijfileexplorer.prototype._disabledUpdated = function () {
                var self = this, disabled = self.options.disabled;

                self._contextMenu.wijmenu("option", "disabled", disabled);
                self._detailView.wijgrid("option", "disabled", disabled);
                self._thumbnailView.wijtilelist("option", "disabled", disabled);
                self._treeView.wijtree("option", "disabled", disabled);
                self._pager.wijpager("option", "disabled", disabled);
                self._splitter.wijsplitter("option", "disabled", disabled);
                self._filterBox.prop("disabled", disabled);
                self._setDragDrop();
            };

            wijfileexplorer.prototype._getRootPaths = function () {
                var options = this.options, initPath = options.initPath, viewPaths = options.viewPaths;
                if (viewPaths && viewPaths.length) {
                    return viewPaths;
                }

                return initPath ? [initPath] : [];
            };

            wijfileexplorer.prototype._enableOpenFileUpdated = function () {
                var self = this;
                self._commands.open.disabled(!self.options.enableOpenFile);
            };

            wijfileexplorer.prototype._enableCreateNewFolderUpdated = function () {
                var self = this;
                self._commands.newFolder.disabled(!self.options.enableCreateNewFolder);
            };

            wijfileexplorer.prototype._allowMultipleSelectionUpdated = function () {
                var self = this;
                self._detailView.wijgrid("option", "selectionMode", self.options.allowMultipleSelection ? "multiRow" : "singleRow");
                self._thumbnailView.wijtilelist("option", "allowMultipleSelection", self.options.allowMultipleSelection);
            };

            wijfileexplorer.prototype._enableCopyUpdated = function () {
                var self = this;
                if (!self.options.enableCopy) {
                    self._copiedItems = null;
                }

                self._commands.copy.disabled(!self.options.enableCopy);
                self._commands.paste.disabled(!self.options.enableCopy || self._copiedItems == null || self._copiedItems.length === 0);
            };

            wijfileexplorer.prototype._initDataOptions = function () {
                var self = this, data = self.options.data, rootPaths;

                delete self.options.data;

                if (data && data.length) {
                    rootPaths = self._getRootPaths();
                    if (!rootPaths || !rootPaths.length) {
                        self.options.viewPaths = $.map(data, function (item) {
                            return item.path;
                        });
                    }
                }

                if (!self.options.currentFolder) {
                    rootPaths = self._getRootPaths();
                    if (rootPaths && rootPaths.length) {
                        self.options.currentFolder = rootPaths[0];
                    }
                }

                if (data) {
                    self._data(data);
                }
            };

            wijfileexplorer.prototype._currentFolderUpdated = function () {
                var self = this, currentFolder = self.options.currentFolder;
                self._updateHistory();
                self._addressBox.text(currentFolder).attr("title", currentFolder);
                if (self._showingControls[visibleControls.detailView] || self._showingControls[visibleControls.thumbnailView]) {
                    self._updateItemsView();
                    self._triggerFolderLoaded({ currentFolder: currentFolder });
                }
                self._showCurrentFolderTreeNode();
            };

            wijfileexplorer.prototype._updateItemsView = function (isFilterChanged) {
                if (typeof isFilterChanged === "undefined") { isFilterChanged = false; }
                var self = this, showingDetialView = self._showingControls[visibleControls.detailView], showingThumbnailView = self._showingControls[visibleControls.thumbnailView], data = self._getCurrentFolderData(), filterExpression = self._filterExpression() || defaultFilterExpression;

                self._itemsViewContainer.height(Math.max(0, self._pager.parent().height() - (self.options.allowPaging ? self._pager.outerHeight() : 0) - parseInt(self._itemsViewContainer.css("borderTopWidth")) - parseInt(self._itemsViewContainer.css("borderBottomWidth"))));

                if (showingDetialView) {
                    self._updatingDetailViewData = true;
                    self._detailView.wijgrid("option", "data", data).wijgrid("ensureControl", true);
                    self._updatingDetailViewData = false;
                    self._adjustDetailViewWidth();
                } else if (showingThumbnailView) {
                    self._thumbnailView.wijtilelist("option", "data", data);
                }

                if (!data || !data.length) {
                    self._emptyFolderTip.show();
                } else {
                    self._emptyFolderTip.hide();
                }

                if (self.options.allowPaging) {
                    self._pager.wijpager("option", {
                        pageCount: self._pageCount(),
                        pageIndex: self._pageIndex()
                    });
                }
                if (!isFilterChanged && filterExpression !== self._filterBox.val()) {
                    self._filterBox.val(filterExpression);
                }

                self._setItemsViewDragDrop();
            };

            wijfileexplorer.prototype._updateHistory = function () {
                var self = this;
                if (!self._histories) {
                    self._histories = [];
                    self._currentHistoryIndex = -1;
                }

                var currentFolder = self.options.currentFolder, histories = self._histories, length = histories.length;

                if (self._updatingHistoryStep) {
                    var newIndex = self._currentHistoryIndex + self._updatingHistoryStep;
                    self._updatingHistoryStep = 0;
                    if (newIndex >= length || newIndex < 0) {
                        return;
                    }

                    self._currentHistoryIndex = newIndex;
                } else {
                    if (length && currentFolder === histories[length - 1]) {
                        return;
                    }

                    self._currentHistoryIndex++;
                    histories.splice(self._currentHistoryIndex, length - self._currentHistoryIndex, currentFolder);
                }

                self._commands.back.disabled(!self._canBack());
                self._commands.forward.disabled(!self._canForward());
            };

            wijfileexplorer.prototype._canBack = function () {
                var self = this;
                return self._histories && self._histories.length > 1 && self._currentHistoryIndex > 0;
            };

            wijfileexplorer.prototype._canForward = function () {
                var self = this;
                return self._histories && self._histories.length > 1 && self._currentHistoryIndex < self._histories.length - 1;
            };

            wijfileexplorer.prototype._showCurrentFolderTreeNode = function () {
                var self = this;
                self._expand(self._getParentNodeByPath(self.options.currentFolder), function () {
                    return self._selectCurrentFolderTreeNode();
                });
            };

            wijfileexplorer.prototype._expandWithExistedNodes = function (node) {
                while (node) {
                    if (!node.options.expanded) {
                        node.expand();
                    }

                    node = this._getParentNodeByPath(node.options.value);
                }
            };

            wijfileexplorer.prototype._updateTreeViewData = function (path, data) {
                var self = this, currentNode = self._getNodeByPath(path) || self._treeView.data("wijmoWijtree");

                data = data || [];
                self._setTreeViewNodes(self._getFolderData(path, data), currentNode);
                self._setTreeViewDragDrop();
            };

            wijfileexplorer.prototype._getParentNodeByPath = function (path) {
                return path ? this._getNodeByPath(getParentPath(path)) : null;
            };

            wijfileexplorer.prototype._getNodeByPath = function (path, nodes) {
                var self = this;
                if (!nodes) {
                    nodes = self._treeView.wijtree('getNodes');
                }
                for (var i = 0; i < nodes.length; i++) {
                    var item = nodes[i];
                    if (item.options.value == path)
                        return item;
                    var children = item.getNodes();
                    if (children.length > 0) {
                        var result = self._getNodeByPath(path, children);
                        if (null == result)
                            continue;
                        else
                            return result;
                    }
                }
                return null;
            };

            wijfileexplorer.prototype._updateCommandsForOperatingItems = function () {
                var self = this, operatingItems = self._getOperatingItems(), commands = self._commands;
                commands.rename.disabled(self._isRootPath(operatingItems[0].path));
                commands["delete"].disabled(self._hasRootPath(operatingItems));
            };

            wijfileexplorer.prototype._layoutOptionsUpdated = function (modeChanged) {
                var self = this, o = self.options, wijCSS = o.wijCSS, addressBar = self.element.find("." + css.addressBar), splitter = self.element.find("." + css.splitterV), splitterVPanel1 = self.element.find("." + css.splitterVPanel1), splitterVPanel2 = self.element.find("." + css.splitterVPanel2), splitterVPanel1Content = self.element.find("." + css.splitterVPanel1Content), splitterVPanel2Content = self.element.find("." + css.splitterVPanel2Content), shouldShowToolbar = self._isVisibleControl(visibleControls.toolbar), shouldShowAddressBox = self._isVisibleControl(visibleControls.addressBox), shouldShowDetailView = self._isVisibleControl(visibleControls.detailView) && o.mode === explorerMode["default"] && o.viewMode === viewMode.detail, shouldShowThumbnailView = self._isVisibleControl(visibleControls.thumbnailView) && o.mode === explorerMode["default"] && o.viewMode === viewMode.thumbnail, shouldShowViewModeBtns = self._isVisibleControl(visibleControls.detailView) && self._isVisibleControl(visibleControls.thumbnailView) && o.mode === explorerMode["default"], shouldShowTreeView = self._isVisibleControl(visibleControls.treeView), shouldShowContextMenu = self._isVisibleControl(visibleControls.contextMenu), shouldShowFilterBox = self._isVisibleControl(visibleControls.filterBox) && (shouldShowDetailView || shouldShowThumbnailView), setDetailViewBtn = self._toolbar.children("." + css.toolbarSetDetailViewMode), setThumbnailViewBtn = self._toolbar.children("." + css.toolbarSetThumbnailViewMode), oldShowingControls = self._showingControls, oldShowingSplitter = oldShowingControls[visibleControls.treeView] && (oldShowingControls[visibleControls.detailView] || oldShowingControls[visibleControls.thumbnailView]), showingSplitter = shouldShowTreeView && (shouldShowDetailView || shouldShowThumbnailView), bottomControlHeight;

                self._showingControls = {};
                self._showingControls[visibleControls.contextMenu] = shouldShowContextMenu;

                self._showingControls[visibleControls.toolbar] = shouldShowToolbar;
                if (shouldShowToolbar) {
                    self._toolbar.show();
                } else {
                    self._toolbar.hide();
                }

                self._showingControls[visibleControls.addressBox] = shouldShowAddressBox;
                if (shouldShowAddressBox) {
                    self._addressBox.show();
                    self._addressBox.parent().show();
                    if (!shouldShowFilterBox) {
                        self._addressBox.parent().addClass(css.addressBarFullWidth);
                    } else {
                        self._addressBox.parent().removeClass(css.addressBarFullWidth);
                    }
                } else {
                    self._addressBox.hide();
                    self._addressBox.parent().hide();
                }

                self._showingControls[visibleControls.filterBox] = shouldShowFilterBox;
                if (shouldShowFilterBox) {
                    self._filterBox.show();
                    self._filterBox.parent().show();
                    if (!shouldShowAddressBox) {
                        self._filterBox.parent().addClass(css.addressBarFullWidth);
                    } else {
                        self._filterBox.parent().removeClass(css.addressBarFullWidth);
                    }
                } else {
                    self._filterBox.hide();
                    self._filterBox.parent().hide();
                }

                if (shouldShowAddressBox || shouldShowFilterBox) {
                    addressBar.show();
                } else {
                    addressBar.hide();
                }

                bottomControlHeight = self.element.height() - (self._toolbar.is(":visible") ? self._toolbar.height() : 0) - (addressBar.is(":visible") ? addressBar.height() : 0);

                splitterVPanel1Content.height(bottomControlHeight);
                splitterVPanel2Content.height(bottomControlHeight);
                if (oldShowingSplitter !== showingSplitter) {
                    splitterVPanel1Content.detach();
                    splitterVPanel2Content.detach();
                    if (showingSplitter) {
                        splitterVPanel1Content.appendTo(splitterVPanel1);
                        splitterVPanel2Content.appendTo(splitterVPanel2);
                    } else {
                        splitterVPanel1Content.appendTo(self.element);
                        splitterVPanel2Content.appendTo(self.element);
                    }
                }

                if (showingSplitter) {
                    splitterVPanel1.height(bottomControlHeight);
                    splitterVPanel2.height(bottomControlHeight);
                    splitter.height(bottomControlHeight).wijsplitter("option", "splitterDistance", o.treePanelWidth).show();
                } else {
                    splitter.hide();
                }

                self._showingControls[visibleControls.treeView] = shouldShowTreeView;
                if (shouldShowTreeView) {
                    self._treeView.show();
                    splitterVPanel1Content.show();
                } else {
                    self._treeView.hide();
                    splitterVPanel1Content.hide();
                }

                self._showingControls[visibleControls.detailView] = shouldShowDetailView;
                if (shouldShowDetailView) {
                    self._detailView.show();
                    self._detailView.parent().show();
                } else {
                    self._detailView.hide();
                    self._detailView.parent().hide();
                }

                self._showingControls[visibleControls.thumbnailView] = shouldShowThumbnailView;
                if (shouldShowThumbnailView) {
                    self._thumbnailView.show();
                } else {
                    self._thumbnailView.hide();
                }

                if (shouldShowDetailView || shouldShowThumbnailView) {
                    splitterVPanel2Content.show();
                } else {
                    splitterVPanel2Content.hide();
                }

                if (shouldShowViewModeBtns) {
                    setDetailViewBtn.show();
                    setThumbnailViewBtn.show();
                } else {
                    setDetailViewBtn.hide();
                    setThumbnailViewBtn.hide();
                }

                if (o.viewMode === viewMode.thumbnail) {
                    setDetailViewBtn.removeClass(wijCSS.stateActive);
                    setThumbnailViewBtn.addClass(wijCSS.stateActive);
                } else {
                    setDetailViewBtn.toggleClass(wijCSS.stateActive);
                    setThumbnailViewBtn.removeClass(wijCSS.stateActive);
                }

                if (self.options.allowPaging) {
                    self._pager.show();
                } else {
                    self._pager.hide();
                }

                if (modeChanged) {
                    self._refreshRoot();
                } else if (shouldShowDetailView || shouldShowThumbnailView) {
                    self._updateItemsView();
                }
            };

            wijfileexplorer.prototype._rootPathsUpdated = function () {
                var self = this;

                // reset history list
                self._histories = [];
                self._currentHistoryIndex = -1;

                self._refreshRoot();
            };

            wijfileexplorer.prototype._refreshRoot = function () {
                var self = this;

                // reset data
                self._data(null);

                // reset currentFolder
                self.options.currentFolder = null;
                self._initDataOptions();

                // reset nodes in tree view
                self._updateTreeViewData(null, []);
                self._createRootNodes();

                // load current folder data
                self._loadCurrentFolder();
            };

            //End Options
            //Begin Events
            wijfileexplorer.prototype._triggerFiltering = function (data) {
                return this._trigger("filtering", null, data);
            };

            wijfileexplorer.prototype._triggerFiltered = function (data) {
                this._trigger("filtered", null, data);
            };

            wijfileexplorer.prototype._triggerItemDeleting = function (data) {
                return this._trigger("itemDeleting", null, data);
            };

            wijfileexplorer.prototype._triggerItemDeleted = function (data) {
                this._trigger("itemDeleted", null, data);
            };

            wijfileexplorer.prototype._triggerItemMoving = function (data) {
                return this._trigger("itemMoving", null, data);
            };

            wijfileexplorer.prototype._triggerItemMoved = function (data) {
                this._trigger("itemMoved", null, data);
            };

            wijfileexplorer.prototype._triggerItemPasting = function (data) {
                return this._trigger("itemPasting", null, data);
            };

            wijfileexplorer.prototype._triggerItemPasted = function (data) {
                this._trigger("itemPasted", null, data);
            };

            wijfileexplorer.prototype._triggerItemCopying = function (data) {
                return this._trigger("itemCopying", null, data);
            };

            wijfileexplorer.prototype._triggerItemCopied = function (data) {
                this._trigger("itemCopied", null, data);
            };

            wijfileexplorer.prototype._triggerItemRenaming = function (data) {
                return this._trigger("itemRenaming", null, data);
            };

            wijfileexplorer.prototype._triggerItemRenamed = function (data) {
                this._trigger("itemRenamed", null, data);
            };

            wijfileexplorer.prototype._triggerNewFolderCreating = function (data) {
                return this._trigger("newFolderCreating", null, data);
            };

            wijfileexplorer.prototype._triggerNewFolderCreated = function (data) {
                this._trigger("newFolderCreated", null, data);
            };

            wijfileexplorer.prototype._triggerErrorOccurred = function (data) {
                return this._trigger("errorOccurred", null, data);
            };

            wijfileexplorer.prototype._triggerItemSelected = function (data) {
                this._trigger("itemSelected", null, data);
            };

            wijfileexplorer.prototype._triggerFileOpening = function (data) {
                return this._trigger("fileOpening", null, data);
            };

            wijfileexplorer.prototype._triggerFileOpened = function (data) {
                this._trigger("fileOpened", null, data);
            };

            wijfileexplorer.prototype._triggerFolderChanged = function (data) {
                this._trigger("folderChanged", null, data);
            };

            wijfileexplorer.prototype._triggerFolderLoaded = function (data) {
                this._trigger("folderLoaded", null, data);
            };

            //End Events
            // Begin Ajax
            wijfileexplorer.prototype._createFakeResponse = function () {
                return {
                    success: true,
                    hostUri: "",
                    items: this._data()
                };
            };

            wijfileexplorer.prototype._tryAjax = function (commandName, data, context, onSuccess, onError, onWithoutAjax) {
                var self = this;

                if (!self._enableAjax()) {
                    if (onWithoutAjax) {
                        onWithoutAjax();
                    } else {
                        onSuccess(self._createFakeResponse());
                    }
                    return;
                }

                if (!self._ajaxActions) {
                    self._ajaxActions = [];
                }

                var endAction = function () {
                    self._ajaxActionEnded();
                    self._ajaxActions.shift();
                    self._nextAjaxAction();

                    if (self._ajaxActions && self._ajaxActions.length === 0) {
                        self._restoreFocus && self._restoreFocus();
                    }
                }, errorAction = function (result) {
                    if (!onError || !onError(result)) {
                        var msg = (typeof result === "string") ? result : result.error;
                        msg = msg || "Unknown error.";
                        self._processError(msg);
                    }
                }, success = function (result) {
                    if (result) {
                        if (result.success && onSuccess) {
                            onSuccess(result);
                        } else if (!result.success) {
                            errorAction(result);
                        }
                    }

                    endAction();
                }, error = function (result) {
                    errorAction(result);
                    endAction();
                };

                data = data || {};
                data.commandName = commandName;
                self._ajaxActions.push(self._createAjaxAction(data, context, success, error));
                if (self._ajaxActions.length === 1) {
                    self._nextAjaxAction();
                }
            };

            wijfileexplorer.prototype._processError = function (error) {
                if (this._triggerErrorOccurred({ error: error }) === false) {
                    return;
                }

                alert(error);
            };

            wijfileexplorer.prototype._nextAjaxAction = function () {
                var self = this;
                if (self._ajaxActions.length > 0) {
                    self._ajaxActions[0]();
                    self._ajaxActionStarted();
                }
            };

            wijfileexplorer.prototype._ajaxActionStarted = function () {
                var self = this;
                self._showLoadingLayer();
            };

            wijfileexplorer.prototype._ajaxActionEnded = function () {
                var self = this;
                self._hideLoadingLayer();
            };

            wijfileexplorer.prototype._isLoading = function () {
                var self = this;
                return self._showLoadingLayerTimer != null || self._isLoadingLayerShowing();
            };

            wijfileexplorer.prototype._isLoadingLayerShowing = function () {
                var self = this;
                return self._loadingLayer && self._loadingLayer.length && self._loadingLayer.is(":visible");
            };

            wijfileexplorer.prototype._hideLoadingLayer = function () {
                var self = this;
                if (self._showLoadingLayerTimer != null) {
                    clearTimeout(self._showLoadingLayerTimer);
                    self._showLoadingLayerTimer = null;
                }

                if (self._isLoadingLayerShowing()) {
                    self._loadingLayer.hide();
                }
            };

            wijfileexplorer.prototype._showLoadingLayer = function () {
                var self = this, wijCSS = this.options.wijCSS;

                if (self._showLoadingLayerTimer != null || (self._loadingLayer && self._loadingLayer.length && self._loadingLayer.is(":visible"))) {
                    return;
                }

                self._showLoadingLayerTimer = setTimeout(function () {
                    if (!self._loadingLayer || !self._loadingLayer.length) {
                        self._loadingLayer = $("<div>").append("<div class=\"" + css.loadingOverlay + " " + wijCSS.overlay + "\"></div>" + "<span class=\"" + css.loadingText + " " + wijCSS.content + " " + wijCSS.cornerAll + "\">" + "<span class=\"" + wijCSS.icon + " " + wijCSS.iconClock + "\"></span>" + self.localizeString("loadingText", "Loading...") + "</span>");
                        self._loadingLayer.hide();
                        self._loadingLayer.appendTo(self.element);
                    }

                    self._loadingLayer.show();
                    self._loadingLayer.find("> ." + css.loadingText).position({
                        my: "center",
                        at: "center center",
                        of: self.element,
                        collision: "none"
                    });

                    self._showLoadingLayerTimer = null;
                }, showLoadingTimout);
            };

            /** @ignore */
            wijfileexplorer.prototype._createAjaxAction = function (data, context, success, error) {
                var _this = this;
                return function () {
                    $.ajax({
                        url: _this.options.actionUri,
                        data: data,
                        context: context,
                        success: success,
                        error: error,
                        dataType: "json",
                        cache: false
                    });
                };
            };

            /** @ignore */
            wijfileexplorer.prototype._enableAjax = function () {
                return this.options.actionUri !== undefined;
            };

            //End Ajax
            wijfileexplorer.prototype._isRootPath = function (path) {
                return $.inArray(path, this._getRootPaths()) > -1;
            };

            wijfileexplorer.prototype._hasRootPath = function (items) {
                var self = this;
                for (var index = 0, length = items.length; index < length; index++) {
                    var item = items[index], path = $.isPlainObject(item) ? item.path : item;
                    if (self._isRootPath(path)) {
                        return true;
                    }
                }

                return false;
            };

            wijfileexplorer.prototype._getParentPath = function (path) {
                return this._isRootPath(path) ? null : getParentPath(path);
            };

            /** @ignore */
            wijfileexplorer.prototype.localizeString = function (key, defaultValue) {
                var localization = this._getLocalization();
                if (localization && localization[key]) {
                    return localization[key];
                }
                return defaultValue;
            };

            /** @ignore */
            wijfileexplorer.prototype._getLocalization = function () {
                return this.options.localization;
            };
            return wijfileexplorer;
        })(wijmo.wijmoWidget);
        fileexplorer.wijfileexplorer = wijfileexplorer;

        /** @ignore */
        (function (OperatingArea) {
            OperatingArea[OperatingArea["TreeView"] = 0] = "TreeView";
            OperatingArea[OperatingArea["ItemsView"] = 1] = "ItemsView";
        })(fileexplorer.OperatingArea || (fileexplorer.OperatingArea = {}));
        var OperatingArea = fileexplorer.OperatingArea;

        

        

        

        

        

        var fileExplorerCommand = (function () {
            function fileExplorerCommand(name, action, text) {
                this.name = name;
                this.action = action;
                this.text = text;
                this._bindElements = [];
            }
            fileExplorerCommand.prototype.disabled = function (value) {
                var self = this;
                if (value === undefined) {
                    return self._disabled;
                }

                if (self._disabled !== value) {
                    self._disabled = value;
                    self._onDisabledChanged();
                }
            };

            fileExplorerCommand.prototype._onDisabledChanged = function () {
                var self = this, disabledCss = $.wijmo.wijCSS.stateDisabled;
                $.each(self._bindElements, function (index, item) {
                    if (self.disabled()) {
                        item.addClass(disabledCss);
                    } else {
                        item.removeClass(disabledCss);
                    }
                });
            };

            fileExplorerCommand.prototype.addBindElement = function (element) {
                this._bindElements.push(element);
            };

            fileExplorerCommand.prototype.removeBindElement = function (element) {
                var elements = this._bindElements, index = $.inArray(element, elements);
                if (index > -1) {
                    elements.splice(index, 1);
                }
            };

            fileExplorerCommand.prototype.execute = function (args) {
                var self = this;
                if (!self._disabled) {
                    self.action(args);
                }
            };
            return fileExplorerCommand;
        })();

        

        var wijfileexplorer_options = (function () {
            function wijfileexplorer_options() {
                /** A value that determines the explorer mode of the wijfileexplorer widget.
                * Possible values are:
                * 'default' and 'fileTree'
                */
                this.mode = explorerMode["default"];
                /** A string array that determines the patterns of files that are shown, usually the file extensions.
                * @remark The default search pattern is "*.*".
                */
                this.searchPatterns = defaultSearchPatterns.slice();
                /** A string value that determines the ViewMode of the wijfileexplorer widget.
                * Possible values are:
                * 'detail' and 'thumbnail'
                */
                this.viewMode = viewMode.detail;
                /** A value that determines whether to allow changing the extension of the file while renaming. */
                this.allowFileExtensionRename = false;
                /** A value that determines whether to allow multiple items selection. */
                this.allowMultipleSelection = false;
                /** A value that determines whether to use paging. */
                this.allowPaging = false;
                /** A value that determines the number of items loaded per page when using paging. */
                this.pageSize = 10;
                /** A object that determines the shortcuts. */
                this.shortcuts = $.extend({}, defaultShortcuts);
                /** A value that determines whether to allow opening a new window with the file. */
                this.enableOpenFile = true;
                /** A value that determines whether to allow creating new folders. */
                this.enableCreateNewFolder = true;
                /** A value that determines whether to allow copying of files/folders. */
                this.enableCopy = true;
                /** A value that determines whether to perform the filtering after the 'Enter' key is pressed. */
                this.enableFilteringOnEnterPressed = false;
                /** A value that determines which components will be shown in wijfileexplorer. */
                this.visibleControls = [
                    visibleControls.addressBox,
                    visibleControls.contextMenu,
                    visibleControls.detailView,
                    visibleControls.filterBox,
                    visibleControls.thumbnailView,
                    visibleControls.toolbar,
                    visibleControls.treeView
                ].join(",");
                /** A value that determines the width of the TreeView. */
                this.treePanelWidth = 200;
                /** A value that determines whether or not to disable the wijfileexplorer widget. */
                this.disabled = false;
                /** The itemSelected event handler.
                * A function called after the item is selected.
                * @event
                * @data {object} data Contains the path of the item.
                */
                this.itemSelected = null;
                /** The fileOpened event handler.
                * A function called after the file is opened.
                * @event
                * @data {object} data Contains the path of the file.
                */
                this.fileOpened = null;
                /** The fileOpening event handler.
                * A function called before the file is opened.
                * @event
                * @data {object} data Contains the path of the file.
                */
                this.fileOpening = null;
                /** The itemCopying event handler.
                * A function called before the item is copied.
                * @event
                * @data {object} data Contains the path of the item.
                */
                this.itemCopying = null;
                /** The itemCopied event handler.
                * A function called after the item is copied.
                * @event
                * @data {object} data Contains the path of the item.
                */
                this.itemCopied = null;
                /** The itemRenaming event handler.
                * A function called before the item is renamed.
                * @event
                * @data {object} data Contains the path of the item and the new name.
                */
                this.itemRenaming = null;
                /** The itemRenamed event handler.
                * A function called after the item is renamed.
                * @event
                * @data {object} data Contains the path of the item and the new name.
                */
                this.itemRenamed = null;
                /** The itemDeleting event handler.
                * A function called before the item is deleted.
                * @event
                * @data {object} data Contains the path of the item.
                */
                this.itemDeleting = null;
                /** The itemDeleted event handler.
                * A function called after the item is deleted.
                * @event
                * @data {object} data Contains the path of the item.
                */
                this.itemDeleted = null;
                /** The errorOccurred event handler.
                * A function called when an error occurs.
                * @event
                * @data {object} data Contains the error message.
                */
                this.errorOccurred = null;
                /** The itemPasting event handler.
                * A function called before the item is pasted.
                * @event
                * @data {object} data Contains the path of the item and the target folder path.
                */
                this.itemPasting = null;
                /** The itemPasted event handler.
                * A function called after the item is pasted.
                * @event
                * @data {object} data Contains the path of the item and the target folder path.
                */
                this.itemPasted = null;
                /** The itemMoving event handler.
                * A function called before the item is moved.
                * @event
                * @data {object} data Contains the path of the item and the target folder path.
                */
                this.itemMoving = null;
                /** The itemMoved event handler.
                * A function called after the item is moved.
                * @event
                * @data {object} data Contains the path of the item and the target folder path.
                */
                this.itemMoved = null;
                /** The newFolderCreating event handler.
                * A function called before a new folder is created.
                * @event
                * @data {object} data Contains the path of the new folder.
                */
                this.newFolderCreating = null;
                /** The newFolderCreated event handler.
                * A function called after a new folder is created.
                * @event
                * @data {object} data Contains the path of the new folder.
                */
                this.newFolderCreated = null;
                /** The folderChanged event handler.
                * A function called after current folder is changed.
                * @event
                * @data {object} data Contains new and old path of the current folder.
                */
                this.folderChanged = null;
                /** The folderLoaded event handler.
                * A function called after the current folder is loaded.
                * @event
                * @data {object} data Contains the path of the current folder.
                */
                this.folderLoaded = null;
                /** The filtering event handler.
                * A function called before filtering.
                * @event
                * @data {object} data Contains filter expression and the path of current folder.
                */
                this.filtering = null;
                /** The filtered event handler.
                * A function called after filtering.
                * @event
                * @data {object} data Contains filter expression and the path of current folder.
                */
                this.filtered = null;
            }
            return wijfileexplorer_options;
        })();
        fileexplorer.wijfileexplorer_options = wijfileexplorer_options;
        ;

        wijfileexplorer.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijfileexplorer_options());
        wijfileexplorer.prototype.widgetEventPrefix = "wijfileexplorer";
        $.wijmo.registerWidget("wijfileexplorer", wijfileexplorer.prototype);
    })(wijmo.fileexplorer || (wijmo.fileexplorer = {}));
    var fileexplorer = wijmo.fileexplorer;
})(wijmo || (wijmo = {}));

;
/// <reference path="../Base/jquery.wijmo.widget.ts" />
/// <reference path="../wijtooltip/jquery.wijmo.wijtooltip.ts" />
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /*globals jQuery*/
    /*
    * Depends:
    *  jquery.js
    *  jquery-ui.js
    */
    (function (treemap) {
        var $ = jQuery, widgetName = "wijtreemap", cls = {
            wijtreemap: "wijmo-wijtreemap",
            container: "wijmo-wijtreemap-container",
            item: "wijmo-wijtreemap-item",
            itemContainer: "wijmo-wijtreemap-itemcontainer",
            title: "wijmo-wijtreemap-title",
            label: "wijmo-wijtreemap-label",
            stateDefault: "wijstate-default",
            stateHover: "wijstate-hover",
            buttons: "wijmo-wijtreemap-buttons",
            backButton: "wijmo-wijtreemap-back",
            homeButton: "wijmo-wijtreemap-home"
        }, defaultColors = [
            {
                max: "#00277d", mid: "#5f7ec1", min: "#a8bbe6"
            }, {
                max: "#7d1f00", mid: "#c1785f", min: "#e6b7a8"
            }, {
                max: "#007d27", mid: "#5fc17e", min: "#a8e6bc"
            }, {
                max: "#7d003c", mid: "#c15f8f", min: "#e6a8c6"
            }, {
                max: "#7d4300", mid: "#c1945f", min: "#e6c9a8"
            }, {
                max: "#51007d", mid: "#9f5fc2", min: "#d1aae6"
            }, {
                max: "#7d7400", mid: "#c2bb5f", min: "#e6e2a8"
            }, {
                max: "#970000", mid: "#c25f5f", min: "#e6a9a9"
            }];

        /** @widget */
        var wijtreemap = (function (_super) {
            __extends(wijtreemap, _super);
            function wijtreemap() {
                _super.apply(this, arguments);
            }
            wijtreemap.prototype._setOption = function (key, value) {
                var self = this, o = self.options;
                if (value === o[key]) {
                    return;
                }
                _super.prototype._setOption.call(this, key, value);

                switch (key) {
                    case "width":
                        self._setWidth(value);
                        self._repaintBox();
                        break;
                    case "height":
                        self._setHeight(value);
                        self._repaintBox();
                        break;
                    case "type":
                        self._repaintBox();
                        break;
                    case "showDepth":
                        break;
                    case "data":
                        self._refresh();
                        break;
                    case "valueBinding":
                        self._resetBinding("value");
                        self._repaint();
                        break;
                    case "labelBinding":
                        self._resetBinding("label");
                        self._resetLabels();
                        break;
                    case "colorBinding":
                        self._resetBinding("color");
                        self._repaintColor();
                        break;
                    case "animation":
                        break;
                    case "showLabel":
                        self._showLabels();
                        break;
                    case "labelFormatter":
                        self._resetLabels();
                        break;
                    case "showTooltip":
                        break;
                    case "tooltipOptions":
                        self._destroyTooltip();
                        self._createTooltip();
                        break;
                    case "showTitle":
                    case "titleHeight":
                        self._repaintBox();
                        break;
                    case "titleFormatter":
                        self._resetTitles();
                        break;
                    case "minColor":
                    case "minColorValue":
                    case "midColor":
                    case "midColorValue":
                    case "maxColor":
                    case "maxColorValue":
                        self._resetColor(key, value);
                        break;
                    case "itemPainting":
                    case "itemPainted":
                    case "painting":
                    case "painted":
                        //if the previous 4 events are reset, need to recreate items to trigger them.
                        self._refresh();
                        break;
                    default:
                        break;
                }
            };

            /**
            * This method refreshes the treemap.
            */
            wijtreemap.prototype.refresh = function () {
                this._refresh();
            };

            wijtreemap.prototype._refresh = function () {
                var self = this;
                self._calcBounds();
                self._recreateItems();
                self._createColor();
                self._destroyTooltip();
                self._createTooltip();
                self._recreateBackButtons();
            };

            wijtreemap.prototype._create = function () {
                var self = this;
                _super.prototype._create.call(this);

                self._decorate(true);
                self._calcBounds();
                self._createItems();
                self._createColor();
                self._bindEvents();
                self._createBackButtons();
                self._createTooltip();
            };

            wijtreemap.prototype._createBackButtons = function () {
                var self = this, wijCSS = self.options.wijCSS, backBtnCls = [cls.backButton, wijCSS.tmbackButton, wijCSS.icon, wijCSS.iconArrowReturn], homeBtnCls = [cls.homeButton, wijCSS.tmhomeButton, wijCSS.icon, wijCSS.iconHome], buttonContainer = $("<span><span").addClass(cls.buttons).addClass(wijCSS.tmbuttons), backBtn = $("<span title='" + self.localizeString("backButtonTitle", "back") + "'></span>").addClass(backBtnCls.join(" ")), homeBtn = $("<span title='" + self.localizeString("homeButtonTitle", "home") + "'></span>").addClass(homeBtnCls.join(" "));

                buttonContainer.append(backBtn).append(homeBtn);
                self.tmItemContainer.ele.append(buttonContainer);
                self.buttons = buttonContainer;
                self._showBackButtons();
                self.buttons.bind("click", function (e) {
                    e.stopPropagation();
                    e.preventDefault();
                    var target = $(e.target);
                    if (target.hasClass(cls.backButton)) {
                        self._play(self.currentContainer, self.currentContainer.parent);
                    } else if (target.hasClass(cls.homeButton)) {
                        self._play(self.currentContainer, self.tmItemContainer);
                    }
                });
            };

            /** @ignore */
            wijtreemap.prototype.localizeString = function (key, defaultValue) {
                var o = this.options;
                if (o.localization && o.localization[key]) {
                    return o.localization[key];
                }
                return defaultValue;
            };

            wijtreemap.prototype._destroyBackButtons = function () {
                var btns = this.buttons;
                if (btns) {
                    btns.unbind("click");
                    btns.remove();
                    this.buttons = null;
                }
            };

            wijtreemap.prototype._recreateBackButtons = function () {
                this._destroyBackButtons();
                this._createBackButtons();
            };

            wijtreemap.prototype._showBackButtons = function () {
                var self = this, o = self.options;
                if (!self.buttons) {
                    return;
                }

                if (!o.showBackButtons || self.currentContainer === self.tmItemContainer) {
                    self.buttons.hide();
                } else {
                    self.buttons.show();
                }
            };

            wijtreemap.prototype._createTooltip = function () {
                if (!$.wijmo.wijtooltip) {
                    return;
                }
                var self = this, o = self.options, tooltipOptions = o.tooltipOptions, content = tooltipOptions && tooltipOptions.content, showing = tooltipOptions && tooltipOptions.showing;

                $("." + cls.item + "." + cls.stateDefault, self.element).wijtooltip($.extend(true, {
                    position: {
                        at: "right-30 top+30"
                    }
                }, tooltipOptions, {
                    content: function () {
                        var tmItem = self._getItemByEle(this);
                        if (tmItem) {
                            if (content) {
                                return content.call(this, tmItem.data);
                            } else {
                                return tmItem.label() + ": " + tmItem.value();
                            }
                        }
                    },
                    showing: function () {
                        if (!o.showTooltip || self._isDisabled()) {
                            return false;
                        }
                        if (showing) {
                            return showing.apply(this, arguments);
                        }
                    }
                }));
            };

            wijtreemap.prototype._destroyTooltip = function () {
                if ($.wijmo.wijtooltip) {
                    var tooltipEle = $("." + cls.item + "." + cls.stateDefault, this.element);
                    if (tooltipEle.data("wijmo-wijtooltip")) {
                        tooltipEle.wijtooltip("destroy");
                    }
                }
            };

            wijtreemap.prototype._bindEvents = function () {
                var self = this;
                self.element.on("click.wijtreemap", $.proxy(self._onClick, self)).on("contextmenu.wijtreemap", $.proxy(self._onRightClick, self)).on("mouseover.wijtreemap", $.proxy(self._onMouseOver, self)).on("mouseout.wijtreemap", $.proxy(self._onMouseOut, self));
            };

            wijtreemap.prototype._onClick = function (e) {
                if (this._isDisabled()) {
                    return;
                }
                var item = this._getItemByEle($(e.target));
                if (item) {
                    //this._play(item, (<TMItem>item).parent);
                    //change behavior accordiong to the customer's request.
                    this._play(item, item);
                }
            };

            wijtreemap.prototype._play = function (item, container) {
                var self = this, tmC = self.tmItemContainer, c = container, isDrillDown;
                if (c === self.currentContainer) {
                    return;
                }

                isDrillDown = self._isDrillDown(self.currentContainer.ele, c.ele);
                if (self._triggerPlaying(item, self.currentContainer, c, isDrillDown) === false) {
                    return;
                }

                if (c !== tmC) {
                    tmC.box.width = 0;
                    tmC.box.height = 0;
                    tmC.applyBox();
                }

                self.currentContainer = c;
                self._resetContainerBox(c);
                c.applyBox();

                self._triggerPlayed(c, isDrillDown);
                self._showBackButtons();
            };

            wijtreemap.prototype._resetContainerBox = function (c) {
                c.box.width = this.width;
                c.box.height = this.height;
                c.box.top = 0;
                c.box.left = 0;
            };

            wijtreemap.prototype._isDrillDown = function (currentEle, targetEle) {
                if ($.contains(currentEle.get(0), targetEle.get(0))) {
                    return true;
                } else {
                    return false;
                }
            };

            wijtreemap.prototype._triggerPlaying = function (item, currentContainer, targetContainer, isDrillDown) {
                var it = item, cc = currentContainer, tc = targetContainer, data;

                data = {
                    currentData: cc.data,
                    targetData: tc.data,
                    clickItemData: it == null ? null : it.data
                };

                if (isDrillDown) {
                    return this._triggerDrillingDown(data);
                } else {
                    return this._triggerRollingUp(data);
                }
                return true;
            };

            wijtreemap.prototype._triggerDrillingDown = function (args) {
                return this._trigger("drillingDown", null, args);
            };

            wijtreemap.prototype._triggerRollingUp = function (args) {
                return this._trigger("rollingUp", null, args);
            };

            wijtreemap.prototype._triggerPlayed = function (currentContainer, isDrillDown) {
                var data = currentContainer.data;
                if (isDrillDown) {
                    this._triggerDrilledDown(data);
                } else {
                    this._triggerRolledUp(data);
                }
            };

            wijtreemap.prototype._triggerDrilledDown = function (args) {
                this._trigger("drilledDown", null, args);
            };

            wijtreemap.prototype._triggerRolledUp = function (args) {
                this._trigger("rolledUp", null, args);
            };

            wijtreemap.prototype._onRightClick = function (e) {
                if (this._isDisabled()) {
                    return false;
                }
                var self = this, item = self._getItemByEle($(e.target));
                ;
                if (self.currentContainer === self.tmItemContainer) {
                    return false;
                }
                self._play(item, self.currentContainer.parent);
                return false;
            };

            wijtreemap.prototype._onMouseOver = function (e) {
                if (this._isDisabled()) {
                    return;
                }
                var item = this._getItemByEle($(e.target));
                if (item) {
                    item.mouseOver();
                }
            };

            wijtreemap.prototype._onMouseOut = function (e) {
                if (this._isDisabled()) {
                    return;
                }
                var item = this._getItemByEle($(e.target));
                if (item) {
                    item.mouseOut();
                }
            };

            wijtreemap.prototype._getItemByEle = function (ele) {
                var self = this, itemEle, index, items = self.tmItemContainer.items, item;
                itemEle = ele.closest("." + cls.item);
                if (itemEle && itemEle.length) {
                    index = itemEle.data("index");
                    if (index == null) {
                        return null;
                    }
                    $.each(index, function (idx, val) {
                        item = items[val];
                        if (item && item.items) {
                            items = item.items;
                        } else {
                            return false;
                        }
                    });
                    return item;
                }
                return null;
            };

            /**
            * The destroy method will remove the treemap functionality completely and will return the element to its pre-init state.
            * @example $("selector").wijtreemap("destroy");
            */
            wijtreemap.prototype.destroy = function () {
                var self = this;
                self._unbindEvents();
                self._destroyItems();
                self._destroyBackButtons();
                self._getContainer().remove();
                self._decorate(false);
                self.colorConverter = null;
                self._destroyTooltip();
                _super.prototype.destroy.call(this);
            };

            wijtreemap.prototype._unbindEvents = function () {
                this.element.off(".wijtreemap");
            };

            wijtreemap.prototype._destroyItems = function () {
                this.tmItemContainer.destroy();
                this._getContainer().empty();
            };

            wijtreemap.prototype._createItems = function () {
                var self = this, o = self.options, container = self._getContainer();
                self._triggerPainting();
                self.tmItemContainer = new TMItemContainer(container, o.data, self);
                self._resetContainerBox(self.tmItemContainer);
                self.tmItemContainer.render();
                self.currentContainer = self.tmItemContainer;
                container.appendTo(self.element);
                self._triggerPainted();
            };

            wijtreemap.prototype._triggerPainting = function () {
                this._trigger("painting", null, this.element);
            };

            wijtreemap.prototype._triggerPainted = function () {
                this._trigger("painted");
            };

            wijtreemap.prototype._recreateItems = function () {
                this._destroyItems();
                this._createItems();
            };

            wijtreemap.prototype._createColor = function () {
                var self = this, o = self.options, minValue = o.minColorValue, maxValue = o.maxColorValue, minMaxValue;
                if (minValue == null || maxValue == null) {
                    minMaxValue = self._getMinMaxItemValue(self.tmItemContainer);
                    if (minValue == null) {
                        minValue = minMaxValue.min;
                    }
                    if (maxValue == null) {
                        maxValue = minMaxValue.max;
                    }
                }
                if (self.colorConverter) {
                    self.colorConverter = null;
                }

                //default color setting of level 1 items is added, so "#000000" and "#ffffff" is only for compling errors and doesn't work here.
                self.colorConverter = new ColorConverter(o.minColor || "#000000", minValue, o.maxColor || "#ffffff", maxValue, o.midColor, o.midColorValue);
                self.tmItemContainer.colorConverter = self.colorConverter;
                self._repaintColor();
            };

            wijtreemap.prototype._resetColor = function (key, value) {
                this.colorConverter["_reset" + key](value);
                this._repaintColor();
            };

            wijtreemap.prototype._getColor = function (val) {
                return this.colorConverter.getColor(val);
            };

            wijtreemap.prototype._getMinMaxItemValue = function (container) {
                var self = this, itemConatiner = container, value = {
                    min: Number.MAX_VALUE,
                    max: Number.MIN_VALUE
                }, val;

                $.each(itemConatiner.items, function (idx, item) {
                    var v = self._getMinMaxItemValue(item);
                    if (v.max > value.max) {
                        value.max = v.max;
                    }
                    if (v.min < value.min) {
                        value.min = v.min;
                    }
                });

                //only compare tail item's value.
                //if (container.value) {
                if (container.value && itemConatiner.items.length === 0) {
                    val = container.value();
                    if (val > value.max) {
                        value.max = val;
                    }
                    if (val < value.min) {
                        value.min = val;
                    }
                }
                return value;
            };

            wijtreemap.prototype._decorate = function (decorate) {
                var self = this, ele = self.element, o = self.options, classNames = [cls.wijtreemap, o.wijCSS.widget, o.wijCSS.wijtreemap].join(" ");
                ele.toggleClass(classNames, decorate);
            };

            wijtreemap.prototype._getContainer = function () {
                var self = this, o = self.options, conCls = [cls.container, o.wijCSS.tmcontainer, cls.itemContainer, o.wijCSS.tmitemContainer].join(" ");
                if (!self.container) {
                    self.container = $("<div></div>").addClass(conCls);
                }
                return self.container;
            };

            wijtreemap.prototype._calcBounds = function () {
                var self = this, ele = self.element, o = self.options, width = o.width ? o.width : ele.width(), height = o.height ? o.height : ele.height();
                self._setWidth(width);
                self._setHeight(height);
            };
            wijtreemap.prototype._setWidth = function (width) {
                this.width = width;
                this._getContainer().css("width", width.toString());
                if (this.tmItemContainer) {
                    this.tmItemContainer.box.width = width;
                }
            };
            wijtreemap.prototype._setHeight = function (height) {
                this.height = height;
                this._getContainer().css("height", height.toString());
                if (this.tmItemContainer) {
                    this.tmItemContainer.box.height = height;
                }
            };

            wijtreemap.prototype._showLabels = function () {
                this.tmItemContainer.toggleLabelVisibility();
            };

            wijtreemap.prototype._resetBinding = function (key) {
                this.tmItemContainer.setBinding(key);
            };

            wijtreemap.prototype._resetLabels = function () {
                this.tmItemContainer.setLabels(false);
            };

            wijtreemap.prototype._resetTitles = function () {
                this.tmItemContainer.setLabels(true);
            };

            wijtreemap.prototype._repaintBox = function () {
                this.currentContainer.applyBox();
            };

            wijtreemap.prototype._repaintColor = function () {
                this.tmItemContainer.applyColor();
            };

            wijtreemap.prototype._repaint = function () {
                this._repaintBox();
                this._repaintColor();
            };
            return wijtreemap;
        })(wijmo.wijmoWidget);
        treemap.wijtreemap = wijtreemap;

        /** @ignore */
        var ColorConverter = (function () {
            function ColorConverter(minColor, minColorValue, maxColor, maxColorValue, midColor, midColorValue) {
                var self = this;
                self.minColor = self._convertColorToRGB(minColor);
                self.minColorValue = minColorValue;
                self.maxColor = self._convertColorToRGB(maxColor);
                self.maxColorValue = maxColorValue;
                self.midColorValue = self.originalMidColorValue = midColorValue;
                self._calculateMidColorValue();
                self.midColor = self.originalMidColor = self._convertColorToRGB(midColor);
                self._calculateMidColor();
            }
            ColorConverter.prototype._resetminColor = function (val) {
                var self = this;
                self.minColor = self._convertColorToRGB(val);
                self._calculateMidColor();
            };
            ColorConverter.prototype._resetmidColor = function (val) {
                var self = this;
                self.midColor = self.originalMidColor = self._convertColorToRGB(val);
                self._calculateMidColor();
            };
            ColorConverter.prototype._resetmaxColor = function (val) {
                var self = this;
                self.maxColor = self._convertColorToRGB(val);
                self._calculateMidColor();
            };
            ColorConverter.prototype._resetminColorValue = function (val) {
                var self = this;
                self.minColorValue = val;
                self._calculateMidColorValue();
            };
            ColorConverter.prototype._resetmidColorValue = function (val) {
                var self = this;
                self.midColorValue = self.originalMidColorValue = val;
                self._calculateMidColorValue();
            };
            ColorConverter.prototype._resetmaxColorValue = function (val) {
                var self = this;
                self.maxColorValue = val;
                self._calculateMidColorValue();
            };

            ColorConverter.prototype._convertColorToRGB = function (color) {
                if (color == null) {
                    return null;
                }
                var rgbStr, rex;
                rgbStr = $("<div></div>").css("background-color", color).css("background-color");
                rex = rgbStr.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
                if (rex.length <= 3) {
                    return;
                }
                return {
                    R: parseInt(rex[1]),
                    G: parseInt(rex[2]),
                    B: parseInt(rex[3])
                };
            };

            ColorConverter.prototype._calculateMidColorValue = function () {
                var self = this;
                if (self.originalMidColorValue == null) {
                    self.midColorValue = (self.maxColorValue + self.minColorValue) / 2;
                }
            };

            ColorConverter.prototype._calculateMidColor = function () {
                var self = this;
                if (self.originalMidColor == null) {
                    self.midColor = self._calculateColorByVal(self.midColorValue, true);
                }
            };

            ColorConverter.prototype._calculateColorByVal = function (val, skipMidCheck) {
                if (typeof skipMidCheck === "undefined") { skipMidCheck = false; }
                var self = this, r, g, b, maxColor = self.maxColor, minColor = self.minColor, maxVal = self.maxColorValue, minVal = self.minColorValue;
                if (val > self.maxColorValue) {
                    return $.extend({}, self.maxColor);
                }
                if (val < self.minColorValue) {
                    return $.extend({}, self.minColor);
                }
                if (!skipMidCheck) {
                    if (val === self.midColorValue) {
                        return $.extend({}, self.midColor);
                    }
                    if (val < self.midColorValue) {
                        maxColor = self.midColor;
                        maxVal = self.midColorValue;
                    } else {
                        minColor = self.midColor;
                        minVal = self.midColorValue;
                    }
                }
                return self._getColor(val, maxColor, maxVal, minColor, minVal);
            };

            ColorConverter.prototype._getColor = function (val, max, maxVal, min, minVal) {
                var self = this;
                return {
                    R: self._getValueByRatio(val, max.R, maxVal, min.R, minVal),
                    G: self._getValueByRatio(val, max.G, maxVal, min.G, minVal),
                    B: self._getValueByRatio(val, max.B, maxVal, min.B, minVal)
                };
            };

            ColorConverter.prototype._getValueByRatio = function (val, max, maxVal, min, minVal) {
                var self = this;
                return Math.abs(min + Math.round((val - minVal) * (max - min) / (maxVal - minVal)));
            };

            ColorConverter.prototype.getColor = function (val) {
                var self = this, color = self._calculateColorByVal(val);
                return "#" + self._hex(color.R) + self._hex(color.G) + self._hex(color.B);
            };

            ColorConverter.prototype._hex = function (val) {
                return ("0" + val.toString(16)).slice(-2);
            };
            return ColorConverter;
        })();

        

        /** @ignore */
        var TMUtils = (function () {
            function TMUtils() {
            }
            //"Squarified Treemap" http://www.win.tue.nl/~vanwijk/stm.pdf,
            //by Mark Bruls, Kees Huizing and Jarke J. van Wijk
            TMUtils.squarified = function (container) {
                var b = container.box, bounds = $.extend(true, {}, b), items = container.items.slice(), ratio, titleBox = container.titleBox, titleLength = titleBox.width || titleBox.height;

                titleLength = (bounds.width === 0 || bounds.height === 0) ? 0 : titleLength;
                bounds.top += titleLength;
                bounds.height -= titleLength;
                ratio = bounds.width * bounds.height / container.total;
                titleBox.width = bounds.width;
                titleBox.height = titleLength;
                do {
                    var rowedItems = TMUtils.getRowedItems(items, bounds, ratio);
                    TMUtils.layoutRowedItems(b, rowedItems, bounds, bounds.width > bounds.height);
                } while(items.length);
            };

            TMUtils.horizontal = function (container) {
                var b = container.box, bounds = $.extend(true, {}, b), items = container.items, titleBox = container.titleBox, titleLength = titleBox.width || titleBox.height;

                titleLength = (bounds.width === 0 || bounds.height === 0) ? 0 : titleLength;
                bounds.left += titleLength;
                bounds.width -= titleLength;
                titleBox.width = titleLength;
                titleBox.height = bounds.height;
                $.each(items, function (idx, item) {
                    var rowedItems = [{
                            item: item,
                            val: item.value() * (b.width - titleLength) * b.height / container.total
                        }];
                    TMUtils.layoutRowedItems(b, rowedItems, bounds, false);
                });
            };

            TMUtils.vertical = function (container) {
                var b = container.box, bounds = $.extend(true, {}, b), items = container.items, titleBox = container.titleBox, titleLength = titleBox.width || titleBox.height;

                titleLength = (bounds.width === 0 || bounds.height === 0) ? 0 : titleLength;
                bounds.top += titleLength;
                bounds.height -= titleLength;
                titleBox.width = bounds.width;
                titleBox.height = titleLength;
                $.each(items, function (idx, item) {
                    var rowedItems = [{
                            item: item,
                            val: item.value() * b.width * (b.height - titleLength) / container.total
                        }];
                    TMUtils.layoutRowedItems(b, rowedItems, bounds, true);
                });
            };

            TMUtils.getNarrowLen = function (bounds) {
                return Math.min(bounds.width, bounds.height);
            };

            TMUtils.getRowedItem = function (item, bounds, ratio) {
                var itemSquare = ratio * item.value();
                return {
                    item: item,
                    val: itemSquare
                };
            };

            TMUtils.getRowedItems = function (items, bounds, ratio) {
                var item = items.shift(), row = [], newRow = [], len = TMUtils.getNarrowLen(bounds), rowedItem = TMUtils.getRowedItem(item, bounds, ratio);
                row.push(rowedItem);
                newRow.push(rowedItem);
                if (items.length > 0) {
                    do {
                        newRow.push(TMUtils.getRowedItem(items[0], bounds, ratio));
                        if (TMUtils.worst(row, len) > TMUtils.worst(newRow, len)) {
                            row = newRow.slice();
                            items.shift();
                        } else {
                            break;
                        }
                    } while(items.length);
                }
                return row;
            };

            TMUtils.layoutRowedItems = function (containerBox, rowedItems, b, isVertical) {
                var left = b.left, top = b.top, maxX = left + b.width, maxY = top + b.height, rowHeight, sum = TMUtils.sumRowedArray(rowedItems);
                if (isVertical) {
                    //if (b.width > b.height) {
                    rowHeight = b.height === 0 ? 0 : sum / b.height;
                    if (left + rowHeight >= maxX) {
                        rowHeight = maxX - left;
                    }
                    $.each(rowedItems, function (idx, item) {
                        var len = rowHeight === 0 ? 0 : item.val / rowHeight;
                        if ((top + len) > maxY || idx === rowedItems.length - 1) {
                            len = maxY - top;
                        }
                        $.extend(item.item.box, {
                            left: left - containerBox.left,
                            top: top - containerBox.top,
                            //left: left,
                            //top: top,
                            width: rowHeight,
                            height: len
                        });
                        top += len;
                    });
                    b.left += rowHeight;
                    b.width -= rowHeight;
                } else {
                    rowHeight = b.width === 0 ? 0 : sum / b.width;
                    if (top + rowHeight >= maxY) {
                        rowHeight = maxY - top;
                    }
                    $.each(rowedItems, function (idx, item) {
                        var len = rowHeight === 0 ? 0 : item.val / rowHeight;
                        if ((left + len) > maxX || idx === rowedItems.length - 1) {
                            len = maxX - left;
                        }
                        $.extend(item.item.box, {
                            left: left - containerBox.left,
                            top: top - containerBox.top,
                            width: len,
                            height: rowHeight
                        });
                        left += len;
                    });
                    b.top += rowHeight;
                    b.height -= rowHeight;
                }
            };

            TMUtils.sumRowedArray = function (array) {
                //http://jsperf.com/summing-array-elements-underscore-reduce-vs-for/2
                //http://jsperf.com/eval-join-vs-reduce
                //for loop is faster.
                var sum = 0, len = array.length;
                for (var i = 0; i < len; i++) {
                    sum += array[i].val;
                }
                return sum;
            };

            TMUtils.worst = function (arr, w) {
                var max, min, tmp, sum = TMUtils.sumRowedArray(arr), sumSquare = sum * sum, wSquare = w * w;
                max = min = arr[0].val;

                //Can't use Math.min/max directly, for loop is the fastest way.
                $.each(arr, function (idx, item) {
                    if (item.val > max) {
                        max = item.val;
                    } else if (item.val < min) {
                        min = item.val;
                    }
                });
                return Math.max((wSquare * max) / sumSquare, sumSquare / (wSquare * min));
            };
            return TMUtils;
        })();

        /** @ignore */
        var TMItemContainer = (function () {
            function TMItemContainer(element, data, tm, parent) {
                if (typeof parent === "undefined") { parent = null; }
                var self = this;
                self.level = (parent && !isNaN(parent.level)) ? parent.level + 1 : 0;
                self.box = self._initBox();
                self.titleBox = self._initBox();
                self.tm = tm;
                self.ele = element;
                self.data = data;
                self.parent = parent;
                self.depth = self.parent === null ? 0 : (self.parent.depth + 1);
                self.total = 0;
                self.items = [];
                self._init();
            }
            TMItemContainer.prototype._initBox = function () {
                return {
                    width: 0,
                    height: 0,
                    left: 0,
                    top: 0
                };
            };

            TMItemContainer.prototype._init = function () {
                var self = this, tmItem;
                if (!self.data || self.data.length === 0) {
                    return;
                }
                $.each(self.data, function (idx, val) {
                    tmItem = self._createTMItem(val, idx);
                    self.items.push(tmItem);
                    self.total += tmItem.value();
                });
            };

            TMItemContainer.prototype._createTMItem = function (data, index) {
                var self = this, tmItemEle = $("<div></div>"), tmOptions = self.tm.options, itemClass = [cls.item, tmOptions.wijCSS.tmitem], tmItem;
                tmItem = new TMItem(tmItemEle, data, self.tm, self, index);
                if (tmItem.items.length > 0) {
                    itemClass.push(cls.itemContainer, tmOptions.wijCSS.tmitemContainer);
                } else {
                    itemClass.push(tmOptions.wijCSS.stateDefault, cls.stateDefault);
                }
                tmItemEle.addClass(itemClass.join(" "));
                return tmItem;
            };

            TMItemContainer.prototype.getColorConverter = function () {
                if (this.colorConverter) {
                    return this.colorConverter;
                }
                if (this.parent) {
                    return this.parent.getColorConverter();
                }
                return null;
            };

            TMItemContainer.prototype.toggleLabelVisibility = function () {
                var self = this;
                if (self.items && self.items.length) {
                    $.each(self.items, function (idx, item) {
                        item.toggleLabelVisibility();
                    });
                }
            };

            TMItemContainer.prototype.setLabels = function (isTitle) {
                var self = this;
                if (self.items && self.items.length) {
                    $.each(self.items, function (idx, item) {
                        item.setLabels(isTitle);
                    });
                }
            };

            TMItemContainer.prototype.setBinding = function (key) {
                var self = this;
                if (self.items && self.items.length) {
                    $.each(self.items, function (idx, item) {
                        item.setBinding(key);
                    });
                }
            };

            TMItemContainer.prototype.applyBox = function () {
                var self = this, renderOptions = {
                    applyBox: true,
                    applyColor: false,
                    applyHtml: false
                };
                self.titleBox = self._initBox();
                self._render(renderOptions);
                self._resetParentTitle();
            };

            TMItemContainer.prototype._resetParentTitle = function () {
                var self = this, tmOptions = self.tm.options, parent = self.parent, ele;
                if (tmOptions.showTitle && parent != null && parent instanceof TMItem) {
                    ele = parent.ele;
                    ele.css({
                        left: 0,
                        top: 0
                    });
                    parent._resetParentTitle();
                }
            };

            TMItemContainer.prototype.applyColor = function () {
                var self = this, renderOptions = {
                    applyBox: false,
                    applyColor: true,
                    applyHtml: false
                };
                self._render(renderOptions);
            };

            TMItemContainer.prototype.render = function () {
                var renderOptions = {
                    applyBox: true,
                    applyColor: false,
                    applyHtml: true
                };
                this._render(renderOptions);
            };

            TMItemContainer.prototype._render = function (options) {
                var self = this;
                if (self.items && self.items.length) {
                    self._renderChildren(options);
                } else {
                    self._renderContent(options);
                }
            };

            TMItemContainer.prototype._renderChildren = function (options) {
                var self = this, tmOptions = self.tm.options, type = tmOptions.type || "squarified";
                if (options.applyBox) {
                    TMUtils[type](self);
                }
                $.each(self.items, function (idx, item) {
                    item._render(options);
                });
            };

            TMItemContainer.prototype._renderContent = function (options) {
            };

            TMItemContainer.prototype._renderColor = function () {
            };

            TMItemContainer.prototype.destroy = function () {
                $.each(this.items, function (idx, item) {
                    item.destroy();
                });
                this.items = null;
            };
            return TMItemContainer;
        })();

        /** @ignore */
        var TMItem = (function (_super) {
            __extends(TMItem, _super);
            function TMItem(element, data, tm, parent, index) {
                var self = this;
                self._label = "label";
                self._value = 0;
                self._color = null;
                self.titleEle = $("<div></div>");
                self.labelEle = $("<span></span>");
                self._isContent = false;
                self._isCustomizeHtml = false;
                if (parent instanceof TMItem) {
                    self.index = parent.index.concat([index]);
                } else {
                    self.index = [index];
                }
                element.data("index", self.index);
                _super.call(this, element, data, tm, parent);
            }
            TMItem.prototype._init = function () {
                var self = this, d = self.data, tmOpts = self.tm.options, defColor = defaultColors[self.index[self.index.length - 1] % defaultColors.length], tmItem;
                self._reset("label")._reset("value")._reset("color");
                if (!d.items || d.items.length === 0) {
                    return;
                }
                $.each(d.items, function (idx, val) {
                    tmItem = self._createTMItem(val, idx);
                    self.items.push(tmItem);
                    //self.total += tmItem.value();
                });

                //If value of an item is not total value of its child items, remove this line.
                self.total = self.value();

                if (d.minColor && d.maxColor) {
                    self._createColorConverter(d.maxColor, d.midColor, d.minColor);
                } else if (self.level === 1 && (tmOpts.maxColor == null || tmOpts.minColor == null)) {
                    //set default color settings to first level items if minColor/maxColor is not set.
                    self._createColorConverter(defColor.max, defColor.mid, defColor.min);
                }
            };

            TMItem.prototype._createColorConverter = function (maxColor, midColor, minColor) {
                var self = this, d = self.data, minValue = d.minColorValue, maxValue = d.maxColorValue, minMaxValue;
                if (minValue == null || maxValue == null) {
                    minMaxValue = self.tm._getMinMaxItemValue(self);
                    if (minValue == null) {
                        minValue = minMaxValue.min;
                    }
                    if (maxValue == null) {
                        maxValue = minMaxValue.max;
                    }
                }
                if (self.colorConverter) {
                    self.colorConverter = null;
                }
                self.colorConverter = new ColorConverter(minColor, minValue, maxColor, maxValue, midColor, d.midColorValue);
            };

            TMItem.prototype._applyBox = function () {
                var self = this, box = self.box;
                self.ele.css({
                    //self.ele.animate({
                    width: box.width,
                    height: box.height,
                    left: box.left,
                    top: box.top
                });
            };

            TMItem.prototype._applyTitleBox = function () {
                var self = this, tmOptions = self.tm.options, box = self.titleBox;
                self.titleEle.css({
                    //self.titleEle.animate({
                    top: 0,
                    left: 0,
                    width: box.width,
                    height: box.height
                });
                if (tmOptions.showTitle) {
                    self.titleEle.show();
                } else {
                    self.titleEle.hide();
                }
            };

            TMItem.prototype._createTitle = function () {
                var self = this, css = self.tm.options.wijCSS;

                self.titleEle.addClass([cls.title, css.header, css.tmtitle].join(" "));
                self.titleEle.prependTo(self.ele);
            };

            TMItem.prototype._setTitle = function () {
                var self = this, tmOptions = self.tm.options, title = self.label(), titleFormatter = tmOptions.titleFormatter;

                if (titleFormatter && $.isFunction(titleFormatter)) {
                    title = $.proxy(titleFormatter, self.data)();
                }
                this.titleEle.html(title);
            };

            TMItem.prototype._createLabel = function () {
                var self = this, tmOptions = self.tm.options;

                self.labelEle.addClass([cls.label, tmOptions.wijCSS.tmlabel].join(" "));
                self.labelEle.prependTo(self.ele);
            };

            TMItem.prototype._setLabel = function () {
                var self = this, tmOptions = self.tm.options, label = self.label(), labelFormatter = tmOptions.labelFormatter;

                if (labelFormatter && $.isFunction(labelFormatter)) {
                    label = $.proxy(labelFormatter, self.data)();
                }
                self.labelEle.html(label);
            };

            TMItem.prototype._render = function (options) {
                var self = this;
                _super.prototype._render.call(this, options);
                if (options.applyBox) {
                    self._applyBox();
                    self._applyTitleBox();
                }
                if (options.applyHtml) {
                    self.ele.appendTo(self.parent.ele);
                }
            };

            TMItem.prototype._renderChildren = function (options) {
                var self = this, tmOptions = self.tm.options;

                //Add title to container.
                self._isContent = false;
                if (options.applyHtml) {
                    self._createTitle();
                    self._setTitle();
                }
                if (options.applyBox) {
                    self.titleBox.height = 0;
                    if (tmOptions.showTitle) {
                        self.titleBox.width = parseInt(tmOptions.titleHeight);
                    } else {
                        self.titleBox.width = 0;
                    }
                }
                _super.prototype._renderChildren.call(this, options);
            };

            TMItem.prototype._renderContent = function (options) {
                var self = this, applyHtml = options.applyHtml, template, tm = self.tm;
                self._isContent = true;
                _super.prototype._renderContent.call(this, options);

                if (applyHtml) {
                    template = self._triggerItemPainting($.extend(true, { htmlTemplate: "" }, self.data));
                    if (typeof template === "string" && template.length > 0) {
                        self._isCustomizeHtml = true;
                        self.ele.empty();
                        self.ele.html(template);
                        self._triggerItemPainted();
                    } else {
                        self._isCustomizeHtml = false;
                    }
                }
                if (!self._isCustomizeHtml) {
                    if (applyHtml) {
                        self._renderHtml();
                        self._triggerItemPainted();
                    }
                    if (options.applyColor) {
                        self._renderColor();
                    }
                }
            };

            TMItem.prototype._triggerItemPainting = function (args) {
                this.tm._trigger("itemPainting", null, args);
                return args.htmlTemplate;
            };

            TMItem.prototype._triggerItemPainted = function () {
                this.tm._trigger("itemPainted");
            };

            TMItem.prototype._renderHtml = function () {
                var self = this;
                self.ele.empty();
                self._createLabel();
                self._setLabel();
                self.toggleLabelVisibility();
            };

            TMItem.prototype._renderColor = function () {
                var self = this, tm = self.tm, color = self.color();
                if (color == null) {
                    //color = tm._getColor(self.value());
                    color = self.parent.getColorConverter().getColor(self.value());
                }
                self.ele.css("background-color", color);
            };

            TMItem.prototype.toggleLabelVisibility = function () {
                var self = this, tmOptions = self.tm.options;
                if (self._isContent) {
                    if (tmOptions.showLabel) {
                        self.labelEle.show();
                    } else {
                        self.labelEle.hide();
                    }
                } else {
                    _super.prototype.toggleLabelVisibility.call(this);
                }
            };

            TMItem.prototype.setLabels = function (isTitle) {
                var self = this;
                if (self._isContent) {
                    if (!isTitle) {
                        self._setLabel();
                    }
                } else {
                    if (isTitle) {
                        self._setTitle();
                    }
                    _super.prototype.setLabels.call(this, isTitle);
                }
            };

            TMItem.prototype.setBinding = function (key) {
                this._reset(key);
                if (!this._isContent) {
                    _super.prototype.setBinding.call(this, key);
                }
            };

            TMItem.prototype.destroy = function () {
                _super.prototype.destroy.call(this);
                if (this.colorConverter) {
                    this.colorConverter = null;
                }
            };

            TMItem.prototype._reset = function (key) {
                var self = this, tmOptions = self.tm.options, keyVal = tmOptions[key + "Binding"] || key;
                if (keyVal in self.data) {
                    self["_" + key] = self.data[keyVal];
                }
                return self;
            };

            TMItem.prototype.label = function (value) {
                var self = this;
                if (value === undefined) {
                    return self._label;
                } else {
                    self._label = value;
                    return self;
                }
            };
            TMItem.prototype.value = function (value) {
                var self = this;
                if (value === undefined) {
                    return self._value;
                } else {
                    self._value = value;
                    return self;
                }
            };
            TMItem.prototype.color = function (value) {
                var self = this;
                if (value === undefined) {
                    return self._color;
                } else {
                    self._color = value;
                    return self;
                }
            };

            TMItem.prototype.click = function (e) {
            };

            TMItem.prototype.mouseOver = function () {
                if (this._isContent) {
                    var tmOptions = this.tm.options;
                    this.ele.addClass(tmOptions.wijCSS.stateHover).addClass(cls.stateHover);
                }
            };
            TMItem.prototype.mouseOut = function () {
                if (this._isContent) {
                    var tmOptions = this.tm.options;
                    this.ele.removeClass(tmOptions.wijCSS.stateHover).removeClass(cls.stateHover);
                }
            };
            return TMItem;
        })(TMItemContainer);

        

        

        

        

        

        

        
        var wijtreemap_options = (function () {
            function wijtreemap_options() {
                /** Selector option for auto self initialization. This option is internal.
                * @ignore
                */
                this.initSelector = ":jqmData(role='wijtreemap')";
                /** wijtreemap css, extend from $.wijmo.wijCSS
                * @ignore
                */
                this.wijCSS = {
                    wijtreemap: "",
                    tmcontainer: "",
                    tmitem: "",
                    tmitemContainer: "",
                    tmtitle: "",
                    tmlabel: "",
                    tmbuttons: "",
                    tmbackButton: "",
                    tmhomeButton: ""
                };
                /** wijtreemap css, extend from $.wijmo.wijCSS
                * @ignore
                */
                this.wijMobileCSS = {};
                /**
                * A value that indicates the width of the treemap in pixels.
                * @remarks
                * Note that this value overrides any value you may set in the <div> element that
                * you use in the body of the HTML page.
                * @type {number}
                */
                this.width = null;
                /**
                * A value that indicates the height of the treemap in pixels.
                * @remarks
                * Note that this value overrides any value you may set in the <div> element that
                * you use in the body of the HTML page.
                * @type {number}
                */
                this.height = null;
                /** A value that indicates the type of treemap to be displayed.
                * @remarks Options are 'squarified', 'horizontal' and 'vertical'.
                */
                this.type = "squarified";
                /***/
                /*
                showDepth: number = 0;*/
                /**
                * A value that indicates the array to use as a source that you can bind to treemap.
                * @remarks
                * Use the valueBinding, labelBinding, colorBinding option, and bind values to treemap.
                */
                this.data = null;
                /** A value that indicates the field to each item's value. Default value field is 'value' if valueBinding is not set. */
                this.valueBinding = null;
                /** A value that indicates the field to each item's label  Default label field is 'label' if labelBinding is not set.*/
                this.labelBinding = null;
                /** A value that indicates the field to each item's color  Default color field is 'color' if colorBinding is not set.*/
                this.colorBinding = null;
                /***/
                /*
                animation: any = null;*/
                /** A value that indicates whether to show the label. */
                this.showLabel = true;
                /**
                * A value that indicates a function which is used to format the label of treemap item.
                * @type {Function}
                */
                this.labelFormatter = null;
                /** A value that indicates whether to show the tooltip. */
                this.showTooltip = false;
                /** A value that indicates options of tooltip.
                * @remarks Its value is wijtooltip's option, visit
                * http://wijmo.com/docs/wijmo/#Wijmo~jQuery.fn.-~wijtooltip.html for more details.*/
                this.tooltipOptions = null;
                /** A value that indicates whether to show the title. */
                this.showTitle = true;
                /** A value that indicates the height of the title. */
                this.titleHeight = 20;
                /**
                * A value that indicates a function which is used to format the title of treemap item.
                * @type {Function}
                */
                this.titleFormatter = null;
                /**
                * A value that indicates the color of min value.
                */
                this.minColor = null;
                /**
                * A value that indicates min value.
                * If this option is not set, treemap will calculate min value automatically.
                */
                this.minColorValue = null;
                /**
                * A value that indicates the color of mid value.
                */
                this.midColor = null;
                /**
                * A value that indicates mid value.
                * If this option is not set, treemap will calculate mid value automatically.
                */
                this.midColorValue = null;
                /**
                * A value that indicates the color of max value.
                */
                this.maxColor = null;
                /**
                * A value that indicates max value.
                * If this option is not set, treemap will calculate max value automatically.
                */
                this.maxColorValue = null;
                /**
                * A value that indicates whether to show back button after treemap drilled down.
                */
                this.showBackButtons = false;
                //Events
                /**
                * This event fires before item is painting. User can create customize item in this event.
                * @event
                * @param {Object} e The jQuery.Event object.
                * @param {Object} data Data of item to be painted, set value to data.htmlTemplate to customize treemap item.
                */
                this.itemPainting = null;
                /**
                * This event fires after item is painted.
                * @event
                */
                this.itemPainted = null;
                /**
                * This event fires before treemap is painting.
                * @event
                * @param {Object} e The jQuery.Event object.
                * @param {JQuery} args The element of wijtreemap.
                */
                this.painting = null;
                /**
                * This event fires after treemap is painted.
                * @event
                */
                this.painted = null;
                /**
                * This event fires before drill down. This event can be cancelled, use "return false;" to cancel the event.
                * @event
                * @dataKey clickItemData The data of clicked item.
                * @dataKey currentData The data of current item.
                * @dataKey targetData The data of target item to be drilled down.
                */
                this.drillingDown = null;
                /**
                * This event fires after drill down.
                * @event
                * @param {Object} e The jQuery.Event object.
                * @param {Object} data The data of item that is drilled down.
                */
                this.drilledDown = null;
                /**
                * This event fires before roll up. This event can be cancelled, use "return false;" to cancel the event.
                * @event
                * @dataKey clickItemData The data of clicked item.
                * @dataKey currentData The data of current item.
                * @dataKey targetData The data of target item to be rolled up.
                */
                this.rollingUp = null;
                /**
                * This event fires after roll up.
                * @event
                * @param {Object} e The jQuery.Event object.
                * @param {Object} data The data of item that is rolled up.
                */
                this.rolledUp = null;
            }
            return wijtreemap_options;
        })();
        ;

        wijtreemap.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijtreemap_options());
        $.wijmo.registerWidget(widgetName, wijtreemap.prototype);
    })(wijmo.treemap || (wijmo.treemap = {}));
    var treemap = wijmo.treemap;
})(wijmo || (wijmo = {}));

;
/// <reference path="drawing.ts" />
/// <reference path="../../External/declarations/geojson.d.ts"/>
var wijmo;
(function (wijmo) {
    (function (maps) {
        /** @ignore */
        var Utils = (function () {
            function Utils() {
            }
            Utils.getBounds = function (pts) {
                if (!pts || pts.length === 0)
                    return null;

                var minx = Number.MAX_VALUE, miny = minx, maxx = -Number.MAX_VALUE, maxy = maxx;

                $.each(pts, function (index, pt) {
                    if (pt.x < minx)
                        minx = pt.x;
                    if (pt.x > maxx)
                        maxx = pt.x;
                    if (pt.y < miny)
                        miny = pt.y;
                    if (pt.y > maxy)
                        maxy = pt.y;
                });

                return new maps.Rectangle(new maps.Point(minx, miny), new maps.Size(maxx - minx, maxy - miny));
            };

            Utils.getListBounds = function (ptsList) {
                var listBounds, bounds;

                $.each(ptsList, function (index, pts) {
                    bounds = Utils.getBounds(pts);
                    if (bounds) {
                        listBounds = bounds.union(listBounds);
                    }
                });

                return listBounds;
            };

            Utils.getPoints = function (coordinates) {
                if (!coordinates)
                    return null;

                var points = [], len = coordinates.length;

                len = len - len % 2;
                for (var i = 0; i < len; i++) {
                    var pt = new maps.Point(coordinates[i], coordinates[++i]);
                    points.push(pt);
                }

                return points;
            };

            Utils.sinh = function (value) {
                return (Math.exp(value) - Math.exp(-value)) / 2;
            };

            Utils.createListPath = function (pointsList, closed) {
                var paths = "", path;
                $.each(pointsList, function (index, points) {
                    path = Utils.createPath(points);
                    if (path) {
                        paths += path;
                    }
                });

                return paths;
            };

            Utils.createPath = function (points, closed) {
                if (!points)
                    return null;

                var len = points.length, point, path = null, start;

                if (len > 0) {
                    start = points[0];
                    path = "M" + start.x + " " + start.y;

                    for (var i = 1; i < len; i++) {
                        point = points[i];
                        path += "L" + point.x + " " + point.y;
                    }

                    if (closed) {
                        path += "Z";
                    }
                }

                return path;
            };

            Utils.getPointData = function (coords) {
                var point = null;
                if (coords && coords.length > 0) {
                    point = new maps.Point(coords[0], coords[1]);
                }

                return point;
            };

            Utils.getLineData = function (coords) {
                var points = null;
                if (coords && coords.length > 0) {
                    points = [];
                    $.each(coords, function (index, position) {
                        points.push(Utils.getPointData(position));
                    });
                }

                return points;
            };

            Utils.getPolygonData = function (coords) {
                var pointsList = null;
                if (coords && coords.length > 0) {
                    pointsList = [];
                    $.each(coords, function (index, positions) {
                        pointsList.push(Utils.getLineData(positions));
                    });
                }

                return pointsList;
            };
            return Utils;
        })();
        maps.Utils = Utils;
    })(wijmo.maps || (wijmo.maps = {}));
    var maps = wijmo.maps;
})(wijmo || (wijmo = {}));

var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /// <reference path="utils.ts" />
    /// <reference path="../../wijutil/jquery.wijmo.raphael.ts"/>
    (function (maps) {
        

        /**
        * @ignore
        * Defines a point with horizontal and vertical coordinates.
        */
        var Point = (function () {
            function Point(pointOrX, y) {
                var self = this;
                if (typeof (pointOrX) === "number") {
                    self.x = pointOrX;
                    self.y = y;
                } else {
                    var point = pointOrX;
                    self.x = point.x;
                    self.y = point.y;
                }
            }
            /**
            * Gets a new Point which has a offset to the current Point.
            * @param {number} offsetX The offset in horizontal.
            * @param {number} offsetY The offset in vertical.
            * @returns {Point} The new Point after offset.
            */
            Point.prototype.offset = function (offsetX, offsetY) {
                return new Point(this.x + offsetX, this.y + offsetY);
            };

            /**
            * Gets a new Point which has a scale to the current Point.
            * @param {number} scaleX The scale in horizontal.
            * @param {number} scaleY The scale in vertical.
            * @returns {Point} The new point after scale.
            */
            Point.prototype.scale = function (scaleX, scaleY) {
                return new Point(this.x * scaleX, this.y * scaleY);
            };
            Point.empty = new Point(0, 0);
            return Point;
        })();
        maps.Point = Point;

        

        /**
        * @ignore
        * Defines an ordered pair  of number, which specify a width and height.
        */
        var Size = (function () {
            function Size(sizeOrWidth, height) {
                var self = this;
                if (typeof (sizeOrWidth) === "number") {
                    self.width = sizeOrWidth;
                    self.height = height;
                } else {
                    var size = sizeOrWidth;
                    self.width = size.width;
                    self.height = size.height;
                }
            }
            /**
            * Gets a new Size object which has a scale to the current Size.
            * @param {number} scaleX The scale of the width.
            * @param {number} scaleY The scale of the height.
            * @returns {Size} The new Size object after scale.
            */
            Size.prototype.scale = function (scaleX, scaleY) {
                return new Size(this.width * scaleX, this.height * scaleY);
            };
            Size.empty = new Size(0, 0);
            return Size;
        })();
        maps.Size = Size;

        

        /**
        * @ignore
        * Defines a rectangle with location and size.
        */
        var Rectangle = (function () {
            /**
            * @param {Point} location The upper-left point of the rectangle.
            * @param {Size} size The size of the rectangle.
            */
            function Rectangle(location, size) {
                this.location = location;
                this.size = size;
            }
            /**
            * Gets the rectangle which is the intersection of itself and the specified rectangle.
            * @param {Rectangle} rect The rectangle with which to intersect.
            * @returns {Rectangle} The intersection rectangle of itself and the specified rectangle.
            */
            Rectangle.prototype.intersect = function (rect) {
                var self = this, x = Math.max(self.location.x, rect.location.x), right = Math.min(self.location.x + self.size.width, rect.location.x + rect.size.width), y = Math.max(self.location.y, rect.location.y), bottom = Math.min(self.location.y + self.size.height, rect.location.y + rect.size.height);

                if (right >= x && bottom >= y) {
                    return new Rectangle(new Point(x, y), new Size(right - x, bottom - y));
                }

                return null;
            };

            /**
            * Tests whether the location and size are both empty.
            * @returns {boolean} true if the location and size are both empty; otherwise, false.
            */
            Rectangle.prototype.isEmpty = function () {
                var self = this;
                return self.size.width === 0 && self.size.height === 0 && self.location.x === 0 && self.location.y === 0;
            };

            /**
            * Gets the right of the rectangle.
            * @returns The right of the rectangle which is left + width.
            */
            Rectangle.prototype.getRight = function () {
                return this.location.x + this.size.width;
            };

            /**
            * Gets the bottom of the rectangle.
            * @returns The bottom of the rectangle which is top + height.
            */
            Rectangle.prototype.getBottom = function () {
                return this.location.y + this.size.height;
            };

            /**
            * Determines if this rectangle intersects with the specified rectangle.
            * @param {Rectangle} rect The rectangle with which to check.
            * @returns {boolean} true if this rectangle intersects with the specified rectangle; otherwise, false.
            */
            Rectangle.prototype.intersectsWith = function (rect) {
                if (!rect)
                    return false;
                var self = this;
                return ((((self.location.x <= (rect.location.x + rect.size.width)) && ((self.location.x + self.size.width) >= rect.location.x)) && (self.location.y <= (rect.location.y + rect.size.height))) && ((self.location.y + self.size.height) >= rect.location.y));
            };

            /**
            * Gets a new rectangle which is the union of itself and the specified rectangle.
            * @param {Rectangle} rect The rectangle with which to union.
            * @returns {Rectangle} The new rectangle which is the union of this rectangle and the specified rectangle.
            */
            Rectangle.prototype.union = function (rect) {
                var self = this;
                if (!rect)
                    return $.extend(true, {}, self);

                var left = Math.min(self.location.x, rect.location.x), top = Math.min(self.location.y, rect.location.y), right = Math.max(self.location.x + self.size.width, rect.location.x + rect.size.width), bottom = Math.max(self.location.y + self.size.height, rect.location.y + rect.size.height);

                return new Rectangle(new Point(left, top), new Size(right - left, bottom - top));
            };
            Rectangle.empty = new Rectangle(Point.empty, Size.empty);
            return Rectangle;
        })();
        maps.Rectangle = Rectangle;

        /**
        * @ignore
        * Represents the vector shape.
        */
        var Shape = (function () {
            function Shape() {
                this.fill = "transparent";
                this.fillOpacity = 1;
                this.stroke = "#000";
                this.strokeOpacity = 1;
                this.strokeWidth = 1.0;
                this.strokeDashArray = "";
                this.strokeLineCap = 0 /* butt */;
                this.strokeLineJoin = 0 /* bevel */;
                this.strokeMiterLimit = 1.0;
            }
            Shape.prototype.createElement = function (paper) {
                return null;
            };

            Shape.prototype._setElementAttributes = function (st) {
                var self = this;
                if (st) {
                    st.attr({
                        fill: self.fill,
                        "fill-opacity": self.fillOpacity,
                        stroke: self.stroke,
                        "stroke-opacity": self.strokeOpacity,
                        "stroke-width": self.strokeWidth,
                        "stroke-dasharray": self.strokeDashArray,
                        "stroke-linecap": PenLineCap[self.strokeLineCap] || PenLineCap[0 /* butt */],
                        "stroke-linejoin": PenLineJoin[self.strokeLineJoin] || PenLineJoin[0 /* bevel */],
                        "stroke-miterlimit": self.strokeMiterLimit
                    });

                    if (self.fill === "transparent") {
                        st.attr("fill", "white").attr("fill-opacity", "0");
                    }
                }
            };
            return Shape;
        })();
        maps.Shape = Shape;

        /** @ignore */
        var Polyline = (function (_super) {
            __extends(Polyline, _super);
            function Polyline() {
                _super.apply(this, arguments);
            }
            Polyline.prototype.createElement = function (paper) {
                paper.setStart();
                var self = this, path = maps.Utils.createPath(self.points, false), st;

                if (path) {
                    paper.path(path);
                }

                st = paper.setFinish();
                self._setElementAttributes(st);
                return st;
            };
            return Polyline;
        })(Shape);
        maps.Polyline = Polyline;

        /** @ignore */
        var MultiPolyline = (function (_super) {
            __extends(MultiPolyline, _super);
            function MultiPolyline() {
                _super.apply(this, arguments);
            }
            MultiPolyline.prototype.createElement = function (paper) {
                paper.setStart();
                var self = this, path, st;

                if (self.points) {
                    $.each(self.points, function (index, linePoints) {
                        path = maps.Utils.createPath(linePoints, false);
                        if (path) {
                            paper.path(path);
                        }
                    });
                }

                st = paper.setFinish();
                self._setElementAttributes(st);
                return st;
            };
            return MultiPolyline;
        })(Shape);
        maps.MultiPolyline = MultiPolyline;

        /** @ignore */
        var Polygon = (function (_super) {
            __extends(Polygon, _super);
            function Polygon() {
                _super.apply(this, arguments);
                this.fillRule = 0 /* evenOdd */;
                this.pointsList = [];
            }
            Polygon.prototype.createElement = function (paper) {
                paper.setStart();
                var self = this, path = maps.Utils.createListPath(self.pointsList, true), st;

                if (path) {
                    paper.path(path);
                }

                st = paper.setFinish();
                self._setElementAttributes(st);
                return st;
            };
            return Polygon;
        })(Shape);
        maps.Polygon = Polygon;

        /** @ignore */
        (function (FillRule) {
            FillRule[FillRule["evenOdd"] = 0] = "evenOdd";
            FillRule[FillRule["nonezero"] = 1] = "nonezero";
        })(maps.FillRule || (maps.FillRule = {}));
        var FillRule = maps.FillRule;

        /** @ignore */
        (function (PenLineCap) {
            PenLineCap[PenLineCap["butt"] = 0] = "butt";
            PenLineCap[PenLineCap["square"] = 1] = "square";
            PenLineCap[PenLineCap["round"] = 2] = "round";
        })(maps.PenLineCap || (maps.PenLineCap = {}));
        var PenLineCap = maps.PenLineCap;

        /** @ignore */
        (function (PenLineJoin) {
            PenLineJoin[PenLineJoin["bevel"] = 0] = "bevel";
            PenLineJoin[PenLineJoin["round"] = 1] = "round";
            PenLineJoin[PenLineJoin["miter"] = 2] = "miter";
        })(maps.PenLineJoin || (maps.PenLineJoin = {}));
        var PenLineJoin = maps.PenLineJoin;
    })(wijmo.maps || (wijmo.maps = {}));
    var maps = wijmo.maps;
})(wijmo || (wijmo = {}));

var wijmo;
(function (wijmo) {
    /// <reference path="drawing.ts" />
    (function (maps) {
        /** @ignore */
        var ClippingEngine = (function () {
            function ClippingEngine() {
            }
            ClippingEngine.createClippedLines = function (pts, clipBounds) {
                var pointsList = [], len = pts.length;

                for (var i = 1; i < len; i++) {
                    var clippedLine = ClippingEngine._clipSegmentCS(clipBounds, [pts[i - 1], pts[i]]);
                    if (clippedLine) {
                        pointsList.push(clippedLine);
                    }
                }

                return pointsList;
            };

            ClippingEngine._clipSegmentCS = function (clipBounds, pts) {
                var visible = false, pt0 = pts[0], pt1 = pts[1], cn = ClippingEngine._csCode(clipBounds, pt0), ck = ClippingEngine._csCode(clipBounds, pt1), dx = pt1.x - pt0.x, dy = pt1.y - pt0.y, dxdy = 0, dydx = 0;

                if (dx !== 0)
                    dydx = dy / dx;
                else {
                    if (dy === 0) {
                        if (cn === 0 && ck === 0)
                            return [pt0, pt1];
                        else
                            return null;
                    }
                }

                if (dy !== 0)
                    dxdy = dx / dy;

                var ii = 4, s, r;

                do {
                    if ((cn & ck) > 0) {
                        break;
                    }

                    if (cn === 0 && ck === 0) {
                        visible = true;
                        break;
                    }

                    if (cn === 0) {
                        s = cn;
                        cn = ck;
                        ck = s;

                        r = pt0.x;
                        pt0.x = pt1.x;
                        pt1.x = r;

                        r = pt0.y;
                        pt0.y = pt1.y;
                        pt1.y = r;
                    }

                    if ((cn & 1) > 0) {
                        var left = clipBounds.location.x;
                        pt0.y += dydx * (left - pt0.x);
                        pt0.x = left;
                    } else if ((cn & 2) > 0) {
                        var right = clipBounds.location.x + clipBounds.size.width;
                        pt0.y += dydx * (right - pt0.x);
                        pt0.x = right;
                    } else if ((cn & 4) > 0) {
                        var bottom = clipBounds.location.y + clipBounds.size.height;
                        pt0.x += dxdy * (bottom - pt0.y);
                        pt0.y = bottom;
                    } else if ((cn & 8) > 0) {
                        var top = clipBounds.location.y;
                        pt0.x += dxdy * (top - pt0.y);
                        pt0.y = top;
                    }

                    cn = ClippingEngine._csCode(clipBounds, pt0);
                } while(--ii >= 0);

                if (visible)
                    return [pt0, pt1];

                return null;
            };

            ClippingEngine.clipPolygon = function (pts, clipBounds) {
                var len = pts.length;
                if (len < 2)
                    return null;

                var list = [];
                for (var i = 0; i < len; i++) {
                    list.push(pts[i]);
                }

                var left = clipBounds.location.x, top = clipBounds.location.y, right = left + clipBounds.size.width, bottom = top + clipBounds.size.height;
                list = ClippingEngine._clipPolygonByLine(list, new maps.Point(left, top), new maps.Point(right, top));
                list = ClippingEngine._clipPolygonByLine(list, new maps.Point(right, top), new maps.Point(right, bottom));
                list = ClippingEngine._clipPolygonByLine(list, new maps.Point(right, bottom), new maps.Point(left, bottom));
                list = ClippingEngine._clipPolygonByLine(list, new maps.Point(left, bottom), new maps.Point(left, top));

                return list;
            };

            ClippingEngine.clipPolygonList = function (ptsList, clipBounds) {
                var list = [];
                $.each(ptsList, function (index, pts) {
                    list.push(ClippingEngine.clipPolygon(pts, clipBounds));
                });
                return list;
            };

            ClippingEngine._clipPolygonByLine = function (pts, cp1, cp2) {
                var list = [], len = pts.length;

                if (len > 0) {
                    var p0 = pts[len - 1];
                    for (var i = 0; i < len; i++) {
                        var p = pts[i];
                        if (this._inside(p, cp1, cp2)) {
                            if (this._inside(p0, cp1, cp2))
                                list.push(p);
                            else {
                                list.push(this._intersect(p0, p, cp1, cp2));
                                list.push(p);
                            }
                        } else {
                            if (this._inside(p0, cp1, cp2)) {
                                list.push(this._intersect(p0, p, cp1, cp2));
                            }
                        }

                        p0 = p;
                    }
                }

                return list;
            };

            ClippingEngine._inside = function (p, cp0, cp1) {
                if (cp1.x > cp0.x)
                    if (p.y >= cp0.y)
                        return true;
                if (cp1.x < cp0.x)
                    if (p.y <= cp0.y)
                        return true;
                if (cp1.y > cp0.y)
                    if (p.x <= cp1.x)
                        return true;
                if (cp1.y < cp0.y)
                    if (p.x >= cp1.x)
                        return true;
                return false;
            };

            ClippingEngine._intersect = function (p0, p1, cp0, cp1) {
                var p = new maps.Point(0, 0);
                if (cp0.y === cp1.y) {
                    p.y = cp0.y;
                    p.x = p0.x + (cp0.y - p0.y) * (p1.x - p0.x) / (p1.y - p0.y);
                } else {
                    p.x = cp0.x;
                    p.y = p0.y + (cp0.x - p0.x) * (p1.y - p0.y) / (p1.x - p0.x);
                }

                return p;
            };

            ClippingEngine._csCode = function (rect, pt) {
                var i = 0, left = rect.location.x, top = rect.location.y, right = left + rect.size.width, bottom = top + rect.size.height;

                if (pt.x < left)
                    ++i;
                else if (pt.x > right)
                    i += 2;

                if (pt.y > bottom)
                    i += 4;
                else if (pt.y < top)
                    i += 8;

                return i;
            };
            return ClippingEngine;
        })();
        maps.ClippingEngine = ClippingEngine;
    })(wijmo.maps || (wijmo.maps = {}));
    var maps = wijmo.maps;
})(wijmo || (wijmo = {}));

var wijmo;
(function (wijmo) {
    /// <reference path="Drawing.ts" />
    (function (maps) {
        

        /** @ignore */
        var MercatorProjection = (function () {
            function MercatorProjection() {
            }
            MercatorProjection.prototype.project = function (lonLat) {
                return new maps.Point((lonLat.x + 180) / 360, (1 - Math.log(Math.tan(lonLat.y * Math.PI / 180) + 1 / Math.cos(lonLat.y * Math.PI / 180)) / Math.PI) / 2);
            };

            MercatorProjection.prototype.unproject = function (p) {
                var n = Math.PI - 2 * Math.PI * p.y;
                return new maps.Point((p.x * 360 - 180), 180 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))));
            };
            return MercatorProjection;
        })();
        maps.MercatorProjection = MercatorProjection;
    })(wijmo.maps || (wijmo.maps = {}));
    var maps = wijmo.maps;
})(wijmo || (wijmo = {}));

var wijmo;
(function (wijmo) {
    /// <reference path="MapProjection.ts" />
    /// <reference path="../../Base/jquery.wijmo.widget.ts" />
    (function (maps) {
        

        /**
        * @ignore
        * The converter to convert the coordinates in geograhic unit (longitude and latitude), logic unit(percentage) and screen unit (pixel).
        */
        var CoordConverter = (function () {
            /**
            * @param {JQuery} element The jQuery object that represents the wijmaps element.
            * @param {Point} center The current center of the map, in geographic unit.
            * @param {number} zoom The current zoom of the map.
            * @param {number} tileWidth The width of the tile, in pixel.
            * @param {number} tileHeight The height of the tile, in pixel.
            */
            function CoordConverter(element, center, zoom, tileWidth, tileHeight) {
                this.element = element;
                this.center = center;
                this.zoom = zoom;
                this.tileWidth = tileWidth;
                this.tileHeight = tileHeight;
                var self = this, leftTopGeographicCoord, rightBottomGeographicCoord;
                self._updateSize();
                self._projection = new maps.MercatorProjection();
                leftTopGeographicCoord = self.logicToGeographic(new maps.Point(0, 0));
                rightBottomGeographicCoord = self.logicToGeographic(new maps.Point(1, 1));
                self.minLongitude = leftTopGeographicCoord.x;
                self.maxLongitude = rightBottomGeographicCoord.x;
                self.minLatitude = rightBottomGeographicCoord.y;
                self.maxLatitude = leftTopGeographicCoord.y;
            }
            /**
            * @ignore
            * Update the cached size when the size of the map changed.
            */
            CoordConverter.prototype._updateSize = function () {
                var self = this, e = self.element;
                self._size = new maps.Size(e.width(), e.height());
            };

            /**
            * Convert the point coordinates from screen unit (pixel) to geographic unit (longitude and latitude).
            * @param {IPoint} position The point to convert, in screen unit.
            * @returns {IPoint} The new point after converted, in geographic unit.
            */
            CoordConverter.prototype.viewToGeographic = function (position) {
                var self = this;
                return self.logicToGeographic(self.viewToLogic(position));
            };

            /**
            * Convert the point coordinates from geographic unit (longitude and latitude) to screen unit (pixel).
            * @param {IPoint} position The point to convert, in geographic unit.
            * @returns {IPoint} The new point after converted, in screen unit.
            */
            CoordConverter.prototype.geographicToView = function (position) {
                var self = this;
                return self.logicToView(self.geographicToLogic(position));
            };

            /**
            * Convert the point coordinates from screen unit (pixel) to logic unit (percentage).
            * @param {IPoint} position The point to convert, in screen unit.
            * @returns {IPoint} The new point after converted, in logic unit.
            */
            CoordConverter.prototype.viewToLogic = function (position) {
                var self = this, viewCenter = self.getViewCenter(), logicCenter = self.getLogicCenter(), fullMapSize = self.getFullMapSize(), offset = new maps.Size(position.x - viewCenter.x, position.y - viewCenter.y).scale(1 / fullMapSize.width, 1 / fullMapSize.height);
                return self._rangeLogicPoint(new maps.Point(logicCenter).offset(offset.width, offset.height));
            };

            /**
            * Convert the point coordinates from logic unit (percentage) to screen unit (pixel).
            * @param {IPoint} position The point to convert, in loogic unit.
            * @returns {IPoint} The new point after converted, in screen unit.
            */
            CoordConverter.prototype.logicToView = function (position) {
                var self = this, logicPosition = self._rangeLogicPoint(position), viewCenter = self.getViewCenter(), logicCenter = self.getLogicCenter(), fullMapSize = self.getFullMapSize(), offset = new maps.Size(logicPosition.x - logicCenter.x, logicPosition.y - logicCenter.y).scale(fullMapSize.width, fullMapSize.height);
                return new maps.Point(viewCenter).offset(offset.width, offset.height);
            };

            /**
            * Convert the point coordinates from geographic unit (longitude and latitude) to logic unit (percentage).
            * @param {IPoint} position The point to convert, in geographic unit.
            * @returns {IPoint} The new point after converted, in logic unit.
            */
            CoordConverter.prototype.geographicToLogic = function (lonLat) {
                var self = this;
                return self._rangeLogicPoint(self._projection.project(lonLat));
            };

            /**
            * Convert the point coordinates from logic unit (percentage) to geographic unit (longitude and latitude).
            * @param {IPoint} position The point to convert, in logic unit.
            * @returns {IPoint} The new point after converted, in geographic unit.
            */
            CoordConverter.prototype.logicToGeographic = function (position) {
                var self = this, logicPosition = self._rangeLogicPoint(position);
                return self._projection.unproject(logicPosition);
            };

            /**
            * Gets the size of the map viewport.
            @returns {ISize} The size of the map viewport, in screen unit (pixel).
            */
            CoordConverter.prototype.getViewSize = function () {
                return this._size;
            };

            /**
            * Gets the size of the map viewport.
            * returns {ISize} The size of the map viewport, in logic unit (percentage).
            */
            CoordConverter.prototype.getLogicSize = function () {
                var self = this, viewSize = self.getViewSize(), fullMapSize = self.getFullMapSize();
                return new maps.Size(viewSize).scale(1 / fullMapSize.width, 1 / fullMapSize.height);
            };

            /**
            * Gets the center of the map viewport.
            * returns {IPoint} The center of the map view port, in screen unit (pixel).
            */
            CoordConverter.prototype.getViewCenter = function () {
                var self = this, size = self._size;
                return new maps.Point(size.width, size.height).scale(0.5, 0.5);
            };

            /**
            * Gets the center of the map viewport.
            * returns {IPoint} The center of the map view port, in logic unit (percentage).
            */
            CoordConverter.prototype.getLogicCenter = function () {
                var self = this;
                return self.geographicToLogic(self.center);
            };

            /**
            * Gets the size of the full map in current zoom level.
            * @returns {ISize} The size of the full map, in screen unit (pixel).
            */
            CoordConverter.prototype.getFullMapSize = function () {
                var self = this;
                return new maps.Size(self.tileWidth, self.tileHeight).scale(Math.pow(2, self.zoom), Math.pow(2, self.zoom));
            };

            /**
            * Calculate the distance between two points.
            * @param {IPoint} lonLat1 The coordinate of first point, in geographic unit.
            * @param {IPoint} longLat2 The coordinate of second point, in geographic unit.
            * @returns {number} The distance between to points, in meters.
            */
            CoordConverter.prototype.distance = function (lonLat1, lonLat2) {
                // taken from http://www.movable-type.co.uk/scripts/latlong.html
                var r = 6371000.0, dLat = (lonLat2.y - lonLat1.y) * (Math.PI / 180), dLon = (lonLat2.x - lonLat1.x) * (Math.PI / 180), a = Math.sin(dLat * 0.5) * Math.sin(dLat * 0.5) + Math.cos(lonLat1.y * (Math.PI / 180)) * Math.cos(lonLat2.y * (Math.PI / 180)) * Math.sin(dLon * 0.5) * Math.sin(dLon * 0.5), c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
                return r * c;
            };

            CoordConverter.prototype._rangeLogicPoint = function (position) {
                var min = 0, max = 0.9999999999;
                if (position.x < min)
                    position.x = min;
                if (position.y < min)
                    position.y = min;
                if (position.x > max)
                    position.x = max;
                if (position.y > max)
                    position.y = max;
                return position;
            };
            return CoordConverter;
        })();
        maps.CoordConverter = CoordConverter;
    })(wijmo.maps || (wijmo.maps = {}));
    var maps = wijmo.maps;
})(wijmo || (wijmo = {}));

var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /// <reference path="../../External/declarations/jquery.d.ts"/>
    (function (maps) {
        var $ = jQuery;

        /**
        * This object provides the mapping relationship between html language and bing maps language,
        * user can override this object to custom mapping relationship.
        */
        maps.cultureMapping = {
            "en": "en-US",
            "zh": "zh-Hans",
            "ja": "ja-JP"
        };

        

        /**
        * @ignore
        * The built-in tile source which gets the tile from bing maps.
        */
        var BingMapsSourceBase = (function () {
            function BingMapsSourceBase() {
                /**
                * The width of the tile, in pixel. The value is 256.
                */
                this.tileWidth = 256;
                /**
                * The height of the tile, in pixel. The value is 256.
                */
                this.tileHeight = 256;
                /**
                * The minmum zoom level which can show the tile. The value is 1.
                */
                this.minZoom = 1;
                /**
                * The maximum zoom level which can show the tile. The value is 19.
                */
                this.maxZoom = 19;
                this._uriFormat = "";
                this._subdomains = ["0", "1", "2", "3", "4", "5", "6", "7"];
            }
            /**
            * The callback function to get the url of the specific tile.
            * @param {number} zoom The current zoom level.
            * @param {number} x The column index of the tile, in 0 base. The amount of columns is 2^zoom.
            * @param {number} y The row index of the tile, in 0 base. The amount of rows is 2^zoom.
            * @return {string} The url of the specific tile.
            */
            BingMapsSourceBase.prototype.getUrl = function (zoom, x, y) {
                var self = this, subdomain = self._subdomains[(y * Math.pow(2, zoom) + x) % self._subdomains.length];
                return self._uriFormat.replace("{subdomain}", subdomain).replace("{quadkey}", self._getQuadkey(zoom, x, y)).replace("{culture}", self._getCulture());
            };

            // see http://msdn.microsoft.com/en-us/library/bb545006.aspx or http://www.cadmaps.com/gisblog/?p=7
            // for an explanation of how the quad tree tiles are codified
            BingMapsSourceBase.prototype._getQuadkey = function (zoom, x, y) {
                var quadkey = "", quadCode = [0, 2, 1, 3];
                for (var i = zoom; i > 0; --i) {
                    quadkey += quadCode[((x >> (i - 1) << 1) & 2) | ((y >> (i - 1)) & 1)];
                }
                return quadkey;
            };

            BingMapsSourceBase.prototype._getCulture = function () {
                var bodyLang = $("body").attr("lang"), htmlLang = $("html").attr("lang"), lang = bodyLang || htmlLang || "en";
                return wijmo.maps.cultureMapping[lang] || "en-US";
            };
            return BingMapsSourceBase;
        })();

        /**
        * @ignore
        * The built-in tile source which gets the tile from bing maps with road style.
        */
        var BingMapsRoadSource = (function (_super) {
            __extends(BingMapsRoadSource, _super);
            function BingMapsRoadSource() {
                _super.apply(this, arguments);
                //"http://t{subdomain}.tiles.ditu.live.com/tiles/r{quadkey}.png?g=41";
                this._uriFormat = "http://ecn.t{subdomain}.tiles.virtualearth.net/tiles/r{quadkey}.jpeg?g=2889&mkt={culture}&shading=hill";
            }
            return BingMapsRoadSource;
        })(BingMapsSourceBase);

        /**
        * @ignore
        * The built-in tile source which gets the tile from bing maps with aerial style.
        */
        var BingMapsAerialSource = (function (_super) {
            __extends(BingMapsAerialSource, _super);
            function BingMapsAerialSource() {
                _super.apply(this, arguments);
                this._uriFormat = "http://ecn.t{subdomain}.tiles.virtualearth.net/tiles/a{quadkey}.jpeg?g=2889&mkt={culture}&shading=hill";
            }
            return BingMapsAerialSource;
        })(BingMapsSourceBase);

        /**
        * @ignore
        * The built-in tile source which gets the tile from bing maps with hybrid style.
        */
        var BingMapsHybridSource = (function (_super) {
            __extends(BingMapsHybridSource, _super);
            function BingMapsHybridSource() {
                _super.apply(this, arguments);
                this._uriFormat = "http://ecn.t{subdomain}.tiles.virtualearth.net/tiles/h{quadkey}.jpeg?g=2889&mkt={culture}&shading=hill";
            }
            return BingMapsHybridSource;
        })(BingMapsSourceBase);

        /**
        * @ignore
        * Defines the built-in tile sources.
        */
        var MapSource = (function () {
            function MapSource() {
            }
            MapSource.bingMapsRoadSource = new BingMapsRoadSource();

            MapSource.bingMapsAerialSource = new BingMapsAerialSource();

            MapSource.bingMapsHybridSource = new BingMapsHybridSource();
            return MapSource;
        })();
        maps.MapSource = MapSource;
    })(wijmo.maps || (wijmo.maps = {}));
    var maps = wijmo.maps;
})(wijmo || (wijmo = {}));

///<reference path="CoordConverter.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    (function (maps) {
        var $ = jQuery;

        /** @ignore */
        (function (LayerType) {
            LayerType[LayerType["vector"] = 0] = "vector";
            LayerType[LayerType["items"] = 1] = "items";
            LayerType[LayerType["virtual"] = 2] = "virtual";
            LayerType[LayerType["custom"] = 3] = "custom";
        })(maps.LayerType || (maps.LayerType = {}));
        var LayerType = maps.LayerType;

        /**
        * @widget
        * The base widget of the wijmaps layer.
        */
        var wijlayer = (function (_super) {
            __extends(wijlayer, _super);
            function wijlayer() {
                _super.apply(this, arguments);
            }
            /** @ignore */
            wijlayer.prototype._create = function () {
                _super.prototype._create.call(this);

                var self = this;
                self._updating = false;
                self._needUpdate = false;
            };

            /**
            * Create the Raphael paper within the container and specific size.
            */
            wijlayer.prototype._createPaper = function (container, size) {
                var clip, paper = Raphael(container, 1, 1);
                $(paper.canvas).css("overflow", "visible");
                this._resizePaper(paper, size);
                return paper;
            };

            /**
            * Update the Raphael paper size based on the container size.
            */
            wijlayer.prototype._resizePaper = function (paper, size) {
                if (Raphael.svg) {
                    $(paper.canvas).css("width", size.width + "px").css("height", size.height + "px");
                } else {
                    $(paper.canvas).css("clip", "rect(0px," + size.width + "px," + size.height + "px,0px)");
                    // vml, keept 1px*1px;
                }
            };

            /** @ignore */
            wijlayer.prototype._setOption = function (key, value) {
                var self = this, o = this.options;
                if (o[key] !== value) {
                    switch (key) {
                        case 'center':
                            self._setCenter(value);
                            return;
                        case 'zoom':
                            self._setZoom(value);
                            return;
                    }
                }
                _super.prototype._setOption.call(this, key, value);
            };

            /**
            * Set the center of the layer.
            * @param {Point} center The current center of the layer, in geographic unit.
            */
            wijlayer.prototype._setCenter = function (center) {
                var self = this, o = self.options;
                if (o.center.x !== center.x || o.center.y !== center.y) {
                    o.center = center;
                    self.update();
                }
            };

            /**
            * Set the zoom of the layer.
            * @param {number} zoom The current zoom of the layer.
            */
            wijlayer.prototype._setZoom = function (zoom) {
                var self = this, o = self.options;
                if (o.zoom !== zoom) {
                    o.zoom = zoom;
                    self.update();
                }
            };

            /**
            * Draw the layer.
            */
            wijlayer.prototype._render = function () {
            };

            /**
            * Update the layer, redraw the layer if needed. It's called when the center and zoom changed.
            */
            wijlayer.prototype.update = function () {
                var self = this, o = self.options;
                if (self._updating) {
                    self._needUpdate = true;
                    return;
                }

                self._render();
            };

            /**
            * Called when the wijmaps begins to update the layer status.
            */
            wijlayer.prototype.beginUpdate = function () {
                this._updating = true;
            };

            /**
            * Called when the wijmaps ends update the layer status. The layer will be updated after this function called.
            */
            wijlayer.prototype.endUpdate = function () {
                var self = this;
                self._updating = false;
                if (self._needUpdate) {
                    self.update();
                }
            };

            /**
            * Refresh the layer. Usually used if want to apply the new data to the layer.
            */
            wijlayer.prototype.refresh = function () {
                this.update();
            };
            return wijlayer;
        })(wijmo.wijmoWidget);
        maps.wijlayer = wijlayer;

        

        

        

        /**
        * The options of the wijlayer.
        */
        var wijlayer_options = (function () {
            function wijlayer_options() {
            }
            return wijlayer_options;
        })();
        maps.wijlayer_options = wijlayer_options;

        wijlayer.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijlayer_options());

        $.wijmo.registerWidget("wijlayer", wijlayer.prototype);
    })(wijmo.maps || (wijmo.maps = {}));
    var maps = wijmo.maps;
})(wijmo || (wijmo = {}));

/// <reference path="Drawing.ts"/>
/// <reference path="Utils.ts"/>
/// <reference path="ClippingEngine.ts"/>
/// <reference path="wijlayer.ts" />
/// <reference path="../../Base/jquery.wijmo.widget.ts" />
/// <reference path="../../wijutil/jquery.wijmo.raphael.ts"/>
/// <reference path="../../External/declarations/geojson.d.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    (function (maps) {
        var $ = jQuery, vectorCanvasCss = "wijmo-wijmaps-vectorlayer-canvas", layerContainerCss = "wijmo-wijmaps-layercontainer", vectorShapeCss = "wijmo-wijmaps-vectorlayer-shape", vectorMarkCss = "wijmo-wijmaps-vectorlayer-mark", vectorMarkLabelCss = "wijmo-wijmaps-vectorlayer-marklabel", vectorData = "wijmoWijvectorlayerData";

        /** @ignore */
        var VectorType;
        (function (VectorType) {
            VectorType[VectorType["placemark"] = 0] = "placemark";
            VectorType[VectorType["polyline"] = 1] = "polyline";
            VectorType[VectorType["polygon"] = 2] = "polygon";
        })(VectorType || (VectorType = {}));

        /** @ignore */
        var LabelVisibility;
        (function (LabelVisibility) {
            LabelVisibility[LabelVisibility["hidden"] = 0] = "hidden";
            LabelVisibility[LabelVisibility["autoHide"] = 1] = "autoHide";
            LabelVisibility[LabelVisibility["visible"] = 2] = "visible";
        })(LabelVisibility || (LabelVisibility = {}));

        /** @ignore */
        var LabelPosition;
        (function (LabelPosition) {
            LabelPosition[LabelPosition["center"] = 0] = "center";
            LabelPosition[LabelPosition["left"] = 1] = "left";
            LabelPosition[LabelPosition["right"] = 2] = "right";
            LabelPosition[LabelPosition["top"] = 3] = "top";
            LabelPosition[LabelPosition["bottom"] = 4] = "bottom";
        })(LabelPosition || (LabelPosition = {}));

        /** @ignore */
        var LOD = (function () {
            function LOD(data) {
                this.minSize = 0;
                this.maxSize = 0;
                this.minZoom = 0;
                this.maxZoom = 0;
                if (!data) {
                    return;
                }

                var self = this;
                self.minSize = data.minSize || 0;
                self.maxSize = data.maxSize || 0;
                self.minZoom = data.minZoom || 0;
                self.maxZoom = data.maxZoom || 0;
            }
            LOD.prototype.isDefault = function () {
                return this.minSize === 0 && this.maxSize === 0 && this.minZoom === 0 && this.maxZoom === 0;
            };
            return LOD;
        })();
        maps.LOD = LOD;

        

        /** @ignore */
        var MapState = (function () {
            function MapState() {
            }
            return MapState;
        })();

        /** @ignore */
        var ProjectionFast = (function () {
            function ProjectionFast(scaleX, scaleY, offsetX, offsetY, extraX, extraY) {
                var self = this;
                self._scaleX = scaleX;
                self._scaleY = scaleY;
                self._offsetX = offsetX;
                self._offsetY = offsetY;
                self._extraX = extraX;
                self._extraY = extraY;
            }
            ProjectionFast.prototype.init = function (o) {
                var self = this, converter = o.converter, viewSize = converter.getViewSize(), logicSize = converter.getLogicSize(), geographicCenter = o.center, scale = viewSize.width / logicSize.width, logicCenter = converter.geographicToLogic(geographicCenter), offsetX = 0.5 * viewSize.width - logicCenter.x * scale, offsetY = 0.5 * viewSize.height - logicCenter.y * scale;

                self._ax = ProjectionFast.toRad * self._scaleX * scale;
                self._bx = self._offsetX * scale + offsetX + self._extraX;

                self._ay = 0.5 * self._scaleY * scale;
                self._by = self._offsetY * scale + offsetY + self._extraY;

                self._converter = converter;
            };

            ProjectionFast.prototype.project = function (longLat) {
                var self = this, converter = self._converter;

                if (converter) {
                    if (longLat.y > converter.maxLatitude)
                        longLat.y = converter.maxLatitude;
                    if (longLat.y < converter.minLatitude)
                        longLat.y = converter.minLatitude;
                }

                var sinLat = Math.sin(longLat.y * ProjectionFast.toRad), x = (longLat.x * self._ax + self._bx), y = (Math.log((1.0 + sinLat) / (1.0 - sinLat)) * self._ay + self._by);

                return new maps.Point(x, y);
            };

            ProjectionFast.prototype.unproject = function (point) {
                var self = this, x = ((point.x - self._offsetX) * ProjectionFast.toDeg / self._scaleX), y = (Math.atan(maps.Utils.sinh((point.y - self._offsetY) / self._scaleY)) * ProjectionFast.toDeg);

                return new maps.Point(x, y);
            };
            ProjectionFast.toRad = Math.PI / 180;
            ProjectionFast.toDeg = 180 / Math.PI;
            return ProjectionFast;
        })();

        /**
        * @widget
        * The vector layer for the wijmaps. Draw the shapes and placemarks.
        */
        var wijvectorlayer = (function (_super) {
            __extends(wijvectorlayer, _super);
            function wijvectorlayer() {
                _super.apply(this, arguments);
            }
            /** @ignore */
            wijvectorlayer.prototype._create = function () {
                var self = this, selector = "." + vectorShapeCss;

                self._proj = new ProjectionFast(1 / (Math.PI * 2), -1 / (Math.PI * 2), 0.5, 0.5, -wijvectorlayer._offsetX, -wijvectorlayer._offsetY);
                self._cache = null;
                self._needFullUpdateShape = false;
                self._needDrawMarkShape = false;

                self._container = $("<div class=\"" + vectorCanvasCss + "\"></div>").appendTo(self.element).on("click." + self.widgetName, selector, function (e) {
                    self._onItemMouseEvent("click", e, this);
                }).on("mousedown." + self.widgetName, selector, function (e) {
                    self._onItemMouseEvent("mouseDown", e, this);
                }).on("mouseup." + self.widgetName, selector, function (e) {
                    self._onItemMouseEvent("mouseUp", e, this);
                }).on("mousemove." + self.widgetName, selector, function (e) {
                    self._onItemMouseEvent("mouseMove", e, this);
                }).on("mouseenter." + self.widgetName, selector, function (e) {
                    self._onItemMouseEvent("mouseEnter", e, this);
                }).on("mouseleave." + self.widgetName, selector, function (e) {
                    self._onItemMouseEvent("mouseLeave", e, this);
                });

                _super.prototype._create.call(this);

                self._setData(self.options.data);
            };

            /** @ignore */
            wijvectorlayer.prototype._setOption = function (key, value) {
                var self = this, o = this.options;
                if (o[key] !== value) {
                    switch (key) {
                        case 'dataType':
                            self._setDataType(value);
                            return;
                        case 'data':
                            self._setData(value);
                            return;
                    }
                }
                _super.prototype._setOption.call(this, key, value);
            };

            wijvectorlayer.prototype._setDataType = function (dataType) {
                var self = this;
                self.options.dataType = dataType;
            };

            wijvectorlayer.prototype._setData = function (data) {
                var self = this, o = self.options;
                o.data = data;

                if (typeof (data) === "string") {
                    self._prepareDataFromUri(data);
                } else if ($.isFunction(data)) {
                    self._applyData(data());
                } else {
                    self._applyData(data);
                }
            };

            wijvectorlayer.prototype._prepareDataFromUri = function (dataUri) {
                var self = this;
                $.ajax({
                    url: dataUri,
                    data: null,
                    context: null,
                    success: function (result) {
                        self._uriLoaded(result);
                    },
                    error: null,
                    dataType: "json"
                });
            };

            wijvectorlayer.prototype._uriLoaded = function (result) {
                var self = this;
                self._applyData(result);
            };

            wijvectorlayer.prototype._applyData = function (data) {
                var self = this;

                if (self._data === data)
                    return;
                self._data = data;

                self._applyDataInternal(data);
            };

            wijvectorlayer.prototype._applyDataInternal = function (data) {
                var self = this, o = self.options;
                if (o.dataType === DataJsonType.wijJson) {
                    self._applyWijJsonData(data);
                } else if (o.dataType === DataJsonType.geoJson) {
                    self._applyGeoJsonData(data);
                }

                self._needFullUpdateShape = true;
                self.update();
            };

            wijvectorlayer.prototype._applyWijJsonData = function (data) {
                this._createVectors(data);
            };

            wijvectorlayer.prototype._applyGeoJsonData = function (data) {
                var self = this, obj = GeoObject.create(data);
                if (obj) {
                    obj.applyData(data, {});
                }
                self._vectorObj = obj;
            };

            wijvectorlayer.prototype._createVectors = function (data) {
                var _this = this;
                var self = this, list = new VectorItemCollection();
                if (data && data.vectors) {
                    $.each(data.vectors, function (index, vector) {
                        var item = _this._createVector(vector);
                        if (item) {
                            var wrapper = new VectorItemWrapper(item);
                            wrapper.applyData(vector);
                            list.addChild(wrapper);
                        }
                    });
                }

                self._vectorObj = list;
            };

            wijvectorlayer.prototype._createVector = function (vectorData) {
                switch (VectorType[vectorData.type]) {
                    case 2 /* polygon */:
                        return new VectorPolygon();
                    case 0 /* placemark */:
                        return new VectorPlacemark();
                    case 1 /* polyline */:
                        return new VectorPolyline();
                }

                return null;
            };

            /**
            * @ignore
            * override
            */
            wijvectorlayer.prototype._render = function () {
                var self = this;
                _super.prototype._render.call(this);
                self._updateShape();
            };

            wijvectorlayer.prototype._createContainer = function () {
                var self = this, clip = wijvectorlayer._clipRect;

                self._destroyContainer();

                self._shapeContainer = $("<div class=\"" + layerContainerCss + "\"></div>");
                self._paper = self._createPaper(self._shapeContainer[0], new maps.Size(clip.getRight(), clip.getBottom()));
                self._group = self._paper.group();
                self._placemarkContainer = $("<div class=\"" + layerContainerCss + "\" style='visibility:hidden;'></div>");
            };

            wijvectorlayer.prototype._destroyContainer = function () {
                var self = this;
                if (self._paper)
                    self._paper.remove();
                if (self._shapeContainer) {
                    self._shapeContainer.off("." + self.widgetName).remove();
                }
                if (self._placemarkContainer) {
                    self._placemarkContainer.off("." + self.widgetName).remove();
                }
            };

            wijvectorlayer.prototype._refreshPaper = function () {
                var self = this;
                self._container.css("left", wijvectorlayer._offsetX + "px").css("top", wijvectorlayer._offsetY + "px");
                self._createContainer();

                self._marks = [];
                if (self._vectorObj) {
                    self._drawVectorObj(self._vectorObj);
                }

                self._container.append(self._shapeContainer);
                self._container.append(self._placemarkContainer);
                self._arrangeMarks();
                self._arrangeLabels();
                self._placemarkContainer.css("visibility", "visible");
            };

            wijvectorlayer.prototype._drawVectorObj = function (vector) {
                var self = this;

                self._drawSingleVectorObj(vector);

                if (vector && vector.children && vector.children.length > 0) {
                    $.each(vector.children, function (index, child) {
                        self._drawVectorObj(child);
                    });
                }
            };

            wijvectorlayer.prototype._drawSingleVectorObj = function (vector) {
                var self = this, shape, els, el, data = { vector: vector, shape: null };
                if (vector.vectorItems) {
                    $.each(vector.vectorItems, function (index, item) {
                        if (item.visible) {
                            shape = item.getShape();
                            if (shape) {
                                el = shape.createElement(self._paper);
                                if (el) {
                                    self._group.push(el);
                                    if (els) {
                                        el.forEach(function (e) {
                                            els.push(e);
                                        });
                                    } else {
                                        els = el;
                                    }
                                }
                            }

                            if (item instanceof VectorPlacemark) {
                                self._drawPlacemark(item, data);
                            }
                        }
                    });

                    if (els) {
                        data.shape = els;
                        $.each(els, function (index, element) {
                            $.wijraphael.addClass($(element.node), vectorShapeCss);
                            $(element.node).data(vectorData, data);
                        });
                        self._onShapeCreated("shapeCreated", data);
                    }
                }
            };

            wijvectorlayer.prototype._drawPlacemark = function (placemark, data) {
                var self = this, cache = { location: placemark.point };
                if (!self._needDrawMarkShape) {
                    self._drawMark(placemark, data, cache);
                }
                self._drawLabel(placemark, cache);

                if (cache.mark || cache.label) {
                    self._marks.push(cache);
                }
            };

            wijvectorlayer.prototype._drawMark = function (placemark, data, cache) {
                var self = this, mo = self.options.placemark, point, mark, size, pin, top, left;

                if (mo === null)
                    return;

                if (mo.render) {
                    mark = mo.render(data);
                } else if (mo.image) {
                    mark = $("<img src='" + mo.image + "' />");
                }

                if (!mark || !mark.length)
                    return;

                cache.mark = mark;
                mark.addClass(vectorMarkCss).data(vectorData, data).appendTo(self._placemarkContainer);
            };

            wijvectorlayer.prototype._arrangeMarks = function () {
                var self = this, o = self.options, mo = o.placemark || {}, location, mark, size, pin, top, left;

                if (self._marks) {
                    $.each(self._marks, function (index, cache) {
                        if (cache.mark) {
                            mark = cache.mark;
                            location = o.converter.geographicToView(cache.location);
                            size = cache.markSize || mo.size || new maps.Size(mark.width(), mark.height());
                            pin = mo.pinPoint || new maps.Point(size.width / 2, size.height / 2);

                            location.x -= wijvectorlayer._offsetX;
                            location.y -= wijvectorlayer._offsetY;

                            left = location.x - pin.x;
                            top = location.y - pin.y;

                            cache.markSize = size;
                            mark.css("position", "absolute").css("left", left + "px").css("top", top + "px");
                        }
                    });
                }
            };

            wijvectorlayer.prototype._drawLabel = function (placemark, cache) {
                var self = this, mo = self.options.placemark || {}, visibility = LabelVisibility[mo.labelVisibility] || 0 /* hidden */, label = placemark.label || placemark.name;

                if (visibility === 0 /* hidden */ || !label) {
                    return;
                }

                var point = placemark.getViewBounds().location, text = $("<span style='position:absolute;' class='" + vectorMarkLabelCss + "'>" + label + "</span>").appendTo(self._placemarkContainer);

                cache.label = text;
            };

            wijvectorlayer.prototype._arrangeLabels = function (visibility) {
                var self = this, o = self.options, mo = o.placemark || {}, labelBounds = [];
                visibility = visibility || LabelVisibility[mo.labelVisibility] || 0 /* hidden */;

                $.each(self._marks, function (index, cache) {
                    if (cache.label) {
                        var location, rect, overlap = false, len = labelBounds.length, i;

                        location = o.converter.geographicToView(cache.location);
                        location.x -= wijvectorlayer._offsetX;
                        location.y -= wijvectorlayer._offsetY;
                        rect = self._calculateLabelBounds(location, cache.label, cache.labelSize);

                        if (visibility === 1 /* autoHide */) {
                            for (i = 0; i < len; i++) {
                                if (rect.intersectsWith(labelBounds[i])) {
                                    overlap = true;
                                    break;
                                }
                            }
                        }

                        if (overlap) {
                            cache.label.remove();
                        } else {
                            cache.label.css("left", rect.location.x + "px").css("top", rect.location.y + "px");
                            cache.labelSize = rect.size;
                            if (visibility === 1 /* autoHide */) {
                                labelBounds.push(rect);
                            }
                        }
                    }
                });
            };

            wijvectorlayer.prototype._calculateLabelBounds = function (point, text, size) {
                var self = this, mo = self.options.placemark || {}, position = LabelPosition[mo.labelPosition] || 0 /* center */, width = size ? size.width : text.outerWidth(), height = size ? size.height : text.outerHeight(), left, top;

                if (position === 1 /* left */) {
                    left = point.x - width;
                    top = point.y - height / 2;
                } else if (position === 2 /* right */) {
                    left = point.x;
                    top = point.y - height / 2;
                } else if (position === 3 /* top */) {
                    left = point.x - width / 2;
                    top = point.y - height;
                } else if (position === 4 /* bottom */) {
                    left = point.x - width / 2;
                    top = point.y;
                } else {
                    left = point.x - width / 2;
                    top = point.y - height / 2;
                }

                return new maps.Rectangle(new maps.Point(left, top), new maps.Size(width, height));
            };

            wijvectorlayer.prototype._translatePaper = function (dx, dy) {
                var self = this, left = wijvectorlayer._offsetX + dx, top = wijvectorlayer._offsetY + dy;
                self._container.css("left", left + "px").css("top", top + "px");
            };

            wijvectorlayer.prototype._scalePaper = function (sx, sy, dx, dy) {
                var self = this;
                if (Raphael.vml) {
                    self._container.empty();
                    return;
                }

                var viewSize = self.options.converter.getViewSize(), left = wijvectorlayer._offsetX, top = wijvectorlayer._offsetY, cx = viewSize.width / 2 - wijvectorlayer._offsetX, cy = viewSize.height / 2 - wijvectorlayer._offsetY, matrix = Raphael.matrix(1, 0, 0, 1, 0, 0);

                self._container.css("left", left + "px").css("top", top + "px");
                self._arrangeMarks();
                self._arrangeLabels(2 /* visible */);

                matrix.translate(dx, dy);
                matrix.scale(sx, sy, cx, cy);
                self._group.transform(matrix);
            };

            wijvectorlayer.prototype._updateShape = function () {
                var self = this;
                if (!self._cache || self._needFullUpdateShape) {
                    self._fullUpdateShape();
                    return;
                }

                var o = self.options, converter = o.converter, pt1 = converter.geographicToView(o.center), pt2 = converter.geographicToView(self._cache.center), dx = pt2.x - pt1.x, dy = pt2.y - pt1.y;

                if (o.zoom === o.targetZoom) {
                    var clip = wijvectorlayer._clipRect;
                    if (o.zoom !== self._cache.zoom || self._needFullUpdateShape || Math.abs(dx) > 0.4 * clip.size.width || Math.abs(dy) > 0.4 * clip.size.height) {
                        self._fullUpdateShape();
                        return;
                    } else {
                        self._translatePaper(dx, dy);
                    }
                } else {
                    var scale = Math.pow(2, o.zoom) / Math.pow(2, self._cache.zoom);
                    self._scalePaper(scale, scale, dx, dy);
                }

                return;
            };

            wijvectorlayer.prototype._updateVectorObj = function (vector, pc, gclip, minsz2, zoom) {
                var self = this;

                self._updateSingleVectorObj(vector, pc, gclip, minsz2, zoom);

                if (vector && vector.children && vector.children.length > 0) {
                    $.each(vector.children, function (index, child) {
                        self._updateVectorObj(child, pc, gclip, minsz2, zoom);
                    });
                }
            };

            wijvectorlayer.prototype._updateSingleVectorObj = function (vector, pc, gclip, minsz2, zoom) {
                var self = this;
                if (vector.vectorItems) {
                    $.each(vector.vectorItems, function (index, item) {
                        self._updateVectorItem(item, pc, gclip, minsz2, zoom);
                    });
                }
            };

            wijvectorlayer.prototype._updateVectorItem = function (item, pc, gclip, minsz2, zoom) {
                item.visible = false;
                if (!gclip.intersectsWith(item.getBounds()))
                    return;
                item.getViewBounds(pc);
                if (item.isVisible(minsz2, zoom)) {
                    item.visible = true;
                    item.updateShape(pc);
                }
            };

            wijvectorlayer.prototype._fullUpdateShape = function () {
                var self = this, o = self.options, mo = o.placemark || {}, minSize = (o.minSize == null) ? 3 : o.minSize, converter = o.converter, minsz2 = minSize * minSize;

                self._needDrawMarkShape = !(mo.image || mo.render);
                self._needFullUpdateShape = false;

                if (!self._vectorObj)
                    return;

                self._cache = { zoom: o.zoom, center: o.center };

                var pc = function (p) {
                    return self._proj.project(p);
                };

                self._proj.init(o);

                var clip = wijvectorlayer._clipRect, left = clip.location.x, top = clip.location.y, right = left + clip.size.width, bottom = top + clip.size.height, pt1 = converter.viewToGeographic(new maps.Point(left + wijvectorlayer._offsetX, top + wijvectorlayer._offsetY)), pt2 = converter.viewToGeographic(new maps.Point(right + wijvectorlayer._offsetX, bottom + wijvectorlayer._offsetY)), gclip = maps.Utils.getBounds([pt1, pt2]);

                self._updateVectorObj(self._vectorObj, pc, gclip, minsz2, o.zoom);

                self._refreshPaper();
            };

            wijvectorlayer.prototype._onShapeCreated = function (eventName, data) {
                this._trigger(eventName, null, data);
            };

            wijvectorlayer.prototype._onItemMouseEvent = function (eventName, e, target) {
                var self = this;
                if (self._isDisabled())
                    return;

                self._trigger(eventName, e, $(target).data(vectorData));
            };

            /**
            * Force to request the data to get the newest one.
            */
            wijvectorlayer.prototype.refresh = function () {
                var self = this;
                self._data = null;
                this._setData(self.options.data);
            };

            /**
            * Removes the wijvectorlayer functionality completely. This will return the element back to its pre-init state.
            */
            wijvectorlayer.prototype.destroy = function () {
                var self = this;
                if (self._paper)
                    self._paper.remove();
                self._container.off("." + self.widgetName).remove();

                _super.prototype.destroy.call(this);
            };
            wijvectorlayer._offsetX = -2000;

            wijvectorlayer._offsetY = -2000;

            wijvectorlayer._clipRect = new maps.Rectangle(new maps.Point(-wijvectorlayer._offsetX - 1000, -wijvectorlayer._offsetY - 1000), new maps.Size(3000, 3000));
            return wijvectorlayer;
        })(maps.wijlayer);
        maps.wijvectorlayer = wijvectorlayer;

        /** @ignore */
        var GeoObjectType;
        (function (GeoObjectType) {
            GeoObjectType[GeoObjectType["Point"] = 0] = "Point";
            GeoObjectType[GeoObjectType["MultiPoint"] = 1] = "MultiPoint";
            GeoObjectType[GeoObjectType["LineString"] = 2] = "LineString";
            GeoObjectType[GeoObjectType["MultiLineString"] = 3] = "MultiLineString";
            GeoObjectType[GeoObjectType["Polygon"] = 4] = "Polygon";
            GeoObjectType[GeoObjectType["MultiPolygon"] = 5] = "MultiPolygon";
            GeoObjectType[GeoObjectType["GeometryCollection"] = 6] = "GeometryCollection";
            GeoObjectType[GeoObjectType["Feature"] = 7] = "Feature";
            GeoObjectType[GeoObjectType["FeatureCollection"] = 8] = "FeatureCollection";
        })(GeoObjectType || (GeoObjectType = {}));

        

        /** @ignore */
        var VectorItemCollection = (function () {
            function VectorItemCollection() {
                this.type = "VectorCollection";
                this.parent = null;
                this.children = [];
                this.vectorItems = null;
            }
            VectorItemCollection.prototype.applyData = function (data) {
            };

            VectorItemCollection.prototype.addChild = function (child) {
                this.children.push(child);
                child.parent = this;
            };
            return VectorItemCollection;
        })();

        /** @ignore */
        var VectorItemWrapper = (function () {
            function VectorItemWrapper(item) {
                this.item = item;
                this.type = "Vector";
                this.vectorItems = [item];
            }
            VectorItemWrapper.prototype.applyData = function (data) {
                this.data = data;
                this.item.applyData(data);
            };
            return VectorItemWrapper;
        })();

        /** @ignore */
        var GeoObject = (function () {
            function GeoObject() {
                this.type = "Object";
            }
            GeoObject.prototype.applyData = function (data, properties) {
                this.data = data;
                this.properties = properties;
            };

            GeoObject.prototype._addChild = function (child) {
                var self = this;
                self.children = self.children || [];
                self.children.push(child);
                child.parent = self;
            };

            GeoObject.create = function (data) {
                switch (data.type) {
                    case GeoObjectType[0 /* Point */]:
                        return new GeoPoint();
                    case GeoObjectType[1 /* MultiPoint */]:
                        return new GeoMultiPoint();
                    case GeoObjectType[2 /* LineString */]:
                        return new GeoLineString();
                    case GeoObjectType[3 /* MultiLineString */]:
                        return new GeoMultiLineString();
                    case GeoObjectType[4 /* Polygon */]:
                        return new GeoPolygon();
                    case GeoObjectType[5 /* MultiPolygon */]:
                        return new GeoMultiPolygon();
                    case GeoObjectType[6 /* GeometryCollection */]:
                        return new GeoGeometryCollection();
                    case GeoObjectType[7 /* Feature */]:
                        return new GeoFeature();
                    case GeoObjectType[8 /* FeatureCollection */]:
                        return new GeoFeatureCollection();
                }
                return null;
            };
            return GeoObject;
        })();

        /** @ignore */
        var GeoGeometryObject = (function (_super) {
            __extends(GeoGeometryObject, _super);
            function GeoGeometryObject() {
                _super.apply(this, arguments);
                this.type = "Geometry";
            }
            GeoGeometryObject.prototype._createVectorItem = function (type) {
                switch (type) {
                    case 2 /* polygon */:
                        return new VectorPolygon();
                    case 0 /* placemark */:
                        return new VectorPlacemark();
                    case 1 /* polyline */:
                        return new VectorPolyline();
                }

                return null;
            };
            return GeoGeometryObject;
        })(GeoObject);

        /** @ignore */
        var GeoPoint = (function (_super) {
            __extends(GeoPoint, _super);
            function GeoPoint() {
                _super.apply(this, arguments);
                this.type = "Point";
            }
            GeoPoint.prototype.applyData = function (data, properties) {
                var self = this, vector;
                _super.prototype.applyData.call(this, data, properties);
                self.data = data;
                if (data.coordinates) {
                    vector = self._createVectorItem(0 /* placemark */);
                    vector.applyGeoData(data.coordinates, properties);
                    self.vectorItems = [vector];
                }
            };
            return GeoPoint;
        })(GeoGeometryObject);

        /** @ignore */
        var GeoMultiPoint = (function (_super) {
            __extends(GeoMultiPoint, _super);
            function GeoMultiPoint() {
                _super.apply(this, arguments);
                this.type = "MultiPoint";
            }
            GeoMultiPoint.prototype.applyData = function (data, properties) {
                var self = this, vector;
                _super.prototype.applyData.call(this, data, properties);
                self.data = data;
                if (data.coordinates) {
                    self.vectorItems = [];
                    $.each(data.coordinates, function (index, single) {
                        vector = self._createVectorItem(0 /* placemark */);
                        vector.applyGeoData(single, properties);
                        self.vectorItems.push(vector);
                    });
                }
            };
            return GeoMultiPoint;
        })(GeoGeometryObject);

        /** @ignore */
        var GeoLineString = (function (_super) {
            __extends(GeoLineString, _super);
            function GeoLineString() {
                _super.apply(this, arguments);
                this.type = "LineString";
            }
            GeoLineString.prototype.applyData = function (data, properties) {
                var self = this, vector;
                _super.prototype.applyData.call(this, data, properties);
                self.data = data;
                if (data.coordinates) {
                    vector = self._createVectorItem(1 /* polyline */);
                    vector.applyGeoData(data.coordinates, properties);
                    self.vectorItems = [vector];
                }
            };
            return GeoLineString;
        })(GeoGeometryObject);

        /** @ignore */
        var GeoMultiLineString = (function (_super) {
            __extends(GeoMultiLineString, _super);
            function GeoMultiLineString() {
                _super.apply(this, arguments);
                this.type = "MultiLineString";
            }
            GeoMultiLineString.prototype.applyData = function (data, properties) {
                var self = this, vector;
                _super.prototype.applyData.call(this, data, properties);
                self.data = data;
                if (data.coordinates) {
                    self.vectorItems = [];
                    $.each(data.coordinates, function (index, single) {
                        vector = self._createVectorItem(1 /* polyline */);
                        vector.applyGeoData(single, properties);
                        self.vectorItems.push(vector);
                    });
                }
            };
            return GeoMultiLineString;
        })(GeoGeometryObject);

        /** @ignore */
        var GeoPolygon = (function (_super) {
            __extends(GeoPolygon, _super);
            function GeoPolygon() {
                _super.apply(this, arguments);
                this.type = "Polygon";
            }
            GeoPolygon.prototype.applyData = function (data, properties) {
                var self = this, vector;
                _super.prototype.applyData.call(this, data, properties);
                self.data = data;
                if (data.coordinates) {
                    vector = self._createVectorItem(2 /* polygon */);
                    vector.applyGeoData(data.coordinates, properties);
                    self.vectorItems = [vector];
                }
            };
            return GeoPolygon;
        })(GeoGeometryObject);

        /** @ignore */
        var GeoMultiPolygon = (function (_super) {
            __extends(GeoMultiPolygon, _super);
            function GeoMultiPolygon() {
                _super.apply(this, arguments);
                this.type = "MultiPolygon";
            }
            GeoMultiPolygon.prototype.applyData = function (data, properties) {
                var self = this, vector;
                _super.prototype.applyData.call(this, data, properties);
                self.data = data;
                if (data.coordinates) {
                    self.vectorItems = [];
                    $.each(data.coordinates, function (index, single) {
                        vector = self._createVectorItem(2 /* polygon */);
                        vector.applyGeoData(single, properties);
                        self.vectorItems.push(vector);
                    });
                }
            };
            return GeoMultiPolygon;
        })(GeoGeometryObject);

        /** @ignore */
        var GeoGeometryCollection = (function (_super) {
            __extends(GeoGeometryCollection, _super);
            function GeoGeometryCollection() {
                _super.apply(this, arguments);
                this.type = "GeometryCollection";
            }
            GeoGeometryCollection.prototype.applyData = function (data, properties) {
                var self = this, child;
                _super.prototype.applyData.call(this, data, properties);
                if (data.geometries) {
                    $.each(data.geometries, function (index, geometry) {
                        child = GeoObject.create(geometry);
                        child.applyData(geometry, properties);
                        self._addChild(child);
                    });
                }
                self.geometries = self.children;
            };
            return GeoGeometryCollection;
        })(GeoGeometryObject);

        /** @ignore */
        var GeoFeature = (function (_super) {
            __extends(GeoFeature, _super);
            function GeoFeature() {
                _super.apply(this, arguments);
                this.type = "Feature";
            }
            GeoFeature.prototype.applyData = function (data) {
                var self = this, geometry;
                _super.prototype.applyData.call(this, data, data.properties);
                if (data.geometry) {
                    geometry = GeoObject.create(data.geometry);
                    geometry.applyData(data.geometry, data.properties);
                    self._addChild(geometry);
                    self.geometry = geometry;
                }
            };
            return GeoFeature;
        })(GeoObject);

        /** @ignore */
        var GeoFeatureCollection = (function (_super) {
            __extends(GeoFeatureCollection, _super);
            function GeoFeatureCollection() {
                _super.apply(this, arguments);
                this.type = "FeaturesCollectiton";
            }
            GeoFeatureCollection.prototype.applyData = function (data) {
                var self = this, child;
                _super.prototype.applyData.call(this, data, null);
                if (data.features) {
                    $.each(data.features, function (index, feature) {
                        child = GeoObject.create(feature);
                        child.applyData(feature, null);
                        self._addChild(child);
                    });
                }
                self.features = self.children;
            };
            return GeoFeatureCollection;
        })(GeoObject);

        /** @ignore */
        var VectorItem = (function () {
            function VectorItem() {
                /** @ignore */
                this._lod = new LOD();
                this.visible = true;
            }
            //virtual
            VectorItem.prototype.applyData = function (data) {
                this._applyProperties(data);
            };

            VectorItem.prototype.applyGeoData = function (coords, properties) {
                this._applyProperties(properties);
            };

            VectorItem.prototype._applyProperties = function (properties) {
                var self = this;
                if (properties) {
                    self.name = properties["name"];
                    self.fill = properties["fill"];
                    self.fillOpacity = properties["fillOpacity"];
                    self.stroke = properties["stroke"];
                    self.strokeOpacity = properties["strokeOpacity"];
                    self.strokeWidth = properties["strokeWidth"];
                    self.strokeDashArray = properties["strokeDashArray"];
                    self.strokeLineCap = maps.PenLineCap[properties["strokeLineCap"]];
                    self.strokeLineJoin = maps.PenLineJoin[properties["strokeLineJoin"]];
                    self.strokeMiterLimit = properties["strokeMiterLimit"];
                    self._lod = new LOD(properties.lod);
                }
            };

            //virtual
            VectorItem.prototype.getBounds = function () {
                return null;
            };

            //virtual
            VectorItem.prototype.getViewBounds = function (pc) {
                return null;
            };

            VectorItem.prototype.isVisible = function (minsz2, zoom) {
                var s2 = 0, bnds = this.getViewBounds();

                if (!bnds.isEmpty()) {
                    s2 = bnds.size.width * bnds.size.width + bnds.size.height * bnds.size.height;
                }

                var lod = this._lod;
                if (lod && lod.isDefault()) {
                    return s2 >= minsz2;
                } else {
                    var visible = (zoom >= lod.minZoom) && (zoom <= lod.maxZoom);
                    if (visible) {
                        if (lod.maxSize === 0)
                            return s2 >= lod.minSize * lod.minSize;
                        else if (this._lod.minSize === 0)
                            return s2 <= lod.maxSize * lod.maxSize;
                        else
                            return s2 >= lod.minSize * lod.minSize && s2 <= lod.maxSize * lod.maxSize;
                    } else {
                        return false;
                    }
                }
            };

            //virtual
            VectorItem.prototype.getShape = function () {
                return null;
            };

            VectorItem.prototype._initShape = function (shape) {
                var self = this;
                if (self.fill != null)
                    shape.fill = self.fill;
                if (self.fillOpacity != null)
                    shape.fillOpacity = self.fillOpacity;
                if (self.stroke != null)
                    shape.stroke = self.stroke;
                if (self.strokeOpacity != null)
                    shape.strokeOpacity = self.strokeOpacity;
                if (self.strokeWidth != null)
                    shape.strokeWidth = self.strokeWidth;
                if (self.strokeDashArray)
                    shape.strokeDashArray = self.strokeDashArray;
                if (self.strokeLineCap != null)
                    shape.strokeLineCap = self.strokeLineCap;
                if (self.strokeLineJoin)
                    shape.strokeLineJoin = self.strokeLineJoin;
                if (self.strokeMiterLimit)
                    shape.strokeMiterLimit = self.strokeMiterLimit;
            };

            //virtual
            VectorItem.prototype.updateShape = function (pc) {
            };

            VectorItem.convertPoints = function (pts, pc) {
                var filterPts = null;
                if (pts != null) {
                    var len = pts.length, prev = pc(pts[0]);

                    filterPts = [];
                    filterPts.push(prev);
                    for (var i = 1; i < len; i++) {
                        var pt = pc(pts[i]);
                        if (Math.abs(pt.x - prev.x) >= VectorItem.optRad || Math.abs(pt.y - prev.y) >= VectorItem.optRad) {
                            filterPts.push(pt);
                            prev = pt;
                        }
                    }
                }

                return filterPts;
            };

            VectorItem.convertPointsList = function (ptsList, pc) {
                var filterPtsList = null;
                if (ptsList != null && ptsList.length > 0) {
                    filterPtsList = [];
                    $.each(ptsList, function (index, pts) {
                        var filterPts = VectorItem.convertPoints(pts, pc);
                        if (filterPts) {
                            filterPtsList.push(filterPts);
                        }
                    });
                }

                return filterPtsList;
            };
            VectorItem.optRad = 1.5;
            return VectorItem;
        })();
        maps.VectorItem = VectorItem;

        /** @ignore */
        var VectorPlacemark = (function (_super) {
            __extends(VectorPlacemark, _super);
            function VectorPlacemark() {
                _super.apply(this, arguments);
            }
            VectorPlacemark.prototype.applyData = function (data) {
                _super.prototype.applyData.call(this, data);
                if (data.coordinates && data.coordinates.length > 1) {
                    this.point = new maps.Point(data.coordinates[0], data.coordinates[1]);
                }
            };

            VectorPlacemark.prototype.applyGeoData = function (coords, properties) {
                _super.prototype.applyGeoData.call(this, coords, properties);
                this.point = maps.Utils.getPointData(coords);
            };

            VectorPlacemark.prototype._applyProperties = function (properties) {
                var self = this;
                if (properties) {
                    _super.prototype._applyProperties.call(this, properties);
                    self.label = properties["label"];
                }
            };

            VectorPlacemark.prototype.getBounds = function () {
                var self = this;
                return new maps.Rectangle(new maps.Point(self.point.x, self.point.y), new maps.Size(0, 0));
            };

            VectorPlacemark.prototype.getViewBounds = function () {
                return this._bnds;
            };

            VectorPlacemark.prototype.isVisible = function (minsz2, zoom) {
                var lod = this._lod, visible = true;
                if (!lod.isDefault()) {
                    visible = (zoom >= lod.minZoom) && (zoom <= lod.maxZoom);
                }

                return visible;
            };

            VectorPlacemark.prototype.getShape = function () {
                return null;
            };

            VectorPlacemark.prototype.updateShape = function (pc) {
                var self = this, pt = pc(self.point), bnds = new maps.Rectangle(new maps.Point(pt.x, pt.y), new maps.Size(0, 0));
                self._bnds = bnds;
            };
            return VectorPlacemark;
        })(VectorItem);

        /** @ignore */
        var VectorPolyline = (function (_super) {
            __extends(VectorPolyline, _super);
            function VectorPolyline() {
                _super.apply(this, arguments);
            }
            VectorPolyline.prototype.applyData = function (data) {
                var self = this;
                _super.prototype.applyData.call(this, data);
                self.points = maps.Utils.getPoints(data.coordinates);
                self._gbnds = maps.Utils.getBounds(self.points);
            };

            VectorPolyline.prototype.applyGeoData = function (coords, properties) {
                _super.prototype.applyGeoData.call(this, coords, properties);
                var self = this;
                self.points = maps.Utils.getLineData(coords);
                self._gbnds = maps.Utils.getBounds(self.points);
            };

            VectorPolyline.prototype.getBounds = function () {
                return this._gbnds;
            };

            VectorPolyline.prototype.getViewBounds = function (pc) {
                var self = this;

                if (pc) {
                    var pt1 = new maps.Point(self._gbnds.location.x, self._gbnds.location.y);
                    var pt2 = new maps.Point(self._gbnds.getRight(), self._gbnds.getBottom());

                    pt1 = pc(pt1);
                    pt2 = pc(pt2);

                    self._bnds = maps.Utils.getBounds([pt1, pt2]);
                }

                return self._bnds;
            };

            VectorPolyline.prototype.getShape = function () {
                return this._plines;
            };

            VectorPolyline.prototype.updateShape = function (pc) {
                var self = this, clip = wijvectorlayer._clipRect, pts = VectorItem.convertPoints(self.points, pc);

                if (!self._plines) {
                    self._plines = new maps.MultiPolyline();
                    self._initShape(self._plines);
                }

                self._bnds = maps.Utils.getBounds(pts);

                if (self._bnds.size.width > clip.size.width || self._bnds.size.height > clip.size.height) {
                    self._plines.points = maps.ClippingEngine.createClippedLines(pts, clip);
                    self._bnds = self._bnds.intersect(clip);
                } else {
                    self._plines.points = [pts];
                }

                return this._bnds;
            };
            return VectorPolyline;
        })(VectorItem);

        /** @ignore */
        var VectorPolygon = (function (_super) {
            __extends(VectorPolygon, _super);
            function VectorPolygon() {
                _super.apply(this, arguments);
            }
            VectorPolygon.prototype.applyData = function (data) {
                var self = this, geoBounds, bounds;

                _super.prototype.applyData.call(this, data);
                self.pointsList = [maps.Utils.getPoints(data.coordinates)];
                self._gbnds = maps.Utils.getListBounds(self.pointsList);
            };

            VectorPolygon.prototype.applyGeoData = function (coords, properties) {
                var self = this;
                _super.prototype.applyGeoData.call(this, coords, properties);
                self.pointsList = maps.Utils.getPolygonData(coords);
                self._gbnds = maps.Utils.getListBounds(self.pointsList);
            };

            VectorPolygon.prototype.getBounds = function () {
                return this._gbnds;
            };

            VectorPolygon.prototype.getViewBounds = function (pc) {
                var self = this;

                if (pc) {
                    var pt1 = new maps.Point(self._gbnds.location.x, self._gbnds.location.y), pt2 = new maps.Point(this._gbnds.getRight(), this._gbnds.getBottom());

                    pt1 = pc(pt1);
                    pt2 = pc(pt2);

                    self._bnds = maps.Utils.getBounds([pt1, pt2]);
                }

                return self._bnds;
            };

            VectorPolygon.prototype.getShape = function () {
                return this._polygon;
            };

            VectorPolygon.prototype.updateShape = function (pc) {
                var self = this, clip = wijvectorlayer._clipRect, pts = VectorItem.convertPointsList(self.pointsList, pc);

                if (!self._polygon) {
                    self._polygon = new maps.Polygon();
                    self._initShape(self._polygon);
                }

                self._bnds = maps.Utils.getListBounds(pts);

                if (self._bnds.size.width > clip.size.width || self._bnds.size.height > clip.size.height) {
                    pts = maps.ClippingEngine.clipPolygonList(pts, clip);
                    self._bnds = maps.Utils.getListBounds(pts);
                }

                self._polygon.pointsList = pts;
            };
            return VectorPolygon;
        })(VectorItem);

        /**
        * The options of the wijvectorlayer.
        */
        var wijvectorlayer_options = (function (_super) {
            __extends(wijvectorlayer_options, _super);
            function wijvectorlayer_options() {
                _super.apply(this, arguments);
                /**
                * The type of the data object. The vector layer supports the following type:
                * <ul>
                * <li>wijJson: the json object with the C1 format. </li>
                * <li>geoJson: the json object with the GeoJson format.</li>
                * </ul>
                */
                this.dataType = DataJsonType.wijJson;
                /**
                * Specifies minimal size at which vectors become visible. The default value is 3.
                */
                this.minSize = 3;
                /**
                * Customize the rendering of placemark.
                */
                this.placemark = null;
                /**
                * This is a callback function called after the shape of the vector created for rendering.
                * @event
                * @param {jQuery.Event} event A jQuery Event object.
                * @param {IVectorEventData} data The data contains the vector and shape.
                * @dataKey {vector} The vector object which wraps the original data from data source.
                * @dataKey {shape} The set of Raphael elements which will be drawn.
                */
                this.shapeCreated = null;
                /**
                * This is a callback function called when the mouse enter the shape.
                * @event
                * @param {jQuery.Event} event A jQuery Event object.
                * @param {IVectorEventData} data The data contains the vector and shape.
                * @dataKey {vector} The vector object which wraps the original data from data source.
                * @dataKey {shape} The set of Raphael elements which will be drawn.
                */
                this.mouseEnter = null;
                /**
                * This is a callback function called when the mouse leave the shape.
                * @event
                * @param {jQuery.Event} event A jQuery Event object.
                * @param {IVectorEventData} data The data contains the vector and shape.
                * @dataKey {vector} The vector object which wraps the original data from data source.
                * @dataKey {shape} The set of Raphael elements which will be drawn.
                */
                this.mouseLeave = null;
                /**
                * This is a callback function called when click mouse down on the shape.
                * @event
                * @param {jQuery.Event} event A jQuery Event object.
                * @param {IVectorEventData} data The data contains the vector and shape.
                * @dataKey {vector} The vector object which wraps the original data from data source.
                * @dataKey {shape} The set of Raphael elements which will be drawn.
                */
                this.mouseDown = null;
                /**
                * This is a callback function called when click mouse up on the shape.
                * @event
                * @param {jQuery.Event} event A jQuery Event object.
                * @param {IVectorEventData} data The data contains the vector and shape.
                * @dataKey {vector} The vector object which wraps the original data from data source.
                * @dataKey {shape} The set of Raphael elements which will be drawn.
                */
                this.mouseUp = null;
                /**
                * This is a callback function called when move mouse on the shape.
                * @event
                * @param {jQuery.Event} event A jQuery Event object.
                * @param {IVectorEventData} data The data contains the vector and shape.
                * @dataKey {vector} The vector object which wraps the original data from data source.
                * @dataKey {shape} The set of Raphael elements which will be drawn.
                */
                this.mouseMove = null;
                /**
                * This is a callback function called when click mouse on the shape.
                * @event
                * @param {jQuery.Event} event A jQuery Event object.
                * @param {IVectorEventData} data The data contains the vector and shape.
                * @dataKey {vector} The vector object which wraps the original data from data source.
                * @dataKey {shape} The set of Raphael elements which will be drawn.
                */
                this.click = null;
            }
            return wijvectorlayer_options;
        })(maps.wijlayer_options);
        maps.wijvectorlayer_options = wijvectorlayer_options;

        /** @ignore */
        var DataJsonType = (function () {
            function DataJsonType() {
            }
            DataJsonType.wijJson = "wijJson";
            DataJsonType.geoJson = "geoJson";
            return DataJsonType;
        })();

        

        

        

        

        

        

        

        

        

        wijvectorlayer.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijvectorlayer_options());

        $.wijmo.registerWidget("wijvectorlayer", $.wijmo.wijlayer, wijvectorlayer.prototype);
    })(wijmo.maps || (wijmo.maps = {}));
    var maps = wijmo.maps;
})(wijmo || (wijmo = {}));


/// <reference path="Drawing.ts"/>
/// <reference path="Utils.ts"/>
/// <reference path="wijlayer.ts"/>
/// <reference path="wijitemslayer.ts" />
/// <reference path="../../Base/jquery.wijmo.widget.ts" />
/// <reference path="../../wijutil/jquery.wijmo.raphael.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    (function (maps) {
        var $ = jQuery, layerContainerCss = "wijmo-wijmaps-layercontainer";

        /**
        * @widget
        * The virtual layer for the wijmaps.
        * Display its items positioned geographically and only shows the items actually in view.
        */
        var wijvirtuallayer = (function (_super) {
            __extends(wijvirtuallayer, _super);
            function wijvirtuallayer() {
                _super.apply(this, arguments);
                this._maxZoom = 20;
            }
            /** @ignore */
            wijvirtuallayer.prototype._create = function () {
                var self = this;

                self._container = $("<div class=\"" + layerContainerCss + "\"></div>");
                self.element.append(self._container);
                self._paper = self._createPaper(self._container[0], self.options.converter.getViewSize());
                _super.prototype._create.call(this);

                self._setRequest(self.options.request);
            };

            /** @ignore */
            wijvirtuallayer.prototype._setOption = function (key, value) {
                var self = this, o = this.options;
                if (o[key] !== value) {
                    switch (key) {
                        case 'request':
                            self._setRequest(value);
                            return;
                        case 'slices':
                            self._setSlices(value);
                            return;
                    }
                }
                _super.prototype._setOption.call(this, key, value);
            };

            wijvirtuallayer.prototype._setRequest = function (request) {
                var self = this;
                self.options.request = request;
                self._refreshLayer();
            };

            wijvirtuallayer.prototype._setSlices = function (slices) {
                var self = this;
                self.options.slices = slices;
                self._refreshLayer();
            };

            wijvirtuallayer.prototype._refreshLayer = function () {
                var self = this, o = self.options;
                self._slices = self._sortSlices(o.slices);
                self._clear();
                self.update();
            };

            /**
            * @ignore
            * override
            */
            wijvirtuallayer.prototype._render = function () {
                var self = this, o = self.options, slice = self._getMatchedSlice();

                if (slice === null) {
                    self._clear();
                    return;
                }

                self._resizePaper(self._paper, o.converter.getViewSize());

                var index = $.inArray(slice, self._slices), maxZoom = index > 0 ? self._slices[index - 1].zoom : self._maxZoom, logicBounds = self._getLogicBounds(), topLeft = logicBounds.location, bottomRight = new maps.Point(logicBounds.getRight(), logicBounds.getBottom()), currentVisibleRegions = [];

                for (var i = Math.floor(topLeft.x * slice.longitudeSlices); i < bottomRight.x * slice.longitudeSlices; i++) {
                    for (var j = Math.floor(topLeft.y * slice.latitudeSlices); j < bottomRight.y * slice.latitudeSlices; j++) {
                        currentVisibleRegions.push(new maps.Region(slice, i, j));
                    }
                }

                var invisibleRegions = $.grep(self._visibleRegions, function (visibleRegion) {
                    for (var i = 0; i < currentVisibleRegions.length; i++) {
                        if (visibleRegion.equals(currentVisibleRegions[i])) {
                            return false;
                        }
                    }
                    return true;
                });
                $.each(invisibleRegions, function (regionIndex, region) {
                    self._removeRegion(region);
                });

                var newRegions = $.grep(currentVisibleRegions, function (currentVisibleRegion) {
                    for (var i = 0; i < self._visibleRegions.length; i++) {
                        if (currentVisibleRegion.equals(self._visibleRegions[i])) {
                            return false;
                        }
                    }
                    return true;
                });

                var remainVisibleRegions = $.grep(self._visibleRegions, function (region) {
                    return $.inArray(region, invisibleRegions) === -1;
                });

                self._visibleRegions = remainVisibleRegions.concat(newRegions);

                $.each(newRegions, function (regionIndex, region) {
                    var regionLowerLeft = o.converter.logicToGeographic(new maps.Point(region.longitude / slice.longitudeSlices, (region.latitude + 1) / slice.latitudeSlices)), regionUpperRight = o.converter.logicToGeographic(new maps.Point((region.longitude + 1) / slice.longitudeSlices, region.latitude / slice.latitudeSlices)), result = o.request(self._paper, self.options.zoom, maxZoom, regionLowerLeft, regionUpperRight);
                    if (result) {
                        region.items = result.items;
                        if (result.items) {
                            maps.wijitemslayer._setItemsData(result.items);
                        }
                    }
                });

                self._relayout();
            };

            wijvirtuallayer.prototype._relayout = function () {
                var self = this, o = self.options, converter = o.converter;
                maps.wijitemslayer._relayoutRegions(converter, self._visibleRegions);
            };

            wijvirtuallayer.prototype._removeRegion = function (region) {
                if (region.items) {
                    $.each(region.items, function (index, item) {
                        item.elements.remove();
                    });
                }
            };

            wijvirtuallayer.prototype._clear = function () {
                var self = this;
                self._visibleRegions = [];
                if (self._paper) {
                    self._paper.clear();
                }
            };

            wijvirtuallayer.prototype._getMatchedSlice = function () {
                var self = this;
                if (!self._slices)
                    return null;

                var len = self._slices.length, i, slice;
                for (i = 0; i < len; i++) {
                    slice = self._slices[i];
                    if (slice.zoom <= self.options.zoom) {
                        return slice;
                    }
                }

                return null;
            };

            wijvirtuallayer.prototype._sortSlices = function (slices) {
                if (!slices)
                    return [];

                return slices.sort(function (a, b) {
                    return -(a.zoom - b.zoom);
                });
            };

            wijvirtuallayer.prototype._getLogicBounds = function () {
                var self = this, converter = self.options.converter, location = converter.viewToLogic(new maps.Point(0, 0)), size = converter.getLogicSize();
                return new maps.Rectangle(location, size);
            };

            /**
            * Force to request the data to get the newest one.
            */
            wijvirtuallayer.prototype.refresh = function () {
                this._refreshLayer();
                _super.prototype.refresh.call(this);
            };

            /**
            * Removes the wijvirtuallayer functionality completely. This will return the element back to its pre-init state.
            */
            wijvirtuallayer.prototype.destroy = function () {
                var self = this;
                if (self._paper)
                    self._paper.remove();
                self._container.remove();

                _super.prototype.destroy.call(this);
            };
            return wijvirtuallayer;
        })(maps.wijlayer);
        maps.wijvirtuallayer = wijvirtuallayer;

        

        

        

        /**
        * Represents the options for the wijvirtuallayer.
        */
        var wijvirtuallayer_options = (function (_super) {
            __extends(wijvirtuallayer_options, _super);
            function wijvirtuallayer_options() {
                _super.apply(this, arguments);
                /**
                * Specifies how the map is partitioned for virtualization.
                * @remarks Each slice defines a set of regions this virtual layer will get items form when needed.
                * The minimum zoom of a slice is the value value of it's <b>zoom</b> property,
                * while the maximum zoom is the value from the <b>zoom</b> property of the next slice.
                * Each slice divides the map in a uniform grid of regions according to the current projection.
                */
                this.slices = [];
            }
            return wijvirtuallayer_options;
        })(maps.wijlayer_options);
        maps.wijvirtuallayer_options = wijvirtuallayer_options;

        wijvirtuallayer.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijvirtuallayer_options());

        $.wijmo.registerWidget("wijvirtuallayer", wijvirtuallayer.prototype);
    })(wijmo.maps || (wijmo.maps = {}));
    var maps = wijmo.maps;
})(wijmo || (wijmo = {}));

var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /// <reference path="wijvirtuallayer.ts" />
    ///<reference path="Drawing.ts"/>
    ///<reference path="Utils.ts"/>
    ///<reference path="wijlayer.ts"/>
    /// <reference path="../../Base/jquery.wijmo.widget.ts" />
    /// <reference path="../../wijutil/jquery.wijmo.raphael.ts"/>
    (function (maps) {
        var $ = jQuery, layerContainerCss = "wijmo-wijmaps-layercontainer";

        

        /**
        * @ignore
        * Defines slice info on specific zoom. Used by virtual layer.
        */
        var MapSlice = (function () {
            /**
            * @param {number} latitudeSlices The number of latitude divisions for this slice.
            * @param {number} longitudeSlices The number of longitude divisions for this slice.
            * @param {number} zoom The minimum zoom of this slice.
            */
            function MapSlice(latitudeSlices, longitudeSlices, zoom) {
                this.latitudeSlices = latitudeSlices;
                this.longitudeSlices = longitudeSlices;
                this.zoom = zoom;
            }
            return MapSlice;
        })();
        maps.MapSlice = MapSlice;

        /** @ignore */
        var Region = (function () {
            function Region(slice, longitude, latitude) {
                this.slice = slice;
                this.longitude = longitude;
                this.latitude = latitude;
            }
            Region.prototype.equals = function (that) {
                var self = this;
                return self.slice === that.slice && self.longitude === that.longitude && self.latitude === that.latitude;
            };
            return Region;
        })();
        maps.Region = Region;

        /**
        * @widget
        * The items layer for the wijmaps. Display its items positioned geographically.
        */
        var wijitemslayer = (function (_super) {
            __extends(wijitemslayer, _super);
            function wijitemslayer() {
                _super.apply(this, arguments);
            }
            /** @ignore */
            wijitemslayer.prototype._create = function () {
                var self = this;

                self._container = $("<div class=\"" + layerContainerCss + "\"></div>");
                self.element.append(self._container);
                self._paper = self._createPaper(self._container[0], self.options.converter.getViewSize());
                _super.prototype._create.call(this);

                self._setRequest(self.options.request);
            };

            /** @ignore */
            wijitemslayer.prototype._setOption = function (key, value) {
                var self = this, o = this.options;
                if (o[key] !== value) {
                    switch (key) {
                        case 'request':
                            self._setRequest(value);
                            return;
                    }
                }
                _super.prototype._setOption.call(this, key, value);
            };

            wijitemslayer.prototype._setRequest = function (request) {
                var self = this;

                self.options.request = request;
                self._clear();
                if (request) {
                    var result = request(self._paper);
                    if (result) {
                        var region = new Region(new MapSlice(1, 1, 0), 0, 0);
                        region.items = result.items;
                        wijitemslayer._setItemsData(result.items);
                        self._visibleRegions = [region];
                    }
                }
                self.update();
            };

            /** @ignore */
            wijitemslayer.prototype._render = function () {
                var self = this, converter = self.options.converter;
                self._resizePaper(self._paper, converter.getViewSize());
                wijitemslayer._relayoutRegions(self.options.converter, self._visibleRegions);
            };

            wijitemslayer.prototype._clear = function () {
                var self = this;
                self._visibleRegions = null;
                if (self._paper) {
                    self._paper.clear();
                }
            };

            /** @ignore */
            wijitemslayer._relayoutRegions = function (converter, regions) {
                if (!regions)
                    return;

                var viewSize = converter.getViewSize(), scale = viewSize.width / converter.getLogicSize().width, center = converter.getLogicCenter(), offsetX = viewSize.width / 2 - center.x * scale, offsetY = viewSize.height / 2 - center.y * scale;

                $.each(regions, function (regionIndex, region) {
                    if (region.items) {
                        $.each(region.items, function (itemIndex, item) {
                            if (item.elements) {
                                var logicLocation = converter.geographicToLogic(item.location), itemLeft = logicLocation.x * scale + offsetX - ((!!item.pinpoint) ? item.pinpoint.x : 0), itemTop = logicLocation.y * scale + offsetY - ((!!item.pinpoint) ? item.pinpoint.y : 0), translate = "t" + itemLeft + "," + itemTop;
                                $.each(item.elements, function (elementIndex, element) {
                                    element.transform(element.data("wijmo-transform") + translate);
                                });
                            }
                        });
                    }
                });
            };

            /** @ignore */
            wijitemslayer._setItemsData = function (items) {
                if (items) {
                    $.each(items, function (itemIndex, item) {
                        if (item.elements) {
                            $.each(item.elements, function (elementIndex, element) {
                                element.data("wijmo-transform", element.transform());
                            });
                        }
                    });
                }
            };

            /**
            * Force to request the data to get the newest one.
            */
            wijitemslayer.prototype.refresh = function () {
                var self = this;
                self._setRequest(self.options.request);

                _super.prototype.refresh.call(this);
            };

            /**
            * Removes the wijitemslayer functionality completely. This will return the element back to its pre-init state.
            */
            wijitemslayer.prototype.destroy = function () {
                var self = this;
                if (self._paper)
                    self._paper.remove();
                self._container.remove();

                _super.prototype.destroy.call(this);
            };
            return wijitemslayer;
        })(maps.wijlayer);
        maps.wijitemslayer = wijitemslayer;

        

        

        

        /**
        * The options of the wijitemslayer.
        */
        var wijitemslayer_options = (function (_super) {
            __extends(wijitemslayer_options, _super);
            function wijitemslayer_options() {
                _super.apply(this, arguments);
            }
            return wijitemslayer_options;
        })(maps.wijlayer_options);
        maps.wijitemslayer_options = wijitemslayer_options;

        wijitemslayer.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijitemslayer_options());

        $.wijmo.registerWidget("wijitemslayer", wijitemslayer.prototype);
    })(wijmo.maps || (wijmo.maps = {}));
    var maps = wijmo.maps;
})(wijmo || (wijmo = {}));

/// <reference path="../../wijslider/jquery.wijmo.wijslider.ts" />
/// <reference path="CoordConverter.ts" />
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    (function (maps) {
        var $ = jQuery, defSpeed = 0.5, defMinPixels = 20, defMaxPixels = 158, css = {
            layerContainerCss: "wijmo-wijmaps-layercontainer",
            toolsLayerCss: "wijmo-wijmaps-toolslayer",
            panCss: "wijmo-wijmaps-pan",
            panpointCss: "wijmo-wijmaps-panpoint",
            zoomCss: "wijmo-wijmaps-zoomer",
            scaleCss: "wijmo-wijmaps-scaler",
            scaleLableCss: "wijmo-wijmaps-content",
            scaleValueCss: "wijmo-wijmaps-scalervalue"
        };

        /**
        * @widget
        * @ignore
        * The tools layer for wijmaps.
        */
        var wijtoolslayer = (function (_super) {
            __extends(wijtoolslayer, _super);
            function wijtoolslayer() {
                _super.apply(this, arguments);
            }
            /** @ignore */
            wijtoolslayer.prototype._create = function () {
                var self = this;
                self.element.addClass(css.toolsLayerCss);

                self._on(self.element, {
                    "dblclick": function (event, data) {
                        event.stopPropagation();
                    }
                });

                self._speed = defSpeed;
                self._isPanning = false;
                self._createPanPanel();
                self._createZoomPanel();
                self._createScalePanel();
            };

            wijtoolslayer.prototype._innerDisable = function () {
                _super.prototype._innerDisable.call(this);
                this._handleDisabledOption(true);
            };

            wijtoolslayer.prototype._innerEnable = function () {
                _super.prototype._innerEnable.call(this);
                this._handleDisabledOption(false);
            };

            wijtoolslayer.prototype._handleDisabledOption = function (disabled) {
                var self = this, options = { disabled: disabled };

                if (self._zoomSlider) {
                    self._zoomSlider.wijslider(options);
                }
            };

            /** @ignore */
            wijtoolslayer.prototype._setOption = function (key, value) {
                var self = this, o = this.options;
                if (o[key] !== value) {
                    switch (key) {
                        case 'center':
                            self._setCenter(value);
                            return;
                        case 'zoom':
                            self._setZoom(value);
                            return;
                    }
                }
                _super.prototype._setOption.call(this, key, value);
            };

            wijtoolslayer.prototype._setCenter = function (center) {
                var self = this, o = self.options;
                o.center = center;
                self._updateScalePanel();
            };

            wijtoolslayer.prototype._setZoom = function (zoom) {
                var self = this, o = self.options;
                o.zoom = zoom;
                self._zoomSlider.wijslider({ orientation: "vertical", range: false, min: o.minZoom, max: o.maxZoom, step: 1, value: o.zoom, values: null });
                self._updateScalePanel();
            };

            wijtoolslayer.prototype._createPanPanel = function () {
                var self = this, o = self.options, e = self.element, offsetX, offsetY, leftArrow, rightArrow, upArrow, downArrow, hOffset, vOffset;

                self._panPanel = $("<div class=\"" + css.panCss + " " + o.wijCSS.stateDefault + "\"></div>").appendTo(e);
                self._on(self._panPanel, {
                    "mousedown": function (event, data) {
                        self._isPanning = true;
                        self._startPanning(self._panPanel, self._getPanPointOffset(self._panPanel, new maps.Point(event.pageX, event.pageY)));
                        $(document).disableSelection();
                        event.stopPropagation();
                    },
                    "dragstart": function (event, data) {
                        //prevent image being dragged in firefox.
                        event.preventDefault();
                    },
                    "selectstart": function (event, data) {
                        //prevent image is selected in ie.
                        event.preventDefault();
                    }
                });

                self._on($(document), {
                    "mouseup": function (event, data) {
                        self._isPanning = false;
                        self._stopPanning();
                        $(document).enableSelection();
                    },
                    "mousemove": function (event, data) {
                        if (self._isPanning) {
                            self._startPanning(self._panPanel, self._getPanPointOffset(self._panPanel, new maps.Point(event.pageX, event.pageY)));
                        }
                    }
                });

                self._panPoint = $("<div class=\"" + css.panpointCss + " " + o.wijCSS.content + " " + o.wijCSS.stateActive + "\"></div>").hide().appendTo(e);

                leftArrow = $("<div class=\"" + o.wijCSS.icon + " " + o.wijCSS.iconArrowLeft + "\"></div>");
                rightArrow = $("<div class=\"" + o.wijCSS.icon + " " + o.wijCSS.iconArrowRight + "\"></div>");
                upArrow = $("<div class=\"" + o.wijCSS.icon + " " + o.wijCSS.iconArrowUp + "\"></div>");
                downArrow = $("<div class=\"" + o.wijCSS.icon + " " + o.wijCSS.iconArrowDown + "\"></div>");

                self._panPanel.append(leftArrow, rightArrow, upArrow, downArrow);
            };

            wijtoolslayer.prototype._getPanPointOffset = function (panPanel, panPoint) {
                var panPanelOffset = panPanel.offset();
                return panPoint.offset(-panPanelOffset.left, -panPanelOffset.top);
            };

            wijtoolslayer.prototype._startPanning = function (target, position) {
                var self = this, o = self.options, viewCenter = o.converter.getViewCenter(), panPanelCenter = new maps.Point(target.outerWidth() / 2, target.outerHeight() / 2), panOffset = position.offset(-panPanelCenter.x, -panPanelCenter.y), length = Math.sqrt(Math.pow(panOffset.x, 2) + Math.pow(panOffset.y, 2)), panPointPosition = new maps.Point(position.x, position.y), newCenter;

                if (self._panningTimer) {
                    clearInterval(self._panningTimer);
                }
                self._panningTimer = setInterval(function () {
                    newCenter = o.converter.viewToGeographic(new maps.Point(panOffset.scale(self._speed, self._speed)).offset(viewCenter.x, viewCenter.y));
                    self._trigger("targetCenterChanged", null, { "targetCenter": newCenter });
                }, 20);

                if (length > panPanelCenter.x) {
                    panPointPosition = panPanelCenter.scale(panOffset.x / length, panOffset.y / length).offset(panPanelCenter.x, panPanelCenter.y);
                }
                panPointPosition = panPointPosition.offset(target.position().left, target.position().top);
                self._panPoint.css("left", panPointPosition.x - self._panPoint.width() / 2).css("top", panPointPosition.y - self._panPoint.height() / 2).show();
            };

            wijtoolslayer.prototype._stopPanning = function () {
                var self = this;
                if (self._panningTimer) {
                    clearInterval(self._panningTimer);
                }
                self._panPoint.hide();
            };

            wijtoolslayer.prototype._createZoomPanel = function () {
                var self = this, o = self.options, e = self.element;
                self._zoomSlider = $("<div></div>").css("height", "100%").css("font-size", "13px"); // need refactor. set it to 13px to make the sliding block align center.
                self._zoomPanel = $("<div class=\"" + css.zoomCss + "\"></div>").append(self._zoomSlider);
                e.append(self._zoomPanel);
                self._zoomSlider.wijslider({ orientation: "vertical", range: false, min: o.minZoom, max: o.maxZoom, step: 1, value: o.zoom, values: null });

                self._on(self._zoomPanel, {
                    "mousedown": function (event, data) {
                        event.stopPropagation();
                    }
                });
                self._on(true, self._zoomPanel, {
                    "wijsliderchange": function (event, data) {
                        self._trigger("targetZoomChanged", null, { "targetZoom": data.value });
                    }
                });
            };

            wijtoolslayer.prototype._createScalePanel = function () {
                var self = this, o = self.options, e = self.element;
                self._scalePanel = $("<div class=\"" + css.scaleCss + " " + o.wijCSS.content + "\"></div>").appendTo(e);
                self._on(self._scalePanel, {
                    "mousedown": function (event, data) {
                        event.stopPropagation();
                    },
                    "dblclick": function (event, data) {
                        event.stopPropagation();
                    }
                });

                self._metersLabel = $("<span class=\"" + css.scaleLableCss + "\"></span>");
                self._milesLabel = $("<span class=\"" + css.scaleLableCss + "\"></span>");
                self._metersValue = $("<span class=\"" + css.scaleValueCss + " " + o.wijCSS.stateDefault + "\"></span>");
                self._milesValue = $("<span class=\"" + css.scaleValueCss + " " + o.wijCSS.stateDefault + "\"></span>");

                self._scalePanel.append(self._metersLabel, self._metersValue, $("<br />"), self._milesLabel, self._milesValue);
                self._updateScalePanel();
            };

            wijtoolslayer.prototype._updateScalePanel = function () {
                var self = this;
                self._updateScale(self._metersValue, self._metersLabel, 1, 1000, "km", "m");
                self._updateScale(self._milesValue, self._milesLabel, 3.2808399, 5280, "mi", "ft");
            };

            wijtoolslayer.prototype._updateScale = function (scale, label, meterToUnit, largeToSmall, largeUnit, unit) {
                if (scale) {
                    var self = this, o = self.options, minPixels = defMinPixels, maxPixels = defMaxPixels, minDistance = self._getDistance(minPixels) * meterToUnit, maxDistance = self._getDistance(maxPixels) * meterToUnit;

                    var roundest = self._roundest(Math.floor(minDistance), Math.floor(maxDistance));
                    if (roundest.toString().length <= Math.ceil(Math.LOG10E * Math.log(largeToSmall))) {
                        if (label)
                            label.text(roundest + " " + unit);
                    } else {
                        minDistance /= largeToSmall;
                        maxDistance /= largeToSmall;
                        roundest = self._roundest(Math.floor(minDistance), Math.floor(maxDistance));
                        if (label)
                            label.text(roundest + " " + largeUnit);
                    }
                }

                var alpha = (roundest - minDistance) * 1.0 / (maxDistance - minDistance);
                scale.width(Math.max(minPixels * (1 - alpha) + maxPixels * alpha, 0));
            };

            // returns the distance in meters from the center of the map to a point 'pixels' pixels to the right
            wijtoolslayer.prototype._getDistance = function (pixels) {
                var self = this, o = self.options;
                return o.converter.distance(o.center, o.converter.viewToGeographic(new maps.Point(o.converter.getViewCenter()).offset(o.center.x < 0 ? pixels : -pixels, 0)));
            };

            // returns the largest number with more trailing zeros between min and max
            wijtoolslayer.prototype._roundest = function (min, max) {
                var self = this, maxs = max.toString(), mins = min.toString();

                for (var i = 0; i < maxs.length; ++i) {
                    if (maxs.length > mins.length || maxs[i] != mins[i]) {
                        return parseInt(self._padRight(maxs.substring(0, i + 1), maxs.length, '0'));
                    }
                }
                return max;
            };

            wijtoolslayer.prototype._padRight = function (str, totalWidth, paddingChar) {
                if (str.length < totalWidth) {
                    var i, paddingString = new String();
                    for (i = 1; i <= (totalWidth - str.length); i++) {
                        paddingString += paddingChar;
                    }
                    return (str + paddingString);
                } else {
                    return str;
                }
            };

            /**
            * Removes the wijtoolslayer functionality completely. This will return the element back to its pre-init state.
            */
            wijtoolslayer.prototype.destroy = function () {
                var self = this;
                $(document).off("." + self.widgetName);
                self._panPanel.remove();
                self._zoomSlider.wijslider("destroy").remove();
                self._panPanel.off("." + self.widgetName).remove();
                self._zoomPanel.off("." + self.widgetName).remove();
                self._scalePanel.off("." + self.widgetName).remove();
                self.element.removeClass(css.toolsLayerCss).off("." + self.widgetName);
                _super.prototype.destroy.call(this);
            };
            return wijtoolslayer;
        })(wijmo.wijmoWidget);
        maps.wijtoolslayer = wijtoolslayer;

        /**
        * @ignore
        * The options for wijtoolslayer.
        */
        var wijtoolslayer_options = (function () {
            function wijtoolslayer_options() {
            }
            return wijtoolslayer_options;
        })();
        maps.wijtoolslayer_options = wijtoolslayer_options;

        wijtoolslayer.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijtoolslayer_options());

        $.wijmo.registerWidget("wijtoolslayer", wijtoolslayer.prototype);
    })(wijmo.maps || (wijmo.maps = {}));
    var maps = wijmo.maps;
})(wijmo || (wijmo = {}));

var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    /// <reference path="mapsources.ts" />
    /// <reference path="drawing.ts" />
    /// <reference path="../../Base/jquery.wijmo.widget.ts" />
    (function (maps) {
        var $ = jQuery, tileCss = "wijmo-wijmaps-tile";

        /**
        * @widget
        * The tile layer for wijmaps. Draw the map tiles.
        */
        var wijmultiscaleimage = (function (_super) {
            __extends(wijmultiscaleimage, _super);
            function wijmultiscaleimage() {
                _super.apply(this, arguments);
            }
            /** @ignore */
            wijmultiscaleimage.prototype._create = function () {
                var self = this, o = self.options;
                self._tileItems = {};
                self._tileScale = self._getTileScale(Math.round(o.zoom), o.zoom);
                self._renderTiles();
            };

            /** @ignore */
            wijmultiscaleimage.prototype._setOption = function (key, value) {
                var self = this, o = self.options;
                if (o[key] !== value) {
                    switch (key) {
                        case 'center':
                            self._setCenter(value);
                            return;
                        case 'zoom':
                            self._setZoom(value);
                            return;
                        case 'source':
                            self._setSource(value);
                            return;
                    }
                }
                _super.prototype._setOption.call(this, key, value);
            };

            wijmultiscaleimage.prototype._setCenter = function (center) {
                var self = this, o = self.options, offset = new maps.Size(center.x - o.center.x, center.y - o.center.y);

                self._offsetTiles(offset);
                o.center = center;
                self._renderTiles();
            };

            wijmultiscaleimage.prototype._setZoom = function (zoom) {
                var self = this, o = self.options, oldZoom = o.zoom, curZoom, roundZoom;
                if (zoom >= o.source.minZoom && zoom <= o.source.maxZoom) {
                    self._tileScale = self._getTileScale(Math.round(zoom), zoom);

                    //scale old tiles to target zoom.
                    self._scaleTiles(self._getTileScale(oldZoom, zoom));

                    //render new tiles by target zoom.
                    o.zoom = zoom;
                    setTimeout(function () {
                        self._renderTiles();
                    }, 10); //make the zooming more smooth.
                }
            };

            wijmultiscaleimage.prototype._setSource = function (source) {
                var self = this, o = self.options;
                o.source = source;
                $.each(self._tileItems, function (key, val) {
                    val.img.remove();
                    delete self._tileItems[key];
                });
                self._renderTiles();
            };

            wijmultiscaleimage.prototype._offsetTiles = function (offset) {
                var self = this, fullSize = self._getViewFullSize();
                $.each(self._tileItems, function (key, val) {
                    val.bounds.location = new maps.Point(val.bounds.location).offset(-offset.width * fullSize.width, -offset.height * fullSize.height);
                    val.img.css("left", val.bounds.location.x).css("top", val.bounds.location.y);
                });
            };

            wijmultiscaleimage.prototype._getTileScale = function (baseZoom, targetZoom) {
                return Math.pow(2, targetZoom - baseZoom);
            };

            wijmultiscaleimage.prototype._scaleTiles = function (scale) {
                var self = this, viewSize = self._getViewSize(), viewRect = new maps.Rectangle(new maps.Point(0, 0), viewSize);
                $.each(self._tileItems, function (key, val) {
                    val.bounds.location.x = viewSize.width / 2 - (viewSize.width / 2 - val.bounds.location.x) * scale;
                    val.bounds.location.y = viewSize.height / 2 - (viewSize.height / 2 - val.bounds.location.y) * scale;
                    val.bounds.size = new maps.Size(val.bounds.size).scale(scale, scale);

                    if (viewRect.intersect(val.bounds)) {
                        val.img.css("left", val.bounds.location.x).css("top", val.bounds.location.y).css("width", val.bounds.size.width).css("height", val.bounds.size.height);
                    } else {
                        val.img.remove();
                        delete self._tileItems[key];
                    }
                });
            };

            wijmultiscaleimage.prototype._renderTiles = function () {
                var self = this, o = self.options, baseZoom = Math.round(o.zoom), leftTopTileItem = self._getLeftTopTileItem(), viewSize = self._getViewSize(), tileSize = self._getTileSize(), maxTileCount = self._getMaxTileCount(o.zoom), maxHorizontalTileCount = maxTileCount - leftTopTileItem.columnIndex, maxVerticalTileCount = maxTileCount - leftTopTileItem.rowIndex, horizontalTileCount = Math.min(maxHorizontalTileCount, Math.ceil((viewSize.width - leftTopTileItem.bounds.location.x) / tileSize.width)), verticalTileCount = Math.min(maxVerticalTileCount, Math.ceil((viewSize.height - leftTopTileItem.bounds.location.y) / tileSize.height)), left, top, rowIndex, columnIndex, tile, oldTiles = $.extend({}, self._tileItems), preLoadTiles = [];

                for (rowIndex = leftTopTileItem.rowIndex; rowIndex < leftTopTileItem.rowIndex + verticalTileCount; rowIndex++) {
                    for (columnIndex = leftTopTileItem.columnIndex; columnIndex < leftTopTileItem.columnIndex + horizontalTileCount; columnIndex++) {
                        left = leftTopTileItem.bounds.location.x + tileSize.width * (columnIndex - leftTopTileItem.columnIndex);
                        top = leftTopTileItem.bounds.location.y + tileSize.height * (rowIndex - leftTopTileItem.rowIndex);
                        tile = new TileItem(columnIndex, rowIndex, new maps.Rectangle(new maps.Point(left, top), new maps.Size(tileSize.width, tileSize.height)), baseZoom);
                        self._renderTile(tile, baseZoom, oldTiles, preLoadTiles);
                    }
                }
            };

            wijmultiscaleimage.prototype._renderTile = function (tile, baseZoom, oldTiles, preLoadTiles) {
                var self = this, o = self.options, location = tile.bounds.location, size = tile.bounds.size, style, tileUrl, oldTile, img, tileItemKey = "tile_" + tile.columnIndex + "_" + tile.rowIndex + "_" + tile.zoomLevel;

                if (!self._tileItems[tileItemKey]) {
                    self._tileItems[tileItemKey] = tile;
                    tileUrl = o.source.getUrl(tile.zoomLevel, tile.columnIndex, tile.rowIndex);
                    style = "left:" + location.x + "px; top:" + location.y + "px; width:" + size.width + "px; height:" + size.height + "px; display:none";
                    tile.img = $("<img class=\"" + tileCss + "\" style=\"" + style + "\" src=\"" + tileUrl + "\"></img>");
                    preLoadTiles.push(tileItemKey);
                    tile.img.one("load.wijmultiscaleimage", function (event, data) {
                        self._onTileLoad(tile.img, tileItemKey, baseZoom, oldTiles, preLoadTiles);
                    });
                    self.element.append(tile.img);
                } else {
                    oldTile = self._tileItems[tileItemKey];
                    oldTile.bounds = tile.bounds;
                    oldTile.img.css("left", location.x).css("top", location.y).css("width", size.width).css("height", size.height);
                    self.element.append(oldTile.img);
                }
            };

            wijmultiscaleimage.prototype._onTileLoad = function (tileImg, tileItemKey, baseZoom, oldTiles, preLoadTiles) {
                var self = this, o = self.options;
                tileImg.fadeIn(600, function () {
                    preLoadTiles.splice($.inArray(tileItemKey, preLoadTiles), 1);
                    if (preLoadTiles.length == 0) {
                        $.each(oldTiles, function (key, val) {
                            if (self._isUselessTile(val, baseZoom)) {
                                val.img.remove();

                                // need refactor. sometimes the remove method has no effect.
                                if ($("img[src='" + val.img.attr("src") + "']").length == 0) {
                                    delete oldTiles[key];
                                    delete self._tileItems[key];
                                }
                            }
                        });
                    }
                });
            };

            wijmultiscaleimage.prototype._isUselessTile = function (tile, baseZoom) {
                var self = this, o = self.options, curBaseZoom = Math.round(o.zoom), viewRect = new maps.Rectangle(maps.Point.empty, self._getViewSize()), intersectRect = viewRect.intersect(tile.bounds);

                if (tile.zoomLevel === baseZoom || tile.zoomLevel === curBaseZoom) {
                    return !intersectRect;
                }
                return true;
            };

            wijmultiscaleimage.prototype._isPointInRect = function (p, rect) {
                return p.x >= rect.location.x && p.x <= rect.location.x + rect.size.width && p.y >= rect.location.y && p.y <= rect.location.y + rect.size.height;
            };

            wijmultiscaleimage.prototype._getLeftTopTileItem = function () {
                var self = this, o = self.options, maxTileCount = self._getMaxTileCount(o.zoom), centerTileLocation = new maps.Point(o.center).scale(maxTileCount, maxTileCount), tileSize = self._getTileSize(), viewSize = self._getViewSize(), tileRowIndex = Math.floor(centerTileLocation.y), tileColumnIndex = Math.floor(centerTileLocation.x), tilePosition = self._getViewCenter().offset(-(centerTileLocation.x % 1) * tileSize.width, -(centerTileLocation.y % 1) * tileSize.height);

                while (tileColumnIndex > 0 && tilePosition.x > 0) {
                    tileColumnIndex -= 1;
                    tilePosition.x -= tileSize.width;
                }
                while (tileRowIndex > 0 && tilePosition.y > 0) {
                    tileRowIndex -= 1;
                    tilePosition.y -= tileSize.height;
                }

                return new TileItem(tileColumnIndex, tileRowIndex, new maps.Rectangle(tilePosition, tileSize), Math.round(o.zoom));
            };

            wijmultiscaleimage.prototype._getTileSize = function () {
                var self = this, o = self.options;
                return new maps.Size(o.source.tileWidth, o.source.tileHeight).scale(self._tileScale, self._tileScale);
            };

            wijmultiscaleimage.prototype._getMaxTileCount = function (zoom) {
                return Math.pow(2, Math.round(zoom));
            };

            wijmultiscaleimage.prototype._getViewSize = function () {
                var self = this;
                return new maps.Size(self.element.width(), self.element.height());
            };

            wijmultiscaleimage.prototype._getViewCenter = function () {
                var self = this, viewSize = self._getViewSize();
                return new maps.Point(viewSize.width / 2, viewSize.height / 2);
            };

            wijmultiscaleimage.prototype._getViewFullSize = function () {
                var self = this, o = self.options, scaledTileCount = Math.pow(2, o.zoom);
                return new maps.Size(o.source.tileWidth, o.source.tileHeight).scale(scaledTileCount, scaledTileCount);
            };

            /**
            * Removes the wijmultiscaleimage functionality completely. This will return the element back to its pre-init state.
            */
            wijmultiscaleimage.prototype.destroy = function () {
                this.element.children().remove();
                _super.prototype.destroy.call(this);
            };
            return wijmultiscaleimage;
        })(wijmo.wijmoWidget);
        maps.wijmultiscaleimage = wijmultiscaleimage;

        /** @ignore */
        var TileItem = (function () {
            function TileItem(columnIndex, rowIndex, bounds, zoomLevel, img) {
                this.columnIndex = columnIndex;
                this.rowIndex = rowIndex;
                this.bounds = bounds;
                this.zoomLevel = zoomLevel;
                this.img = img;
            }
            return TileItem;
        })();

        /**
        * The options of wijmultiscaleimage.
        */
        var wijmultiscaleimage_options = (function () {
            function wijmultiscaleimage_options() {
                /**
                * The current center of the layer, in geographic unit.
                */
                this.center = new maps.Point(0, 0);
                /**
                * The current zoom level of the layer.
                */
                this.zoom = 3;
            }
            return wijmultiscaleimage_options;
        })();
        maps.wijmultiscaleimage_options = wijmultiscaleimage_options;

        wijmultiscaleimage.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijmultiscaleimage_options());

        $.wijmo.registerWidget("wijmultiscaleimage", wijmultiscaleimage.prototype);
    })(wijmo.maps || (wijmo.maps = {}));
    var maps = wijmo.maps;
})(wijmo || (wijmo = {}));

/// <reference path="MapSources.ts" />
/// <reference path="wijlayer.ts" />
/// <reference path="CoordConverter.ts" />
/// <reference path="../../Base/jquery.wijmo.widget.ts" />
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};

var wijmo;
(function (wijmo) {
    (function (maps) {
        var $ = jQuery, defMinZoom = 1, defMaxZoom = 20, defTileWidth = 256, defTileHeight = 256, wijmapsCss = "wijmo-wijmaps", containerCss = "wijmo-wijmaps-container", tilesContainerCss = "wijmo-wijmaps-tileslayer", layerContainerCss = "wijmo-wijmaps-layercontainer";

        /** @widget */
        var wijmaps = (function (_super) {
            __extends(wijmaps, _super);
            function wijmaps() {
                _super.apply(this, arguments);
            }
            /** @ignore */
            wijmaps.prototype._create = function () {
                var self = this, o = self.options;
                self._setInnerSource(o.source, function () {
                    self._createMaps();
                });
                _super.prototype._create.call(this);
            };

            wijmaps.prototype._createMaps = function () {
                var self = this, e = self.element, o = self.options, offsetX, offsetY, targetZoom, targetCenter, leftTopGeographicCoord, rightBottomGeographicCoord;
                e.addClass(wijmapsCss);
                e.addClass(o.wijCSS.content);
                e.attr("tabindex", -1);

                self._isPanning = false;
                self._isZooming = false;
                self._isCenterChanging = false;
                self._keyCode = wijmo.getKeyCodeEnum();

                if (self._innerSource) {
                    self._minZoom = self._innerSource.minZoom;
                    self._maxZoom = self._innerSource.maxZoom;
                    self._coordConverter = new maps.CoordConverter(e, new maps.Point(o.center.x, o.center.y), o.zoom, self._innerSource.tileWidth, self._innerSource.tileHeight);
                } else {
                    self._minZoom = defMinZoom;
                    self._maxZoom = defMaxZoom;
                    self._coordConverter = new maps.CoordConverter(e, new maps.Point(o.center.x, o.center.y), o.zoom, defTileWidth, defTileHeight);
                }

                if (!o.targetCenter) {
                    o.targetCenter = $.extend({}, o.center);
                }

                if (o.targetZoom === undefined) {
                    o.targetZoom = o.zoom;
                }

                self._createLayers();

                if (o.targetZoom !== o.zoom) {
                    targetZoom = o.targetZoom;
                    o.targetZoom = o.zoom;
                    self._setTargetZoom(targetZoom);
                }

                if (o.targetCenter.x !== o.center.x || o.targetCenter.y !== o.center.y) {
                    targetCenter = o.targetCenter;
                    o.targetCenter = o.center;
                    self._setTargetCenter(targetCenter);
                }

                self._on(e, {
                    "dragstart": function (event, data) {
                        //prevent image being dragged in firefox.
                        event.preventDefault();
                    },
                    "selectstart": function (event, data) {
                        //prevent image is selected in ie.
                        event.preventDefault();
                    },
                    "mousewheel": function (event, data) {
                        var position = new maps.Point(event.pageX - e.offset().left, event.pageY - e.offset().top);
                        if (data > 0) {
                            self._zoomIn(position);
                        } else {
                            self._zoomOut(position);
                        }
                        event.preventDefault();
                    },
                    "dblclick": function (event, data) {
                        var position = new maps.Point(event.pageX - e.offset().left, event.pageY - e.offset().top);
                        self._zoomIn(position);
                    },
                    "mousedown": function (event, data) {
                        e.focus();
                        self._isPanning = true;
                        self._panningStartPosition = new maps.Point(event.pageX, event.pageY);
                        $(document).disableSelection();
                    },
                    "keydown": function (event, data) {
                        if (self._onKeyDown(event)) {
                            event.preventDefault();
                        }
                    },
                    "keypress": function (event, data) {
                        if (self._onKeyPress(event)) {
                            event.preventDefault();
                        }
                    }
                });

                self._on($(document), {
                    "mouseup": function (event, data) {
                        self._isPanning = false;
                        $(document).enableSelection();
                    },
                    "mousemove": function (event, data) {
                        if (self._isPanning) {
                            offsetX = self._panningStartPosition.x - event.pageX;
                            offsetY = self._panningStartPosition.y - event.pageY;
                            self._panningStartPosition = new maps.Point(event.pageX, event.pageY);
                            self._panning(offsetX, offsetY);
                        }
                    }
                });
            };

            wijmaps.prototype._innerDisable = function () {
                _super.prototype._innerDisable.call(this);
                this._handleDisabledOption(true);
            };

            wijmaps.prototype._innerEnable = function () {
                _super.prototype._innerEnable.call(this);
                this._handleDisabledOption(false);
            };

            wijmaps.prototype._handleDisabledOption = function (disabled) {
                var self = this, o = self.options, layers = self._layers, options = { disabled: disabled };

                if (layers) {
                    $.each(layers, function (key, item) {
                        item.element[item.wijname](options);
                    });
                }

                if (self._innerSource) {
                    self._multiScaleImageContainer.wijmultiscaleimage(options);
                }

                if (o.showTools) {
                    self._toolsLayerContainer.wijtoolslayer(options);
                }

                if (disabled) {
                    self._disabledCover.show();
                } else {
                    self._disabledCover.hide();
                }
            };

            /** @ignore */
            wijmaps.prototype._setOption = function (key, value) {
                var self = this, o = this.options;
                if (o[key] !== value) {
                    switch (key) {
                        case 'center':
                            self._setCenter(value);
                            return;
                        case 'targetCenter':
                            self._setTargetCenter(value);
                            return;
                        case 'zoom':
                            self._setZoom(value);
                            return;
                        case 'targetZoom':
                            self._setTargetZoom(value);
                            return;
                        case 'layers':
                            self._setLayers(value);
                            return;
                        case 'showTools':
                            self._setShowTools(value);
                            return;
                        case 'source':
                            self._setSource(value);
                            return;
                    }
                }
                _super.prototype._setOption.call(this, key, value);
            };

            wijmaps.prototype._setInnerSource = function (source, callback) {
                var self = this, o = self.options, isBingMapsSource;

                switch (source) {
                    case "bingMapsRoadSource":
                        self._innerSource = maps.MapSource.bingMapsRoadSource;
                        isBingMapsSource = true;
                        break;
                    case "bingMapsAerialSource":
                        self._innerSource = maps.MapSource.bingMapsAerialSource;
                        isBingMapsSource = true;
                        break;
                    case "bingMapsHybridSource":
                        self._innerSource = maps.MapSource.bingMapsHybridSource;
                        isBingMapsSource = true;
                        break;
                    default:
                        self._innerSource = source;
                        isBingMapsSource = false;
                        break;
                }

                if (isBingMapsSource && o.bingMapsKey && o.bingMapsKey !== "") {
                    $.ajax({
                        url: "http://dev.virtualearth.net/webservices/v1/LoggingService/LoggingService.svc/Log?entry=0&auth=" + o.bingMapsKey + "&fmt=1&type=3&group=wijmo&name=wijmaps&mkt=en-us&jsonp=?",
                        data: null,
                        context: null,
                        success: function (result) {
                            self._authenticationResult = result ? result["authenticationResultCode"] : "";
                            self._sessionId = result ? result["sessionId"] : "";
                            callback();
                        },
                        error: function (result) {
                            // authentication failed.
                            callback();
                        },
                        dataType: "json",
                        timeout: 5000
                    });
                } else {
                    callback();
                }
            };

            wijmaps.prototype._setShowTools = function (showTools) {
                var self = this, o = self.options;

                o.showTools = showTools;
                if (showTools) {
                    self._createToolsLayer();
                } else {
                    self._destroyToolsLayer();
                }
            };

            wijmaps.prototype._setSource = function (source) {
                var self = this, o = self.options;
                o.source = source;
                self._setInnerSource(source, function () {
                    self._refreshTileLayer();
                });
            };

            wijmaps.prototype._refreshTileLayer = function () {
                var self = this;
                self._destroyTileLayer();
                if (self._innerSource) {
                    self._minZoom = self._innerSource.minZoom;
                    self._maxZoom = self._innerSource.maxZoom;
                    self._coordConverter.tileWidth = self._innerSource.tileWidth;
                    self._coordConverter.tileHeight = self._innerSource.tileHeight;
                    self._createMultiScaleImageLayer();
                } else {
                    self._minZoom = defMinZoom;
                    self._maxZoom = defMaxZoom;
                    self._coordConverter.tileWidth = defTileWidth;
                    self._coordConverter.tileHeight = defTileHeight;
                }
            };

            wijmaps.prototype._setLayers = function (layers) {
                var self = this;
                self.options.layers = layers;
                self._destroyInnerLayers();
                self._createInnerLayers();
            };

            wijmaps.prototype._setCenter = function (center) {
                var self = this;
                self.options.targetCenter = center;
                self._trigger("targetCenterChanged", null, { "targetCenter": center });
                self._setCenterInternal(new maps.Point(center.x, center.y));
            };

            wijmaps.prototype._setCenterInternal = function (center) {
                var self = this, o = self.options;
                o.center = { "x": center.x, "y": center.y };
                self._coordConverter.center = center;
                self._updateLayers();
                self._trigger("centerChanged", null, { "center": o.center });
            };

            wijmaps.prototype._setZoom = function (zoom, position) {
                var self = this, o = self.options;
                if (zoom !== o.zoom && zoom >= self._minZoom && zoom <= self._maxZoom) {
                    self.options.targetZoom = zoom;
                    self._trigger("targetZoomChanged", null, { "targetZoom": zoom });
                    self._setZoomInternal(zoom, position);
                }
            };

            wijmaps.prototype._setZoomInternal = function (zoom, position) {
                var self = this, o = self.options, zoomPosition, viewCenter, offset;
                viewCenter = self._coordConverter.getViewCenter();
                zoomPosition = position ? position : viewCenter;
                offset = new maps.Size(zoomPosition.x - viewCenter.x, zoomPosition.y - viewCenter.y).scale(1 - Math.pow(2, o.zoom - zoom), 1 - Math.pow(2, o.zoom - zoom));
                self._offsetCenter(offset.width, offset.height);

                o.zoom = zoom;
                self._coordConverter.zoom = zoom;
                self._updateLayers();
                self._trigger("zoomChanged", null, { "zoom": o.zoom });
            };

            wijmaps.prototype._zoomIn = function (zoomPosition) {
                var self = this, o = self.options, newZoom = Math.min(Math.round(o.targetZoom + 1), self._maxZoom);

                if (o.zoom !== newZoom) {
                    self._setTargetZoom(newZoom, zoomPosition);
                }
            };

            wijmaps.prototype._zoomOut = function (zoomPosition) {
                var self = this, o = self.options, newZoom = Math.max(Math.round(o.targetZoom - 1), self._minZoom);

                if (o.zoom !== newZoom) {
                    self._setTargetZoom(newZoom, zoomPosition);
                }
            };

            wijmaps.prototype._setTargetZoom = function (targetZoom, position) {
                var self = this, o = self.options, intermediateZoom;

                if (targetZoom > self._maxZoom)
                    targetZoom = self._maxZoom;
                if (targetZoom < self._minZoom)
                    targetZoom = self._minZoom;

                if (targetZoom !== o.targetZoom) {
                    o.targetZoom = targetZoom;
                    self._trigger("targetZoomChanged", null, { "targetZoom": targetZoom });

                    if (self._isZooming)
                        return;

                    self._isZooming = true;
                    clearInterval(self._targetZoomTimer);
                    self._targetZoomTimer = setInterval(function () {
                        if (self._isZooming) {
                            if (Math.abs(o.zoom - o.targetZoom) < 0.001) {
                                intermediateZoom = o.targetZoom;
                                self._isZooming = false;
                                clearInterval(self._targetZoomTimer);
                            } else {
                                intermediateZoom = o.targetZoom * o.targetZoomSpeed + o.zoom * (1 - o.targetZoomSpeed);
                            }

                            self._setZoomInternal(intermediateZoom, position);
                        }
                    }, 20);
                }
            };

            wijmaps.prototype._setTargetCenter = function (targetCenter) {
                var self = this, o = self.options, intermediateCenter, converter = self._coordConverter;

                if (targetCenter.x < converter.minLongitude)
                    targetCenter.x = converter.minLongitude;
                if (targetCenter.x > converter.maxLongitude)
                    targetCenter.x = converter.maxLongitude;
                if (targetCenter.y < converter.minLatitude)
                    targetCenter.y = converter.minLatitude;
                if (targetCenter.y > converter.maxLatitude)
                    targetCenter.y = converter.maxLatitude;

                if (o.targetCenter.x !== targetCenter.x || o.targetCenter.y !== targetCenter.y) {
                    o.targetCenter = targetCenter;
                    self._trigger("targetCenterChanged", null, { "targetCenter": targetCenter });

                    if (self._isCenterChanging)
                        return;

                    self._isCenterChanging = true;
                    clearInterval(self._targetCenterTimer);
                    self._targetCenterTimer = setInterval(function () {
                        if (self._isCenterChanging) {
                            if (Math.abs(o.targetCenter.x - o.center.x) < 0.001 && Math.abs(o.targetCenter.y - o.center.y) < 0.001) {
                                intermediateCenter = new maps.Point(o.targetCenter.x, o.targetCenter.y);
                                self._isCenterChanging = false;
                                clearInterval(self._targetCenterTimer);
                            } else {
                                intermediateCenter = new maps.Point(o.targetCenter.x * o.targetCenterSpeed + o.center.x * (1 - o.targetCenterSpeed), o.targetCenter.y * o.targetCenterSpeed + o.center.y * (1 - o.targetCenterSpeed));
                            }

                            self._setCenterInternal(intermediateCenter);
                        }
                    }, 20);
                }
            };

            wijmaps.prototype._panning = function (offsetX, offsetY) {
                var self = this, o = self.options;
                if (offsetX !== 0 || offsetY !== 0) {
                    self._offsetCenter(offsetX, offsetY);
                }
            };

            wijmaps.prototype._offsetCenter = function (offsetX, offsetY) {
                if (offsetX === 0 && offsetY == 0) {
                    return;
                }

                var self = this, c = self._coordConverter, fullMapSize = c.getFullMapSize(), logicCenter = new maps.Point(c.getLogicCenter()).offset(offsetX / fullMapSize.width, offsetY / fullMapSize.height), newCenter = c.logicToGeographic(logicCenter);

                self._setCenter({ "x": newCenter.x, "y": newCenter.y });
            };

            wijmaps.prototype._onKeyDown = function (event) {
                var self = this, o = self.options, c = self._coordConverter, panSpeed = 5, center, keyCode = self._keyCode, viewSize = c.getViewSize(), offsetX = 0, offsetY = 0;
                switch (event.which) {
                    case keyCode.UP:
                        offsetY = -panSpeed;
                        break;
                    case keyCode.DOWN:
                        offsetY = panSpeed;
                        break;
                    case keyCode.LEFT:
                        offsetX = -panSpeed;
                        break;
                    case keyCode.RIGHT:
                        offsetX = panSpeed;
                        break;
                    case keyCode.HOME:
                        offsetX = -viewSize.width;
                        break;
                    case keyCode.END:
                        offsetX = viewSize.width;
                        break;
                    case keyCode.PAGE_UP:
                        offsetY = -viewSize.height;
                        break;
                    case keyCode.PAGE_DOWN:
                        offsetY = viewSize.height;
                        break;
                    default:
                        return false;
                }

                if (offsetX !== 0 || offsetY !== 0) {
                    center = c.geographicToView(o.targetCenter);
                    self._setTargetCenter(c.viewToGeographic({ "x": center.x + offsetX, "y": center.y + offsetY }));
                }

                return true;
            };

            wijmaps.prototype._onKeyPress = function (event) {
                var self = this, targetZoom = self.options.targetZoom, newTargetZoom = targetZoom;
                switch (String.fromCharCode(event.which)) {
                    case "+":
                        newTargetZoom++;
                        break;
                    case "-":
                        newTargetZoom--;
                        break;
                    default:
                        return false;
                }

                if (targetZoom !== newTargetZoom) {
                    self._setTargetZoom(newTargetZoom);
                }

                return true;
            };

            wijmaps.prototype._createLayers = function () {
                var self = this, o = self.options;

                self._container = $("<div class='" + containerCss + "'></div>").appendTo(self.element);

                self._multiScaleImageContainer = $("<div class=\"" + layerContainerCss + " " + tilesContainerCss + "\"></div>").appendTo(self._container);
                if (self._innerSource) {
                    self._createMultiScaleImageLayer();
                }

                self._layersContainer = $("<div class=\"" + layerContainerCss + "\"></div>").appendTo(self._container);
                self._createInnerLayers();

                self._toolsLayerContainer = $("<div class=\"" + layerContainerCss + "\"></div>").appendTo(self._container);
                if (o.showTools) {
                    self._createToolsLayer();
                }

                self._disabledCover = $("<div class='" + containerCss + "'></div>").hide().appendTo(self.element);
            };

            wijmaps.prototype._createMultiScaleImageLayer = function () {
                var self = this, o = self.options;
                self._multiScaleImageContainer.wijmultiscaleimage(self._createMultiscaleimageOptions());
            };

            wijmaps.prototype._createInnerLayers = function () {
                var self = this, o = self.options, e = self.element;
                if (o.layers) {
                    self._layers = [];
                    $.each(o.layers, function (key, options) {
                        var wijname = (options.type === maps.LayerType[3 /* custom */]) ? options.widgetName : "wij" + options.type + "layer", layer = self._createLayer(wijname, options);
                        if (layer) {
                            self._layers.push({ wijname: wijname, options: options, element: layer });
                        }
                    });
                }
            };

            wijmaps.prototype._createToolsLayer = function () {
                var self = this, o = self.options;
                self._toolsLayerContainer.wijtoolslayer({ "center": new maps.Point(o.center.x, o.center.y), "zoom": o.targetZoom, "minZoom": self._minZoom, "maxZoom": self._maxZoom, "converter": self._coordConverter });
                self._toolsLayerContainer.on("wijtoolslayertargetzoomchanged." + self.widgetName, function (e, d) {
                    if (o.targetZoom !== d["targetZoom"]) {
                        self._setTargetZoom(d["targetZoom"]);
                    }
                }).on("wijtoolslayertargetcenterchanged." + self.widgetName, function (e, d) {
                    if (d.targetCenter && (!o.targetCenter || o.targetCenter.x !== d.targetCenter.x || o.targetCenter.y !== d.targetCenter.y)) {
                        self._setTargetCenter({ "x": d.targetCenter.x, "y": d.targetCenter.y });
                    }
                });
            };

            wijmaps.prototype._createLayer = function (wijname, options) {
                var self = this, wo = self._createWijlayerOptions(options), element = $("<div class=\"" + layerContainerCss + "\"></div>");
                self._layersContainer.append(element);
                if (element[wijname]) {
                    return element[wijname](wo);
                }
                return null;
            };

            wijmaps.prototype._createWijlayerOptions = function (lo) {
                var self = this, o = self.options;

                return $.extend(new maps.wijlayer_options(), {
                    disabled: self._isDisabled(),
                    center: new maps.Point(o.center.x, o.center.y),
                    zoom: o.zoom,
                    targetCenter: new maps.Point(o.targetCenter.x, o.targetCenter.y),
                    targetZoom: o.targetZoom,
                    isZooming: self._isZooming,
                    converter: self._coordConverter
                }, lo);
            };

            wijmaps.prototype._updateLayers = function () {
                var self = this, o = self.options, layers = self._layers, options;

                self._coordConverter._updateSize();

                if (layers) {
                    $.each(layers, function (key, item) {
                        options = self._createWijlayerOptions(item.options);
                        item.element[item.wijname]("beginUpdate");
                        item.element[item.wijname](options);
                        item.element[item.wijname]("endUpdate");
                    });
                }

                if (self._innerSource) {
                    self._multiScaleImageContainer.wijmultiscaleimage(self._createMultiscaleimageOptions());
                }

                if (o.showTools) {
                    self._toolsLayerContainer.wijtoolslayer({ "center": new maps.Point(o.center.x, o.center.y), "zoom": o.targetZoom, "converter": self._coordConverter });
                }
            };

            wijmaps.prototype._createMultiscaleimageOptions = function () {
                var self = this, o = self.options;
                return { "source": self._innerSource, "zoom": o.zoom, "center": self._coordConverter.geographicToLogic(new maps.Point(o.center.x, o.center.y)) };
            };

            /**
            * Refresh the map layers. Usually used when the items of the layer data changed.
            */
            wijmaps.prototype.refreshLayers = function () {
                var self = this, o = self.options, layers = self._layers;
                if (layers) {
                    $.each(layers, function (key, item) {
                        item.element[item.wijname]("refresh");
                    });
                }
            };

            /**
            * Convert the point from screen unit (pixel) to  geographic unit (longitude and latitude).
            * @param {IPoint} position The point to convert.
            */
            wijmaps.prototype.viewToGeographic = function (position) {
                return this._coordConverter.viewToGeographic(position);
            };

            /**
            * Convert the point from geographic unit (longitude and latitude) to screen unit (pixel).
            * @param {IPoint} position The point to convert.
            */
            wijmaps.prototype.geographicToView = function (position) {
                return this._coordConverter.geographicToView(position);
            };

            /**
            * Convert the point from screen unit (pixel) to logic unit (percentage).
            * @param {IPoint} position The point to convert.
            */
            wijmaps.prototype.viewToLogic = function (position) {
                return this._coordConverter.viewToLogic(position);
            };

            /**
            * Convert the point from logic unit (percentage) to screen unit (pixel).
            * @param {IPoint} position The point to convert.
            */
            wijmaps.prototype.logicToView = function (position) {
                return this._coordConverter.logicToView(position);
            };

            /**
            * Calculate the distance between two points.
            * @param {Point} lonLat1 The coordinate of first point, in geographic unit.
            * @param {Point} longLat2 The coordinate of second point, in geographic unit.
            * @returns {number} The distance between to points, in meters.
            */
            wijmaps.prototype.distance = function (lonLat1, lonLat2) {
                return this._coordConverter.distance(lonLat1, lonLat2);
            };

            /**
            * Removes the wijmaps functionality completely. This will return the element back to its pre-init state.
            */
            wijmaps.prototype.destroy = function () {
                var self = this, o = self.options, e = self.element;

                e.removeClass(wijmapsCss);
                e.removeClass(o.wijCSS.content);
                e.removeAttr("tabindex");

                self.element.off("." + self.widgetName);
                $(document).off("." + self.widgetName);
                self._destroyLayers();
                _super.prototype.destroy.call(this);
            };

            wijmaps.prototype._destroyLayers = function () {
                var self = this, o = self.options;

                if (self._innerSource) {
                    self._destroyTileLayer();
                }

                self._destroyInnerLayers();

                if (o.showTools) {
                    self._destroyToolsLayer();
                }

                self._container.remove();
                self._disabledCover.remove();
            };

            wijmaps.prototype._destroyTileLayer = function () {
                var self = this;
                if (self._multiScaleImageContainer.data()["wijmoWijmultiscaleimage"]) {
                    self._multiScaleImageContainer.off("." + self.widgetName).wijmultiscaleimage("destroy");
                }
            };

            wijmaps.prototype._destroyToolsLayer = function () {
                var self = this;
                if (self._toolsLayerContainer.data()["wijmoWijtoolslayer"]) {
                    this._toolsLayerContainer.off("." + self.widgetName).wijtoolslayer("destroy");
                }
            };

            wijmaps.prototype._destroyInnerLayers = function () {
                var self = this;
                if (self._layers) {
                    $.each(self._layers, function (index, layer) {
                        layer.element[layer.wijname]("destroy").remove();
                    });
                    self._layers = null;
                }
            };
            return wijmaps;
        })(wijmo.wijmoWidget);
        maps.wijmaps = wijmaps;

        /**
        * The options of the wijmaps widget.
        */
        var wijmaps_options = (function () {
            function wijmaps_options() {
                /**
                * The source of the wijmaps tile layer. Wijmaps provides some built in sources:
                * <ul>
                * <li>bingMapsRoadSource</li>
                * <li>bingMapsAerialSource</li>
                * <li>bingMapsHybridSource</li>
                * </ul>
                * Set to null if want to hide the tile layer.<br>
                * Set to a IMultiScaleTileSource object if want to use another map tile server.
                */
                this.source = "bingMapsRoadSource";
                /**
                * The bing mpas key of the bing maps source.
                *
                */
                this.bingMapsKey = "";
                /**
                * The center of wijmaps view port, in geographic unit.
                */
                this.center = { "x": 0, "y": 0 };
                /**
                * The current zoom of the wijmaps.
                */
                this.zoom = 1;
                /**
                * Determine whether show the tools layer.
                */
                this.showTools = true;
                /**
                * The speed for scaling the wijmaps from current zoom to target zoom.
                */
                this.targetZoomSpeed = 0.3;
                /**
                * The speed for translate the wijmaps from current center to target center.
                */
                this.targetCenterSpeed = 0.3;
                /**
                * Defines the array of layers append to the wijmaps.
                */
                this.layers = [];
            }
            return wijmaps_options;
        })();
        maps.wijmaps_options = wijmaps_options;

        

        

        

        

        

        wijmaps.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijmaps_options());

        $.wijmo.registerWidget("wijmaps", wijmaps.prototype);
    })(wijmo.maps || (wijmo.maps = {}));
    var maps = wijmo.maps;
})(wijmo || (wijmo = {}));
;
/// <reference path="../Base/jquery.wijmo.widget.ts" />
/// <reference path="../wijlinechart/jquery.wijmo.wijlinechart.ts"/>
/// <reference path="../wijslider/jquery.wijmo.wijslider.ts"/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var wijmo;
(function (wijmo) {
    (function (_chart) {
        var chartMargin = 2;

        var _getArrayMinMax = function (array, field) {
            var min, max, isTime;

            if (array && array.length) {
                min = _chart.ChartUtil.getFirstValidListValue(array);
                max = min = field ? min[field] : min;
                if (typeof min === "string") {
                    return { min: 0, max: array.length - 1 };
                }

                isTime = _chart.ChartUtil.isDate(min);

                $.each(array, function (idx, item) {
                    item = field ? item[field] : item;
                    if (min > item) {
                        min = item;
                    }
                    if (max < item) {
                        max = item;
                    }
                });

                min = isTime ? $.toOADate(min) : min;
                max = isTime ? $.toOADate(max) : max;

                return { min: min, max: max, isTime: isTime };
            }
            return undefined;
        };

        var getIndicatorTimeDefaultFormat = function (max, min) {
            var dateUtil = _chart.ChartDataUtil, range = max - min, format = "d";

            if (range > 2 * dateUtil.tmInc.year) {
                format = "yy";
            } else if (range > dateUtil.tmInc.year) {
                format = "MMM yy";
            } else if (range > dateUtil.tmInc.month) {
                format = "MMM d";
            } else if (range > dateUtil.tmInc.week) {
                format = "ddd d";
            } else if (range > dateUtil.tmInc.day) {
                format = "ddd H";
            } else if (range > dateUtil.tmInc.hour) {
                format = "H:mm";
            }

            return format;
        };

        /** @widget */
        var wijchartnavigator = (function (_super) {
            __extends(wijchartnavigator, _super);
            function wijchartnavigator() {
                _super.apply(this, arguments);
            }
            wijchartnavigator.prototype._create = function () {
                _super.prototype._create.call(this);
                this.element.addClass(this.options.wijCSS.chartNavigator);

                this.isInitialized = true;
                this._render();
            };

            wijchartnavigator.prototype._render = function () {
                var self = this;

                self._initialXDataRange();
                if (self.isInitialized) {
                    self._initialTargetCharts();
                } else {
                    self._updateTargetCharts();
                }
                self._initialNavigator();
                self.isInitialized = false;
            };

            wijchartnavigator.prototype._setOption = function (key, value) {
                var self = this, opts = self.options, xAxis = opts.xAxis, range;

                if (key === "targetSelector") {
                    if (opts.targetSelector !== value) {
                        opts.targetSelector = value;
                        self._initialTargetCharts();
                    }
                } else if (key === "data" || key === "dataSource" || key === "seriesList") {
                    opts[key] = value;
                    self._render();
                } else if (key === "seriesStyles") {
                    opts.seriesStyles = value;
                    self.element.wijlinechart("option", "seriesStyles", value);
                } else if (key === "xAxis") {
                    opts.xAxis = value;
                    if ((value.min != null && value.min !== xAxis.min) || (value.max != null && value.max !== xAxis.max)) {
                        self._render();
                    } else {
                        self.element.wijlinechart("option", "axis", { x: value });
                    }
                } else if (key === "culture") {
                    self.element.wijlinechart("option", "culture", value);
                    self.indicatorCulture = $.wijGetCulture(value, "");
                } else if (key === "indicator") {
                    opts.indicator = value;
                    self._initialNvIndicator();
                } else if (key === "rangeMin" || key === "rangeMax") {
                    range = self._getCurrentRange();
                    if (key === "rangeMin") {
                        self._triggerRangeUpdated(value, range.max);
                    } else {
                        self._triggerRangeUpdated(range.min, value);
                    }
                    self._updateNvSlider("values");
                } else if (key === "disabled" || key === "step") {
                    _super.prototype._setOption.call(this, key, value);
                    self._updateNvSlider(key);
                }
                _super.prototype._setOption.call(this, key, value);
            };

            wijchartnavigator.prototype._initialXDataRange = function () {
                var self = this, xAxis = self.options.xAxis, nvRange;

                if (xAxis) {
                    if (xAxis.min) {
                        self.xFieldIsTime = _chart.ChartUtil.isDate(xAxis.min);
                        self.nvMin = xAxis.min;
                    }
                    if (xAxis.max) {
                        self.xFieldIsTime = _chart.ChartUtil.isDate(xAxis.max);
                        self.nvMax = xAxis.max;
                    }
                }

                if (self.nvMin == null || self.nvMax == null) {
                    nvRange = self._getNavigatorXRange();
                    if (nvRange) {
                        self.nvMin = self.nvMin === undefined ? nvRange.min : self.nvMin;
                        self.nvMax = self.nvMax === undefined ? nvRange.max : self.nvMax;
                        self.xFieldIsTime = nvRange.isTime;
                    }
                }
            };

            wijchartnavigator.prototype._getNavigatorXRange = function () {
                var self = this, opt = self.options, dataSource = opt.dataSource, data = opt.data, seriesList = opt.seriesList, xField, isTime = false, range, sRange;

                if (!(seriesList && seriesList.length > 0)) {
                    return undefined;
                }

                if (dataSource && dataSource.length) {
                    if (data && data.x && data.x.bind) {
                        xField = data.x.bind.toString();
                    } else {
                        if (seriesList[0].data && seriesList[0].data.x) {
                            xField = seriesList[0].data.x.bind;
                        }
                    }

                    if (xField) {
                        range = _getArrayMinMax(dataSource, xField);
                    }
                } else {
                    if (data && data.x && $.isArray(data.x)) {
                        range = _getArrayMinMax(data.x);
                    }
                    $.each(seriesList, function (idx, series) {
                        if (series.data && series.data.x) {
                            sRange = _getArrayMinMax(series.data.x);
                            if (sRange) {
                                range = range ? {
                                    min: Math.min(range.min, sRange.min),
                                    max: Math.max(range.max, sRange.max),
                                    isTime: range.isTime && sRange.isTime
                                } : sRange;
                            }
                        }
                    });
                }

                return range;
            };

            wijchartnavigator.prototype._initialTargetCharts = function () {
                var self = this, opt = self.options, selector = opt.targetSelector, targetChartInfos, targetCharts, newTargets, i = 0, chartInfo, chart;
                if (selector === undefined || selector === null) {
                    return;
                }

                targetChartInfos = self.targetChartInfos || [];
                targetCharts = self.targetCharts || [];

                newTargets = $(selector);

                while (i < targetChartInfos.length) {
                    chartInfo = targetChartInfos[i];

                    if ($.inArray(chartInfo.chartObj.element[0], newTargets) < 0) {
                        self._recoverTarget(chartInfo);
                        targetChartInfos.splice(i, 1);
                    } else {
                        i++;
                    }
                }

                for (i = 0; i < newTargets.length; i++) {
                    if ($.inArray(newTargets[i], targetCharts) < 0) {
                        chart = self._getChartObj($(newTargets[i]));
                        if (chart) {
                            targetChartInfos.push(chart);
                        }
                    }
                }

                self.targetChartInfos = targetChartInfos;
                self.targetCharts = newTargets;

                self._updateTargetCharts();
            };

            wijchartnavigator.prototype._getChartObj = function (target) {
                var self = this, chartTarget = undefined, chartOpts, type, isDataBind = false, dataSource, data, seriesList, axisXMin, axisXMax, isTime;

                $.each(self.targetChartTypes, function (idx, chartType) {
                    chartTarget = target.data("wijmo-" + chartType);
                    if (chartTarget) {
                        type = chartType;
                        chartOpts = chartTarget.options;
                        isTime = chartTarget.axisInfo && chartTarget.axisInfo.x.isTime;
                        dataSource = chartOpts.dataSource;
                        data = chartOpts.data;
                        seriesList = chartOpts.seriesList;
                        isDataBind = dataSource !== undefined && dataSource !== null && $.isArray(dataSource);
                        axisXMax = axisXMin = undefined;
                        if (!chartOpts.axis.x.autoMin) {
                            axisXMin = chartOpts.axis.x.min;
                            axisXMin = self._getActualValue(axisXMin);
                        }
                        if (!chartOpts.axis.x.autoMax) {
                            axisXMax = chartOpts.axis.x.max;
                            axisXMax = self._getActualValue(axisXMax);
                        }

                        return false;
                    }
                });

                if (chartTarget) {
                    return {
                        type: type,
                        chartObj: chartTarget,
                        isDataBind: isDataBind,
                        dataSource: dataSource,
                        data: data,
                        seriesList: seriesList,
                        axisXMax: axisXMax,
                        axisXMin: axisXMin
                    };
                }

                return undefined;
            };

            wijchartnavigator.prototype._initialNavigator = function () {
                var self = this;
                self._initialNvChart();
                self._initialNvSlider();
            };

            wijchartnavigator.prototype._initialNvChart = function () {
                var self = this, opt = self.options, chartOpt;

                chartOpt = {
                    dataSource: opt.dataSource,
                    data: opt.data,
                    marginTop: chartMargin,
                    marginBottom: chartMargin,
                    marginLeft: chartMargin,
                    marginRight: chartMargin,
                    axis: {
                        y: {
                            visible: false,
                            textVisible: false,
                            gridMajor: {
                                visible: false
                            },
                            gridMinor: {
                                visible: false
                            }
                        }
                    },
                    showChartLabels: false,
                    legend: { visible: false },
                    hint: { enable: false },
                    animation: { enabled: false },
                    seriesTransition: { enabled: false },
                    culture: opt["culture"]
                };

                if (opt.seriesList && opt.seriesList.length > 0) {
                    chartOpt.seriesList = $.arrayClone(opt.seriesList);
                }
                if (opt.seriesStyles && opt.seriesStyles.length > 0) {
                    chartOpt.seriesStyles = $.arrayClone(opt.seriesStyles);
                }

                chartOpt.axis.x = $.extend(true, {}, {
                    min: self._getActualValue(self.nvMin),
                    max: self._getActualValue(self.nvMax)
                }, self.options.xAxis);

                self.element.wijlinechart(chartOpt);
            };

            wijchartnavigator.prototype._initialNvSlider = function () {
                var self = this, opt = self.options, sliderContainer, nvBounds, nvSlider, updatingResult, sliderOpts, eleOffset = self.element.offset(), top, sOffset, sSize, indicatorOpt = opt.indicator, indicatorVisible = !(indicatorOpt && indicatorOpt.visible === false), range = self._getCurrentRange(), max = range.max, min = range.min;

                self.isSliding = false;

                nvBounds = self.element.data("wijmo-wijlinechart").canvasBounds;

                if (!self.nvSliderEle) {
                    sliderContainer = $("<div class='" + opt.wijCSS.navigatorSliderContainer + "'></div>").appendTo(self.element);
                    top = eleOffset.top - sliderContainer.offset().top;
                    sliderContainer.css("top", top + "px");

                    nvSlider = $("<div class='" + opt.wijCSS.navigatorSlider + "'></div>").appendTo(sliderContainer);
                } else {
                    nvSlider = self.nvSliderEle;
                }

                nvSlider.css({
                    "height": (nvBounds.endY - nvBounds.startY + chartMargin) + "px"
                });

                self.nvSliderLayout = {
                    width: nvSlider.width(),
                    height: nvSlider.height(),
                    offset: nvSlider.offset()
                };

                sliderOpts = {
                    disabled: this._isDisabled(),
                    min: self.nvMin || 0,
                    max: self.nvMax || 100,
                    values: [min, max],
                    step: opt.step,
                    range: true
                };

                sliderOpts.start = function () {
                    if (indicatorVisible) {
                        self.nvSliderLayout.offset = self.nvSliderEle.offset();
                        self.nvIndicateTooltips[0].show();
                        self.nvIndicateTooltips[1].show();
                    }
                    self.isSliding = true;
                };

                // For drag the handlers
                sliderOpts.slide = function (event, ui) {
                    updatingResult = self._triggerRangeUpdating(ui.values[0], ui.values[1], false, event);
                };

                // For drag the "fill" element
                sliderOpts.change = function (event, ui) {
                    if (self.isSliding) {
                        updatingResult = self._triggerRangeUpdating(ui.values[0], ui.values[1], true, event);
                    }
                };

                sliderOpts.stop = function (event, ui) {
                    if (updatingResult !== false) {
                        self._triggerRangeUpdated(ui.values[0], ui.values[1], event);
                    }

                    self.nvIndicateTooltips[0].hide();
                    self.nvIndicateTooltips[1].hide();
                    self.isSliding = false;
                };

                self.nvSliderEle = nvSlider.wijslider(sliderOpts);
                self._initialNvIndicator();
            };

            wijchartnavigator.prototype._triggerRangeUpdating = function (min, max, dragFill, event) {
                var self = this, opt = self.options, updating = opt.updating, indicatorOpt = opt.indicator, indicatorVisible = !(indicatorOpt && indicatorOpt.visible === false), content = indicatorOpt ? indicatorOpt.content : "", range = self._getCurrentRange(), needUpdating, updatingResult = true;

                self._updateNvIndicateTooltips(min, max, content);

                needUpdating = max !== range.max || min !== range.min;
                needUpdating = dragFill ? needUpdating && (max - min === range.max - range.min) : needUpdating;

                if (!needUpdating) {
                    return false;
                }
                if (updating && typeof updating === "function") {
                    updatingResult = updating.call(self, event, {
                        rangeMin: self._getActualValue(min),
                        rangeMax: self._getActualValue(max)
                    });
                }

                return updatingResult;
            };

            wijchartnavigator.prototype._triggerRangeUpdated = function (min, max, event) {
                var self = this, updated = self.options.updated, range = self._getCurrentRange(), needUpdated = max !== range.max || min !== range.min;

                if (!needUpdated) {
                    return;
                }

                self.options.rangeMax = max;
                self.options.rangeMin = min;
                self._updateTargetCharts();
                if (updated && typeof updated === "function") {
                    updated.call(self, event, {
                        rangeMin: self._getActualValue(min),
                        rangeMax: self._getActualValue(max)
                    });
                }
            };

            wijchartnavigator.prototype._initialNvIndicator = function () {
                var self = this, leftIndicator, rightIndicator, opt = self.options, indicatorOpt = opt.indicator;

                if (!self.nvIndicateTooltips || self.nvIndicateTooltips.length === 0) {
                    leftIndicator = $("<div></div>").addClass(opt.wijCSS.navigatorIndicator).appendTo("body");
                    rightIndicator = $("<div></div>").addClass(opt.wijCSS.navigatorIndicator).appendTo("body");
                    self.nvIndicateTooltips = [leftIndicator, rightIndicator];
                }

                self._bindSliderHandlerEvents();
            };

            wijchartnavigator.prototype._bindSliderHandlerEvents = function () {
                var self = this, opt = self.options, sliderEle = self.nvSliderEle, indicatorOpt = opt.indicator, indicatorVisible = !(indicatorOpt && indicatorOpt.visible === false), content = indicatorOpt ? indicatorOpt.content : "", index, stringFormat = indicatorOpt ? indicatorOpt.format : "", sliderHandlers = sliderEle.find(".ui-slider-handle"), range;

                if (self.xFieldIsTime && (!stringFormat || stringFormat.length === 0)) {
                    stringFormat = getIndicatorTimeDefaultFormat(self.nvMax, self.nvMin);
                }
                self.indicatorContentFormat = stringFormat;
                self.indicatorCulture = $.wijGetCulture(opt["culture"], "");

                self._unbindSliderHandlerEvents();
                sliderEle.on("wijmouseover." + self.widgetName, ".ui-slider-handle", function (event) {
                    if (indicatorVisible && !self.isSliding && !self._isDisabled()) {
                        self.nvSliderLayout.offset = self.nvSliderEle.offset();
                        range = self._getCurrentRange();
                        self._updateNvIndicateTooltips(range.min, range.max, content);
                        index = event.target === sliderHandlers[0] ? 0 : 1;
                        self.nvIndicateTooltips[index].show();
                    }
                }).on("wijmouseout." + self.widgetName, ".ui-slider-handle", function (event) {
                    if (!self.isSliding) {
                        index = event.target === sliderHandlers[0] ? 0 : 1;
                        self.nvIndicateTooltips[index].hide();
                    }
                });
            };

            wijchartnavigator.prototype._unbindSliderHandlerEvents = function () {
                var self = this;

                self.nvSliderEle.off("." + self.widgetName, ".ui-slider-handle");
            };

            wijchartnavigator.prototype._updateNvSlider = function (key) {
                var self = this, opts = self.options, range = self._getCurrentRange(), max = range.max, min = range.min, step = opts.step, sliderEle = self.nvSliderEle;

                if (sliderEle) {
                    if (key === "values") {
                        sliderEle.wijslider({
                            "values": [min, max]
                        });
                    } else if (key === "step") {
                        sliderEle.wijslider({
                            step: step
                        });
                    } else if (key === "disabled") {
                        sliderEle.wijslider({
                            disabled: self._isDisabled()
                        });
                    }
                }
            };

            wijchartnavigator.prototype._updateNvIndicateTooltips = function (rangeMin, rangeMax, content) {
                var self = this, leftPos, rightPos, contentResult, leftContent = "", rightContent = "", nvLayout = self.nvSliderLayout, dx = self.nvMax - self.nvMin, width = nvLayout.width, height = nvLayout.height, offset = nvLayout.offset, ui, format = self.indicatorContentFormat;
                rangeMin = rangeMin === undefined ? self.nvMin : rangeMin;
                rangeMax = rangeMax === undefined ? self.nvMax : rangeMax;

                leftPos = { left: offset.left, top: offset.top };
                rightPos = { left: offset.left, top: offset.top };
                leftPos.top += height / 2;
                rightPos.top += height / 2;
                leftPos.left += (rangeMin - self.nvMin) / dx * width;
                rightPos.left += (rangeMax - self.nvMin) / dx * width;

                self._updateIndicatorsContent(rangeMin, rangeMax, content);
                self._updateIndicatorsPosition(leftPos, rightPos);
            };

            wijchartnavigator.prototype._updateIndicatorsContent = function (rangeMin, rangeMax, content) {
                var self = this, contentResult = content, ui, leftContent, rightContent, format = self.indicatorContentFormat;

                if (typeof content === "function") {
                    ui = {
                        rangeMin: self._getActualValue(rangeMin),
                        rangeMax: self._getActualValue(rangeMax)
                    };
                    contentResult = content.call(self, ui);
                }
                if (typeof contentResult === "string" && contentResult.length > 0) {
                    contentResult = contentResult.split(",");
                }
                if ($.isArray(contentResult) && contentResult.length > 0) {
                    leftContent = contentResult[0].toString();
                    rightContent = (contentResult[1] || contentResult[0]).toString();
                } else {
                    leftContent = self._getActualValue(rangeMin);
                    rightContent = self._getActualValue(rangeMax);
                    if (format) {
                        leftContent = Globalize.format(leftContent, format, self.indicatorCulture);
                        rightContent = Globalize.format(rightContent, format, self.indicatorCulture);
                    }
                }

                self.nvIndicateTooltips[0].html(leftContent);
                self.nvIndicateTooltips[1].html(rightContent);
            };

            wijchartnavigator.prototype._updateIndicatorsPosition = function (lPosition, rPosition) {
                var self = this, lTooltipEle = self.nvIndicateTooltips[0], rTooltipEle = self.nvIndicateTooltips[1], left, width, height;

                lTooltipEle.css("float", "left");
                width = lTooltipEle.width();
                height = lTooltipEle.height();
                left = parseInt(lPosition.left) - (width + 15);
                lTooltipEle.css("left", left);
                lTooltipEle.css("top", lPosition.top - height / 2);

                rTooltipEle.css("float", "left");
                width = rTooltipEle.width();
                height = rTooltipEle.height();
                left = parseInt(rPosition.left) + 15;
                rTooltipEle.css("left", left);
                rTooltipEle.css("top", rPosition.top - height / 2);
            };

            wijchartnavigator.prototype._updateTargetCharts = function () {
                var self = this, opts = self.options, range = self._getCurrentRange(), max = range.max, min = range.min;

                if (!self.targetChartInfos) {
                    return;
                }
                $.each(self.targetChartInfos, function (idx, targetChart) {
                    if (self.isInitialized) {
                        self._clearTargetInitialAnimation(targetChart.chartObj);
                    }

                    self._updateTarget(targetChart, min, max);
                });
            };

            wijchartnavigator.prototype._updateTarget = function (targetChartInfo, rangeMin, rangeMax) {
                var self = this, type = targetChartInfo.type, isCandlestick = (type.indexOf("candlestickchart") > -1), chartObj = targetChartInfo.chartObj, currentChartObj = chartObj.element.data("wijmo-" + type), isDataBind = targetChartInfo.isDataBind, seriesList = targetChartInfo.seriesList, dataSource, data, sLength = 0, xField = "", xFieldIsString = false, idx = 0, hasSharedDataX = false, updatedDataSource, updatedData, updatedSeriesList, originRangeMin = targetChartInfo.rangeMin, originRangeMax = targetChartInfo.rangeMax, newXAxis, xDataArray = [], filterFunc = function (element, index) {
                    var value;
                    if (isDataBind && xField) {
                        value = element[xField];
                    } else {
                        value = xDataArray[index];
                    }

                    if (value !== null && value !== undefined) {
                        if (typeof value === "string") {
                            value = index;
                        }

                        return value >= rangeMin && value <= rangeMax;
                    }
                    return true;
                };

                if (!(seriesList && seriesList.length > 0)) {
                    return;
                }

                if (rangeMin === originRangeMin && rangeMax === originRangeMax) {
                    return;
                }

                targetChartInfo.rangeMin = rangeMin;
                targetChartInfo.rangeMax = rangeMax;

                rangeMin = self._getActualValue(rangeMin);
                rangeMax = self._getActualValue(rangeMax);

                newXAxis = isCandlestick ? undefined : {
                    x: {
                        min: rangeMin,
                        max: rangeMax
                    }
                };

                if (!currentChartObj || chartObj !== currentChartObj) {
                    self._removeInvalidTarget(targetChartInfo);
                    return;
                }

                if (isDataBind) {
                    dataSource = targetChartInfo.dataSource;
                    data = targetChartInfo.data;
                    if (data && data.x) {
                        xField = data.x.bind;
                    } else {
                        while (xField == "") {
                            if (seriesList[idx].data && seriesList[idx].data.xField) {
                                xField = seriesList[idx].data.xField;
                            }
                            idx++;
                        }
                    }
                    if (xField) {
                        updatedDataSource = $.grep(dataSource, filterFunc);
                        chartObj.beginUpdate();
                        chartObj.element[type]({
                            "dataSource": updatedDataSource,
                            axis: newXAxis
                        });
                        chartObj.endUpdate();
                    }
                } else {
                    data = targetChartInfo.data;
                    updatedSeriesList = $.arrayClone(seriesList);
                    hasSharedDataX = data && data.x && $.isArray(data.x);
                    if (hasSharedDataX) {
                        xDataArray = data.x;
                        updatedData = { x: $.grep(data.x, filterFunc) };
                    }
                    $.each(updatedSeriesList, function (idx, series) {
                        if (!series.data) {
                            return true;
                        }
                        xDataArray = series.data.x || xDataArray;
                        $.each(series.data, function (key, dataArray) {
                            if (dataArray && dataArray.length > 0) {
                                series.data[key] = $.grep(dataArray, filterFunc);
                            }
                        });
                    });

                    xFieldIsString = typeof _chart.ChartUtil.getFirstValidListValue(xDataArray) === "string";
                    newXAxis = xFieldIsString ? undefined : newXAxis;

                    chartObj.beginUpdate();
                    chartObj.element[type]({
                        "data": updatedData,
                        "seriesList": updatedSeriesList,
                        axis: newXAxis
                    });
                    chartObj.endUpdate();
                }
            };

            // Clear the storage of last state for the redraw animation to start from the original state.
            wijchartnavigator.prototype._clearTargetInitialAnimation = function (chartObj) {
                var chartField = chartObj.element.data("fields");

                // wijlinechart
                chartObj["aniPathsAttr"] = null;

                // wijbarchart
                if (chartField) {
                    chartField.aniBarsAttr = null;
                }
            };

            wijchartnavigator.prototype._recoverTargetCharts = function () {
                var self = this;

                if (self.targetChartInfos && self.targetChartInfos.length > 0) {
                    $.each(self.targetChartInfos, function (idx, targetChartInfo) {
                        self._recoverTarget(targetChartInfo);

                        self.targetChartInfos[idx] = null;
                    });
                }

                self.targetChartInfos = null;
            };

            wijchartnavigator.prototype._recoverTarget = function (targetChartInfo) {
                var type = targetChartInfo.type, chartObj = targetChartInfo.chartObj, currentChartObj = chartObj.element.data("wijmo-" + type), isDataBind = targetChartInfo.isDataBind, seriesList = targetChartInfo.seriesList, dataSource = targetChartInfo.dataSource, data = targetChartInfo.data, axisXInfo = {
                    min: targetChartInfo.axisXMin,
                    max: targetChartInfo.axisXMax
                };

                if (!currentChartObj || chartObj !== currentChartObj) {
                    this._removeInvalidTarget(targetChartInfo);
                    return;
                }

                chartObj.beginUpdate();
                if (isDataBind) {
                    chartObj.element[type]({
                        "dataSource": dataSource,
                        data: data,
                        axis: {
                            x: axisXInfo
                        }
                    });
                } else {
                    chartObj.element[type]({
                        "data": data,
                        "seriesList": seriesList,
                        axis: {
                            x: axisXInfo
                        }
                    });
                }
                chartObj.endUpdate();
            };

            wijchartnavigator.prototype._removeInvalidTarget = function (chartInfo) {
                var self = this, index = -1;
                if (!self.targetChartInfos) {
                    return;
                }
                index = self.targetChartInfos.indexOf(chartInfo);
                self.targetChartInfos.splice(index, 1);
            };

            wijchartnavigator.prototype.destroy = function () {
                var self = this;
                self.element.removeClass(self.options.wijCSS.chartNavigator);
                self._recoverTargetCharts();

                self._removeNvIndicator();

                self.nvSliderEle.remove();
                self.element.wijlinechart("destroy");

                _super.prototype.destroy.call(this);
            };

            wijchartnavigator.prototype._removeNvIndicator = function () {
                var self = this;
                self._unbindSliderHandlerEvents();

                self.nvIndicateTooltips[0].remove();
                self.nvIndicateTooltips[0] = null;
                self.nvIndicateTooltips[1].remove();
                self.nvIndicateTooltips[1] = null;
                self.nvIndicateTooltips = null;
            };

            wijchartnavigator.prototype._getActualValue = function (value) {
                return this.xFieldIsTime ? $.fromOADate(value) : value;
            };

            wijchartnavigator.prototype._getCurrentRange = function () {
                var self = this, opts = self.options, max = opts.rangeMax, min = opts.rangeMin;

                min = min === undefined ? self.nvMin : Math.max(min, self.nvMin);
                max = max === undefined ? self.nvMax : Math.min(max, self.nvMax);

                max = Math.max(max, min);
                return {
                    min: min,
                    max: max
                };
            };
            return wijchartnavigator;
        })(wijmo.wijmoWidget);
        _chart.wijchartnavigator = wijchartnavigator;

        // c1chartnavigator will overwrite this value.
        wijchartnavigator.prototype.targetChartTypes = ["wijbarchart", "wijcandlestickchart", "wijlinechart"];

        wijchartnavigator.prototype.widgetEventPrefix = "wijchartnavigator";

        var wijchartnavigator_css = (function (_super) {
            __extends(wijchartnavigator_css, _super);
            function wijchartnavigator_css() {
                _super.apply(this, arguments);
                this.chartNavigator = "wijmo-wijchartnavigator";
                this.navigatorSliderContainer = "wijmo-wijchartnavigator-sliderContainer";
                this.navigatorSlider = "wijmo-wijchartnavigator-slider";
                this.navigatorIndicator = "wijmo-wijchartnavigator-indicator";
            }
            return wijchartnavigator_css;
        })(wijmo.wijmo_css);
        _chart.wijchartnavigator_css = wijchartnavigator_css;

        var wijchartnavigator_options = (function () {
            function wijchartnavigator_options() {
                /** @ignore*/
                this.initSelector = ":jqmData(role='wijchartnavigator')";
                /**
                * All CSS classes used in widgets.
                * @ignore
                */
                this.wijCSS = new wijchartnavigator_css();
                /** Set this option as a jquery selector to bind the target chart(s).
                */
                this.targetSelector = "";
                /**
                * Creates an array of series objects that contain data values and labels to display in the chart navigator.
                */
                this.seriesList = [];
                /**
                * The updating event is raised when range of navigator is changing.
                * @event
                * @param {JQueryEventObject} e The jQuery.Event object.
                * @param {any} args The data with this event.
                */
                this.updating = null;
                /**
                * The updated event is raised when range of navigator has been changed.
                * @event
                * @param {JQueryEventObject} e The jQuery.Event object.
                * @param {any} args The data with this event.
                */
                this.updated = null;
            }
            return wijchartnavigator_options;
        })();
        _chart.wijchartnavigator_options = wijchartnavigator_options;

        wijchartnavigator.prototype.options = $.extend(true, {}, wijmo.wijmoWidget.prototype.options, new wijchartnavigator_options());

        $.wijmo.registerWidget("wijchartnavigator", wijchartnavigator.prototype);

        

        

        
    })(wijmo.chart || (wijmo.chart = {}));
    var chart = wijmo.chart;
})(wijmo || (wijmo = {}));
