text: ﻿(function ($) {
      'use strict';
      
      $.jqx.observableArray = function (items, observeFunction) {
          if (typeof (items) == 'string') {
              items = $.parseJSON(items);
          }
  
          if (!Object.defineProperty ||
      !(function () { try { Object.defineProperty({}, 'x', {}); return true; } catch (e) { return false; } }())) {
              var orig = Object.defineProperty;
              Object.defineProperty = function (o, prop, desc) {
                  // In IE8 try built-in implementation for defining properties on DOM prototypes.
                  if (orig) { try { return orig(o, prop, desc); } catch (e) { } }
  
                  if (o !== Object(o)) { throw TypeError("Object.defineProperty called on non-object"); }
                  if (Object.prototype.__defineGetter__ && ('get' in desc)) {
                      Object.prototype.__defineGetter__.call(o, prop, desc.get);
                  }
                  if (Object.prototype.__defineSetter__ && ('set' in desc)) {
                      Object.prototype.__defineSetter__.call(o, prop, desc.set);
                  }
                  if ('value' in desc) {
                      o[prop] = desc.value;
                  }
                  else if (!o[prop]) {
                      o[prop] = desc;
                  }
  
                  return o;
              };
          }
  
          if (!Array.prototype.forEach) {
              Array.prototype.forEach = function (fun /*, thisp */) {
                  if (this === void 0 || this === null) { throw TypeError(); }
  
                  var t = Object(this);
                  var len = t.length >>> 0;
                  if (typeof fun !== "function") { throw TypeError(); }
  
                  var thisp = arguments[1], i;
                  for (i = 0; i < len; i++) {
                      if (i in t) {
                          fun.call(thisp, t[i], i, t);
                      }
                  }
              };
          }
  
          if (typeof Object.getOwnPropertyNames !== "function") {
              Object.getOwnPropertyNames = function (o) {
                  if (o !== Object(o)) { throw TypeError("Object.getOwnPropertyNames called on non-object"); }
                  var props = [], p;
                  for (p in o) {
                      if (Object.prototype.hasOwnProperty.call(o, p)) {
                          props.push(p);
                      }
                  }
                  return props;
              };
          }
  
          var that = this, notifier, array = [];
          that.notifier = null;
          that.name = "observableArray";
          that.observing = true;
          that.changes = new Array();
  
          var observeFunction = observeFunction;
          that.observe = function () {
              that.observing = true;
              if (arguments.length == 1 ) {
                  observeFunction = arguments[0];
              }
          }
  
          that.unobserve = function () {
              that.observing = false;
          }
  
          that.toArray = function () {
              return array.slice(0);
          }
  
          that.toJSON = function (keys, subArray) {
              var value = array;
              if (subArray) {
                  value = subArray;
              }
              var escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
              meta = {
               '\b': '\\b',
               '\t': '\\t',
               '\n': '\\n',
               '\f': '\\f',
               '\r': '\\r',
               '"': '\\"',
               '\\': '\\\\'
              };
  
              function quote(string) {
                  return '"' + string.replace(escapable, function (a) {
                      var c = meta[a];
                      return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
                  }) + '"';
              }
  
              function formatNumber(n) {
                  return n < 10 ? '0' + n : n;
              }
  
              function stringifyDate(value) {
                  var date;
                  if (isFinite(value.valueOf())) {
                      date = value.getUTCFullYear() + '-' + formatNumber(value.getUTCMonth() + 1) + '-' +
                      formatNumber(value.getUTCDate()) + 'T' + formatNumber(value.getUTCHours()) + ':' +
                      formatNumber(value.getUTCMinutes()) + ':' + formatNumber(value.getUTCSeconds()) + 'Z"';
                  } else {
                      date = 'null';
                  }
                  return date;
              }
  
              function stringifyArray(value) {
                  var len = value.length,
                      partial = [],
                      i;
                  for (i = 0; i < len; i++) {
                      partial.push(str(i, value) || 'null');
                  }
  
                  return '[' + partial.join(',') + ']';
              }
  
              function stringifyObject(value) {
                  var partial = [],
                      i, v;
                  for (i in value) {
                      if (Object.prototype.hasOwnProperty.call(value, i)) {
                          if (i != "" && keys && keys.indexOf(i) === -1) {
                              continue;
                          }
  
                          v = str(i, value);
                          if (v) {
                              partial.push(quote(i) + ':' + v);
                          }
                      }
                  }
                  return '{' + partial.join(',') + '}';
              }
  
              function stringifyReference(value) {
                  switch (Object.prototype.toString.call(value)) {
                      case '[object Date]':
                          return stringifyDate(value);
                      case '[object Array]':
                          return stringifyArray(value);
                  }
                  return stringifyObject(value);
              }
  
              function stringifyPrimitive(value, type) {
                  switch (type) {
                      case 'string':
                          return quote(value);
                      case 'number':
                      case 'float':
                      case 'integer':
                      case 'int':
                          return isFinite(value) ? value : 'null';
                      case 'boolean':
                          return value;
                  }
                  return 'null';
              }
  
              function str(key, holder) {
                  var value = holder[key], type = typeof value;
  
                  if (value && typeof value === 'object' && typeof value.toJSON === 'function') {
                      value = value.toJSON(key);
                      type = typeof value;
                  }
                  if (/(number|float|int|integer|string|boolean)/.test(type) || (!value && type === 'object')) {
                      return stringifyPrimitive(value, type);
                  } else {
                      return stringifyReference(value);
                  }
              }
              if (!keys && window.JSON && typeof window.JSON.stringify === 'function') {
                  return window.JSON.stringify(value);
              }
  
              return str("", { "": value });
          }
  
          that.defineIndexProperty = function (index) {
              if (!(index in that)) {
                  var defineProperty = function (obj, property, path, context) {
                      var newValue = obj[property];
                      var oldValue = newValue;
                      var getter = function () {
                          return oldValue;
                      }
                      var setter = function (val) {
                          newValue = val;
                          if (oldValue !== newValue) {
                              var oldValueArg = oldValue;
                              oldValue = newValue;
                              if (typeof notifier === "function") {
                                  var index = array.indexOf(context);
                                 
                                  var propertyPath = "";
                                  var getPath = function (obj, path) {
                                      Object.getOwnPropertyNames(obj).forEach(function (name) {
                                          var type = $.type(obj[name]);
                                          if (type == "array" || type == "object") {
                                              getPath(obj[name], path + "." + name);
                                          }
                                          else if (property === name) {
                                              propertyPath = path + "." + name;
                                          }
                                      });
                                  }
                                  getPath(context, index);
                            
                                  notifier({ object: that, type: 'update', path: propertyPath, index: index, name: property, newValue: newValue, oldValue: oldValueArg });
                              }
                          }
                          oldValue = newValue;
                          return newValue;
                      }
                      if (obj[property] != undefined && property != "length") {
                          if (Object.defineProperty) 
                              Object.defineProperty(obj, property, {
                                  get: getter,
                                  set: setter
                              });
                          else if (Object.prototype.__defineGetter__ && Object.prototype.__defineSetter__) {
                              Object.prototype.__defineGetter__.call(obj, property, getter);
                              Object.prototype.__defineSetter__.call(obj, property, setter);
                          }
                      }
                  }
  
                  var defineProperties = function (obj, path, context) {
                      var type = $.type(obj);
                      if (/(number|float|int|integer|string|boolean)/.test(type)) {
                          return;
                      }
  
                      if (obj === undefined) {
                          return;
                      }
  
                      Object.getOwnPropertyNames(obj).forEach(function (name) {
                          var type = $.type(obj[name]);
                          if (type == "array" || type == "object") {
                              defineProperty(obj, name, path + "." + name, context);
                              defineProperties(obj[name], path + "." + name, context);
                          }
                          else {
                              defineProperty(obj, name, path + "." + name, context);
                          }
                      });
                  }
  
                  Object.defineProperty(that, index, {
                      configurable: true,
                      enumerable: true,
                      get: function () {
                          return array[index];
                      },
                      set: function (newValue) {
                          var oldValue = array[index];
                          if (that.toJSON(null, oldValue) != that.toJSON(null, newValue)) {
                              array[index] = newValue;
                              if (typeof notifier === "function") {
                                  notifier({ object: that, type: 'update', path: index.toString(), index: index, name: "index", newValue: newValue, oldValue: oldValue });
                              }
                              defineProperties(newValue, index, newValue);
                          }
                      }
                  });
                  defineProperties(that[index], index, that[index]);
              }
          }
  
          that.push = function () {
              var index;
              for (var i = 0, ln = arguments.length; i < ln; i++) {
                  index = array.length;
                  array.push(arguments[i]);
                  that.defineIndexProperty(index);
                  if (typeof notifier === "function") {
                      notifier({ object: that, type: 'add', name: "length", index: index, newValue: array.length, oldValue: index });
                  }
              }
              return array.length;
          };
  
          that.pop = function () {
              if (~array.length) {
                  var index = array.length - 1,
                      item = array.pop();
                  delete that[index];
                  if (typeof notifier === "function") {
                      notifier({ object: that, type: 'delete', name: "length", index: index, newValue: array.length, oldValue: index });
                  }
                  return item;
              }
          };
  
          that.unshift = function () {
              var index = array.length;
              for (var i = 0, ln = arguments.length; i < ln; i++) {
                  array.splice(i, 0, arguments[i]);
                  that.defineIndexProperty(array.length - 1);
              }
              if (typeof notifier === "function") {
                  notifier({ object: that, type: 'add', index: 0, name: "length", newValue: array.length, oldValue: index });
              }
              return array.length;
          };
  
          that.shift = function () {
              var index = array.length;
              if (~array.length) {
                  var item = array.shift();
                  array.length === 0 && delete that[index];
                  if (typeof notifier === "function") {
                      notifier({ object: that, type: 'delete', index: index, name: "length", newValue: array.length, oldValue: index });
                  }
                  return item;
              }
          };
  
          that.slice = function (start, end, observeFunction) {
              var newArray = array.slice(start, end);
              var observableArray = new $.jqx.observableArray(newArray, observeFunction);
              return observableArray;
          }
  
          that.splice = function (index, howMany, observeFunction) {
              var removed = [],
                  item,
                  pos;
  
              index = !~index ? array.length - index : index;
  
              howMany = (howMany == null ? array.length - index : howMany) || 0;
  
              while (howMany--) {
                  item = array.splice(index, 1)[0];
                  removed.push(item);
                  delete that[array.length];
                  if (typeof notifier === "function") {
                      notifier({ object: that, type: 'delete', index: index, name: "length", newValue: -1, oldValue: index });
                  }
              }
  
              for (var i = 2, ln = arguments.length; i < ln; i++) {
                  array.splice(index, 0, arguments[i]);
                  that.defineIndexProperty(array.length - 1);
                  if (typeof notifier === "function") {
                      notifier({ object: that, type: 'add', index: index, name: "length", newValue: array.length - 1, oldValue: index });
                  }
                  index++;
              }
  
              var observableArray = new $.jqx.observableArray(removed, observeFunction);
              return observableArray;
          };
  
          Object.defineProperty(that, "length", {
              configurable: false,
              enumerable: true,
              get: function () {
                  return array.length;
              },
              set: function (value) {
                  var n = Number(value);
                  if (n % 1 === 0 && n >= 0) {
                      if (n < array.length) {
                          that.splice(n);
                      } else if (n > array.length) {
                          that.push.apply(that, new Array(n - array.length));
                      }
                  } else {
                      throw new RangeError("Invalid array length");
                  }
                  return value;
              }
          });
  
          $.jqx.observableArray.prototype.fromArray = function (array, observeFunction) {
              var observableArray = new $.jqx.observableArray(array, observeFunction);
              return observableArray;
          }
  
          $.jqx.observableArray.prototype.clone = function () {
              var observableArray = new $.jqx.observableArray(array, observeFunction);
              observableArray.observing = that.observing;
              observableArray.changes = that.changes;
              observableArray.notifier = that.notifier;
              return observableArray;
          }
  
          that.remove = function (index) {
              if (index < 0 || index >= that.length) {
                  throw new Error('Invalid index : ' + index);
              }
              if (that.hasOwnProperty(index)) {
                  var oldValue = that[index];
                  that[index] = undefined;
                  array[index] = undefined;
                  if (typeof notifier === "function") {
                      notifier({ object: that, type: 'delete', index: index, name: "index", newValue: undefined, oldValue: oldValue });
                  }
                  return true;
              }
              return false;
          };
  
          that.concat = function (args, observeFunction) {
              var newArray = array.concat(args);
              var observableArray = new $.jqx.observableArray(newArray, observeFunction);
              return observableArray;
          };
  
          Object.getOwnPropertyNames(Array.prototype).forEach(function (name) {
              if (!(name in that)) {
                  var fn = function () {
                      var tmp = that.observing;
                      that.observing = false;
                      var arrayFn = array[name];
                      var result = arrayFn.apply(array, arguments);
                      that.observing = tmp;
                      return result;
                  }
                  Object.defineProperty(that, name, {
                      configurable: false,
                      enumerable: true,
                      writeable: false,
                      value: fn
                  });
              }
          });
  
  
          that.set = function (index, value) {
              if ($.type(index) == "string" && index.split(".").length > 1) {
                  var items = index.split(".");
                  var obj = that;
                  for (var i = 0; i < items.length; i++) {
                      if (i === 0) {
                          if (items[i] >= that.length) {
                              throw new Error("Invalid Index: " + index);
                          }
                      }
                      if (i < items.length - 1) {
                          obj = obj[items[i]];
                      }
                      else {
                          obj[items[i]] = value;
                      }
                  }
                  return true;
              }
              if (index >= that.length) {
                  that.push(value);
              }
              else {
                  that[index] = value;
              }
              return true;
          }
  
          that.get = function (index) {
              return that[index];
          }
  
          if (items instanceof Array) {
              that.push.apply(that, items);
          }
  
          notifier = function () {
              if (!that.observing) {
                  return;
              }
  
              if (arguments && arguments[0]) {
                  that.changes.push(arguments[0]);
              }
  
              if (observeFunction) {
                  observeFunction.apply(that, arguments);
              }
              if (that.notifier) {
                  that.notifier.apply(that, arguments);
              }
          }
        
          return that;
      }
  
      $.jqx.formatDate = function(value, format, calendar)
      {
          var result = $.jqx.dataFormat.formatdate(value, format, calendar);
          return result;
      }
  
      $.jqx.formatNumber = function (value, format, calendar) {
          var result = $.jqx.dataFormat.formatnumber(value, format, calendar);
          return result;
      }
  
      $.jqx.dataAdapter = function (source, options) {
          if (source != undefined) {
              if (source.dataFields !== undefined) {
                  source.datafields = source.dataFields;
              }
              if (source.dataType !== undefined) {
                  source.datatype = source.dataType;
              }
              if (source.localData !== undefined) {
                  source.localdata = source.localData;
              }
              if (source.sortColumn !== undefined) {
                  source.sortcolumn = source.sortColumn;
              }
              if (source.sortDirection !== undefined) {
                  source.sortdirection = source.sortDirection;
              }
              if (source.sortOrder !== undefined) {
                  source.sortdirection = source.sortOrder;
              }
              if (source.formatData !== undefined) {
                  source.formatdata = source.formatData;
              }
              if (source.processData !== undefined) {
                  source.processdata = source.processData;
              }
              if (source.pageSize !== undefined) {
                  source.pagesize = source.pageSize;
              }
              if (source.pageNum !== undefined) {
                  source.pagenum = source.pageNum;
              }
              if (source.updateRow !== undefined) {
                  source.updaterow = source.updateRow;
              }
              if (source.addRow !== undefined) {
                  source.addrow = source.addRow;
              }
              if (source.deleteRow !== undefined) {
                  source.deleterow = source.deleteRow;
              }
              if (source.contentType !== undefined) {
                  source.contenttype = source.contentType;
              }
              if (source.totalRecords != undefined) {
                  source.totalrecords = source.totalRecords;
              }
              if (source.loadError != undefined) {
                  source.loadError = source.loadError;
              }
              if (source.sortComparer != undefined) {
                  source.sortcomparer = source.sortComparer;
              }
          }
  
          this._source = source;
          this._options = options || {};
          if (source.beforeLoadComplete != undefined) {
              this._options.beforeLoadComplete = this._source.beforeLoadComplete;
          }
          if (source.downloadComplete != undefined) {
              this._options.downloadComplete = this._source.downloadComplete;
          }
          if (source.loadComplete != undefined) {
              this._options.loadComplete = this._source.loadComplete;
          }
          if (source.autoBind != undefined) {
              this._options.downloadComplete = this._source.autoBind;
          }
          if (source.formatData != undefined) {
              this._options.formatData = this._source.formatData;
          }
          if (source.loadError != undefined) {
              this._options.loadError = this._source.loadError;
          }
          if (source.beforeSend != undefined) {
              this._options.beforeSend = this._source.beforeSend;
          }
          if (source.contentType != undefined) {
              this._options.contentType = this._source.contentType;
          }
          if (source.async != undefined) {
              this._options.async = this._source.async;
          }
          if (source.loadServerData != undefined) {
              this._options.loadServerData = this._source.loadServerData;
          }
          if (source.uniqueDataFields != undefined) {
              this._options.uniqueDataFields = this._source.uniqueDataFields;
          }
  
          this.records = new Array();
          this._downloadComplete = new Array();
          this._bindingUpdate = new Array();
  
          if (source != undefined && source.localdata != null && typeof source.localdata == "function") {
              var localData = source.localdata();
              if (localData != null) {
                  source._localdata = source.localdata;
                  var me = this;
                  if (source._localdata.subscribe) {
                      me._oldlocaldata = [];
                      source._localdata.subscribe(function (value) {
                          var deepClone = function (objThing) {
                              if ($.isArray(objThing)) {
                                  return $.makeArray(deepClone($(objThing)));
                              }
                              return $.extend(true, {}, objThing);
                          };
                          if (me.suspendKO == false || me.suspendKO == undefined || me._oldlocaldata.length == 0) {
                              me._oldlocaldata = deepClone(value);
                          }
                      }, source._localdata, 'beforeChange');
  
                      source._localdata.subscribe(function (value) {
                          if (me.suspendKO == false || me.suspendKO == undefined) {
                              var changeType = "";
                              me._oldrecords = me.records;
                              if (me._oldlocaldata.length == 0) {
                                  source.localdata = source._localdata();
                              }
  
                              if (me._oldlocaldata.length == 0) {
                                  changeType = 'change';
                              }
                              else {
                                  if (value) {
                                      if (me._oldlocaldata.length == value.length) {
                                          changeType = 'update';
                                      }
                                      if (me._oldlocaldata.length > value.length) {
                                          changeType = 'remove';
                                      }
                                      if (me._oldlocaldata.length < value.length) {
                                          changeType = 'add';
                                      }
                                  }
                              }
                              me.dataBind(null, changeType);
                          }
                      }, source._localdata, 'change');
  
                      me._knockoutdatasource = true;
                  }
  
                  source.localdata = localData;
              }
          }
          if (this._options.autoBind == true) {
              this.dataBind();
          }
      }
  
      $.jqx.dataAdapter.prototype = {
          getrecords: function () {
              return this.records;
          },
  
          beginUpdate: function () {
              this.isUpdating = true;
          },
  
          endUpdate: function (refresh) {
              this.isUpdating = false;
              if (refresh != false) {
                  if (this._changedrecords && this._changedrecords.length > 0) {
                      this.callBindingUpdate("update");
                      this._changedrecords = [];
                  }
                  else {
                      this.dataBind(null, "");
                  }
              }
          },
  
          formatDate: function(value, format, calendar)
          {
              var result = $.jqx.dataFormat.formatdate(value, format, calendar);
              return result;
          },
  
          formatNumber: function (value, format, calendar) {
              var result = $.jqx.dataFormat.formatnumber(value, format, calendar);
              return result;
          },
  
          dataBind: function (objectuniqueId, collectionChanged) {
              if (this.isUpdating == true)
                  return;
  
              var source = this._source;
              if (!source)
                  return;
  
              if (source.generatedfields) {
                  source.datafields = null;
                  source.generatedfields = null;
              }
  
              $.jqx.dataFormat.datescache = new Array();
              if (source.dataFields != null) {
                  source.datafields = source.dataFields;
              }
  
              if (source.recordstartindex == undefined) {
                  source.recordstartindex = 0;
              }
              if (source.recordendindex == undefined) {
                  source.recordendindex = 0;
              }
              if (source.loadallrecords == undefined) {
                  source.loadallrecords = true;
              }
              if (source.root == undefined) source.root = '';
              if (source.record == undefined) source.record = '';
  
              if (source.sort != undefined) {
                  this.sort = source.sort;
              }
  
              if (source.filter != undefined) {
                  this.filter = source.filter;
              }
              else this.filter = null;
  
              if (source.sortcolumn != undefined) {
                  this.sortcolumn = source.sortcolumn;
              }
  
              if (source.sortdirection != undefined) {
                  this.sortdirection = source.sortdirection;
              }
  
              if (source.sortcomparer != undefined) {
                  this.sortcomparer = source.sortcomparer;
              }
  
              this.records = new Array();
              var options = this._options || {};
              this.virtualmode = options.virtualmode != undefined ? options.virtualmode : false;
              this.totalrecords = options.totalrecords != undefined ? options.totalrecords : 0;
              this.pageable = options.pageable != undefined ? options.pageable : false;
              this.pagesize = options.pagesize != undefined ? options.pagesize : 0;
              this.pagenum = options.pagenum != undefined ? options.pagenum : 0;
              this.cachedrecords = options.cachedrecords != undefined ? options.cachedrecords : new Array();
              this.originaldata = new Array();
              this.recordids = new Array();
              this.updaterow = options.updaterow != undefined ? options.updaterow : null;
              this.addrow = options.addrow != undefined ? options.addrow : null;
              this.deleterow = options.deleterow != undefined ? options.deleterow : null;
              this.cache = options.cache != undefined ? options.cache : false;
              this.unboundmode = false;
              if (source.formatdata != undefined) {
                  options.formatData = source.formatdata;
              }
              if (source.data != undefined) {
                  if (options.data == undefined) {
                      options.data = {};
                  }
                  $.extend(options.data, source.data);
              }
  
              if (source.mapChar != undefined) {
                  source.mapchar = source.maxChar;
              }
  
              if (source.mapchar != undefined) {
                  this.mapChar = source.mapchar ? source.mapchar : '>';
              }
              else {
                  this.mapChar = options.mapChar ? options.mapChar : '>';
              }
  
              if (options.unboundmode || source.unboundmode) {
                  this.unboundmode = options.unboundmode || source.unboundmode;
              }
  
              if (source.cache != undefined) {
                  this.cache = source.cache;
              }
  
              if (this.koSubscriptions) {
                  for (var subscription = 0; subscription < this.koSubscriptions.length; subscription++) {
                      this.koSubscriptions[subscription].dispose();
                  }
              }
              this.koSubscriptions = new Array();
  
              if (this.pagenum < 0) {
                  this.pagenum = 0;
              }
  
              var me = this;
  
              var datatype = source.datatype;
  
              if (source.datatype === 'csv' || source.datatype === 'tab' || source.datatype === 'tsv' || source.datatype == 'text')
                  datatype = 'text';
  
              var async = options.async != undefined ? options.async : true;
  
              if (source.async != undefined) {
                  async = source.async;
              }
  
              switch (datatype) {
                  case "local":
                  case "array":
                  case "observablearray":
                  case "observableArray":
                  default:
                      if (source.localdata == undefined && source.length) {
                          source.localdata = new Array();
                          for (var i = 0; i < source.length; i++) {
                              source.localdata[source.localdata.length] = source[i];
                              source[i].uid = i;
                          }
                      }
                      if (source.beforeprocessing && $.isFunction(source.beforeprocessing)) {
                          source.beforeprocessing(source.localdata);
                      }
  
                      var length = source.localdata.length;
                      this.totalrecords = this.virtualmode ? (source.totalrecords || length) : length;
  
                      if (this.unboundmode) {
                          this.totalrecords = this.unboundmode ? (source.totalrecords || length) : length;
                          var datafieldslength = source.datafields ? source.datafields.length : 0;
                          if (datafieldslength > 0) {
                              for (var i = 0; i < this.totalrecords; i++) {
                                  var record = {};
                                  for (var j = 0; j < datafieldslength; j++) {
                                      record[source.datafields[j].name] = "";
                                  }
                                  record.uid = i;
                                  source.localdata[source.localdata.length] = record;
                              }
                          }
                      }
  
                      if (this.totalrecords == undefined) {
                          this.totalrecords = 0;
                      }
  
                      var datafieldslength = source.datafields ? source.datafields.length : 0;
                      var getrecord = function (record, datafieldslength) {
                          var datarow = {};
                          for (var j = 0; j < datafieldslength; j++) {
                              var datafield = source.datafields ? source.datafields[j] : {};
                              var value = '';
                              if (undefined == datafield || datafield == null) {
                                  continue;
                              }
  
                              if (datafield.map) {
                                  if ($.isFunction(datafield.map)) {
                                      value = datafield.map(record);
                                  }
                                  else {
                                      var splitMap = datafield.map.split(me.mapChar);
                                      if (splitMap.length > 0) {
                                          var datarecord = record;
                                          for (var p = 0; p < splitMap.length; p++) {
                                              if (!datarecord) continue;
                                              datarecord = datarecord[splitMap[p]];
                                          }
                                          value = datarecord;
                                      }
                                      else {
                                          value = record[datafield.map];
                                      }
                                  }
  
                                  if (value != undefined && value != null) {
                                      value = value.toString();
                                  }
                                  else {
                                      if (value == undefined && value != null) {
                                          value = '';
                                      }
                                  }
                              }
                              var isEmptyString = false;
                              // searches by both selectors when necessary.
                              if (value == '') {
                                  isEmptyString = true;
                                  value = record[datafield.name];
                                  if (value != undefined && value != null) {
                                      if (source._localdata && value.subscribe) {
                                          value = value();
                                      }
                                      else {
                                          if (datafield.type != "array") {
                                              if (datafield.type === 'date') {
                                                  if (value && value instanceof Date) {
                                                      value = value;
                                                  }
                                              }
                                              else {
                                                  value = value.toString();
                                              }
                                          }
                                      }
                                  }
                              }
                              if (value == "[object Object]" && datafield.map && isEmptyString) {
                                  value = '';
                              }
  
                              value = me.getvaluebytype(value, datafield);
                              if (datafield.displayname != undefined) {
                                  datarow[datafield.displayname] = value;
                              }
                              else {
                                  datarow[datafield.name] = value;
                              }
                          }
                          return datarow;
                      }
  
                      if (source._localdata) {
                          this._changedrecords = [];
                          this.records = new Array();
                          var localdata = source._localdata();
  
                          $.each(localdata, function (i, value) {
                              if (typeof value === 'string') {
                                  me.records.push(value);
                              }
                              else {
                                  var record = {};
                                  var _koindex = 0;
                                  var dataObject = this;
                                  $.each(this, function (obj, objvalue) {
                                      var map = null;
                                      var type = 'string';
                                      var dataFieldName = obj;
                                      if (datafieldslength > 0) {
                                          var hasField = false;
                                          var hasMap = false;
                                          for (var j = 0; j < datafieldslength; j++) {
                                              var datafield = source.datafields[j];
                                              if (datafield != undefined && (datafield.name == obj)) {
                                                  hasField = true;
                                                  map = datafield.map;
                                                  type = datafield.type;
                                                  dataFieldName = datafield.name;
                                                  break;
                                              }
                                              else if (datafield != undefined && datafield.map && (datafield.map.indexOf(obj) >= 0)) {
                                                  hasField = true;
                                                  map = datafield.map;
                                                  type = datafield.type;
                                                  dataFieldName = datafield.name;
                                                  hasMap = true;
                                                  var value = dataObject[obj];
                                                  if (map != null) {
                                                      var splitMap = map.split(me.mapChar);
                                                      if (splitMap.length > 0) {
                                                          var datarecord = dataObject;
                                                          for (var p = 0; p < splitMap.length; p++) {
                                                              datarecord = datarecord[splitMap[p]];
                                                          }
                                                          value = datarecord;
                                                      }
                                                      else {
                                                          value = dataObject[map];
                                                      }
                                                  }
  
                                                  if (type != 'string') {
                                                      value = me.getvaluebytype(value, { type: type });
                                                  }
                                                  record[dataFieldName] = value;
                                                  if (record[dataFieldName] != undefined) {
                                                      _koindex += record[dataFieldName].toString().length + record[dataFieldName].toString().substr(0, 1);
                                                  }
                                              }
                                          }
                                          if (!hasField) return true;
                                          if (hasMap) return true;
                                      }
  
                                      var isFunction = $.isFunction(dataObject[obj]);
                                      if (isFunction) {
                                          var value = dataObject[obj]();
                                          if (type != 'string') {
                                              value = me.getvaluebytype(value, { type: type });
                                          }
                                          record[obj] = value;
                                          if (dataObject[obj].subscribe) {
                                              var recordindex = i;
                                              me.koSubscriptions[me.koSubscriptions.length] = dataObject[obj].subscribe(function (value) {
                                                  var _changeindex = recordindex;
                                                  record[obj] = value;
                                                  var changedRecord = { index: _changeindex, oldrecord: record, record: record };
                                                  me._changedrecords.push(changedRecord);
                                                  if (me.isUpdating)
                                                      return;
  
                                                  me.callBindingUpdate("update");
                                                  me._changedrecords = [];
                                                  return false;
                                              });
                                          }
                                      }
                                      else {
                                          var value = dataObject[obj];
                                          if (map != null) {
                                              var splitMap = map.split(me.mapChar);
                                              if (splitMap.length > 0) {
                                                  var datarecord = dataObject;
                                                  for (var p = 0; p < splitMap.length; p++) {
                                                      datarecord = datarecord[splitMap[p]];
                                                  }
                                                  value = datarecord;
                                              }
                                              else {
                                                  value = dataObject[map];
                                              }
                                          }
  
                                          if (type != 'string') {
                                              value = me.getvaluebytype(value, { type: type });
                                          }
                                          record[dataFieldName] = value;
                                          if (record[dataFieldName] != undefined) {
                                              _koindex += record[dataFieldName].toString().length + record[dataFieldName].toString().substr(0, 1);
                                          }
                                      }
                                  });
  
                                  var recordid = me.getid(source.id, dataObject, i);
                                  record.uid = recordid;
                                  me.records.push(record);
                      
                                  record._koindex = _koindex;
                                  if (me._oldrecords) {
                                      var _changeindex = me.records.length - 1;
                                      if (collectionChanged == 'update') {
                                          if (me._oldrecords[_changeindex]._koindex != _koindex) {
                                              var changedRecord = { index: _changeindex, oldrecord: me._oldrecords[_changeindex], record: record };
                                              me._changedrecords.push(changedRecord);
                                          }
                                      }
                                  }
                              }
                          });
                          if (collectionChanged == 'add') {
                              var length = me.records.length;
                              for (var i = 0; i < length; i++) {
                                  var record = me.records[i];
                                  var hasOldRecord = false;
                                  for (var p = 0; p < me._oldrecords.length; p++) {
                                      if (me._oldrecords[p]._koindex === record._koindex) {
                                          hasOldRecord = true;
                                          break;
                                      }
                                  }
                                  if (!hasOldRecord) {
                                      me._changedrecords.push({ index: i, oldrecord: null, record: record, position: (i != 0 ? "last" : "first") });
                                  }
                              }
                          }
                          else if (collectionChanged == 'remove') {
                              var length = me._oldrecords.length;
                              for (var i = 0; i < length; i++) {
                                  var oldrecord = me._oldrecords[i];
                                  if (!me.records[i]) {
                                      me._changedrecords.push({ index: i, oldrecord: oldrecord, record: null });
                                  }
                                  else {
                                      if (me.records[i]._koindex != oldrecord._koindex) {
                                          me._changedrecords.push({ index: i, oldrecord: oldrecord, record: null });
                                      }
                                  }
                              }
                          }
                      }
                      else {
                          if (!$.isArray(source.localdata)) {
                              this.records = new Array();
                              var fields = 0;
                              var generatedfields = new Array();
                              $.each(source.localdata, function (i) {
                                  var recordid = me.getid(source.id, this, i);
                                  if (datafieldslength == 0) {
                                      if (!(typeof this === "string" || this instanceof String)) {
                                          for (var obj in this) {
                                              fields++;
                                              var valueType = $.type(this[obj]);
  
                                              generatedfields.push({ name: obj, type: valueType });
                                          }
                                          datafieldslength = fields;
                                          source.datafields = generatedfields;
                                          source.generatedfields = generatedfields;
                                      }
                                  }
                                  if (datafieldslength > 0) {
                                      var record = this;
                                      var datarow = getrecord(record, datafieldslength);
                                      datarow.uid = recordid;
                                      me.records[me.records.length] = datarow;                                  
                                  }
                                  else {
                                      this.uid = recordid;
                                      me.records[me.records.length] = this;
                                  }
                              });
                          }
                          else {
                              if (datafieldslength == 0) {
                                  var fields = 0;
                                  var generatedfields = new Array();
  
                                  $.each(source.localdata, function (i, value) {
                                //      var record = $.extend({}, this);
                                      var record = new Object(this);
                                      if (typeof value === "string")
                                      {
                                          me.records = source.localdata;
                                          return false;
                                      }
                                      else {
                                          var recordid = me.getid(source.id, record, i);
                                          if (typeof (recordid) === "object") {
                                              recordid = i;
                                          }
                                          record.uid = recordid;
                                          if (i == 0) {
                                              for (var obj in this) {
                                                  fields++;
                                                  var valueType = $.type(this[obj]);
  
                                                  generatedfields.push({ name: obj, type: valueType });
                                              }
                                              datafieldslength = fields;
                                              source.datafields = generatedfields;
                                              source.generatedfields = generatedfields;
                                          }
                                          if (datafieldslength > 0) {
                                              var datarow = getrecord(record, datafieldslength);
                                              datarow.uid = recordid;
                                              me.records[me.records.length] = datarow;
                                          }
                                          else {
                                              me.records[me.records.length] = record;
                                          }
                                      }
                                  });
                              }
                              else {
                                  $.each(source.localdata, function (i) {
                                      var record = this;
                                      var datarow = getrecord(record, datafieldslength);
                                      var recordid = me.getid(source.id, datarow, i);
                                      if (typeof (recordid) === "object") {
                                          recordid = i;
                                      }
                                //      var record = $.extend({}, datarow);
                                      var record = new Object(datarow);
                                      record.uid = recordid;
                                      me.records[me.records.length] = record;
                                  });
                              }
                          }
                      }
  
                      this.originaldata = source.localdata;
                      this.cachedrecords = this.records;
                      this.addForeignValues(source);
                      if (options.uniqueDataFields) {
                          var uniquerecords = this.getUniqueRecords(this.records, options.uniqueDataFields);
                          this.records = uniquerecords;
                          this.cachedrecords = uniquerecords;
                      }
  
                      if (options.beforeLoadComplete) {
                          var newRecords = options.beforeLoadComplete(me.records, this.originaldata);
                          if (newRecords != undefined) {
                              me.records = newRecords;
                              me.cachedrecords = newRecords;
                          }
                      }
  
                      if (options.autoSort && options.autoSortField) {
                          var tmpToString = Object.prototype.toString;
                          // Usages of autoSort/autoSortField indicate that we don't expect a function that returns a field name
                          // Declared field below to suppress linting errors.
                          var field = undefined;
                          Object.prototype.toString = (typeof field == "function") ? field : function () { return this[options.autoSortField] };
                          me.records.sort(function (value1, value2) {
                              if (value1 === undefined) { value1 = null; }
                              if (value2 === undefined) { value2 = null; }
                              if (value1 === null && value2 === null) {
                                  return 0;
                              }
                              if (value1 === null && value2 !== null) {
                                  return 1;
                              }
                              if (value1 !== null && value2 === null) {
                                  return -1;
                              }
  
                              value1 = value1.toString();
                              value2 = value2.toString();
                              if (value1 === null && value2 === null) {
                                  return 0;
                              }
                              if (value1 === null && value2 !== null) {
                                  return 1;
                              }
                              if (value1 !== null && value2 === null) {
                                  return -1;
                              }
                              if ($.jqx.dataFormat.isNumber(value1) && $.jqx.dataFormat.isNumber(value2)) {
                                  if (value1 < value2) { return -1; }
                                  if (value1 > value2) { return 1; }
                                  return 0;
                              }
                              else if ($.jqx.dataFormat.isDate(value1) && $.jqx.dataFormat.isDate(value2)) {
                                  if (value1 < value2) { return -1; }
                                  if (value1 > value2) { return 1; }
                                  return 0;
                              }
                              else if (!$.jqx.dataFormat.isNumber(value1) && !$.jqx.dataFormat.isNumber(value2)) {
                                  value1 = String(value1).toLowerCase();
                                  value2 = String(value2).toLowerCase();
                              }
  
                              try {
                                  if (value1 < value2) { return -1; }
                                  if (value1 > value2) { return 1; }
                              }
                              catch (error) {
                                  var er = error;
                              }
  
                              return 0;
                          });
                          Object.prototype.toString = tmpToString;
                      }
  
                      me.loadedData = source.localdata;
                      me.buildHierarchy();
  
                      if ($.isFunction(options.loadComplete)) {
                          options.loadComplete(source.localdata, me.records);
                      }
                      break;
                  case "json":
                  case "jsonp":
                  case "xml":
                  case "xhtml":
                  case "script":
                  case "text":
                  case "ics":
                      {
                          if (source.localdata != null && !source.url) {
                              if ($.isFunction(source.beforeprocessing)) {
                                  source.beforeprocessing(source.localdata);
                              }
                              if (source.datatype === "xml") {
                                  me.loadxml(source.localdata, source.localdata, source);
                              }
                              else if (datatype === "text") {
                                  me.loadtext(source.localdata, source);
                              }
                              else if (datatype === "ics") {
                                  me.loadics(source.localdata, source);
                              }
                              else {
                                  me.loadjson(source.localdata, source.localdata, source);
                              }
                              me.addForeignValues(source);
                              if (options.uniqueDataFields) {
                                  var uniquerecords = me.getUniqueRecords(me.records, options.uniqueDataFields);
                                  me.records = uniquerecords;
                                  me.cachedrecords = uniquerecords;
                              }
  
                              if (options.beforeLoadComplete) {
                                  var newRecords = options.beforeLoadComplete(me.records, this.originaldata);
                                  if (newRecords != undefined) {
                                      me.records = newRecords;
                                      me.cachedrecords = newRecords;
                                  }
                              }
  
                              me.loadedData = source.localdata;
                              me.buildHierarchy.call(me);
                              if ($.isFunction(options.loadComplete)) {
                                  options.loadComplete(source.localdata, me.records);
                              }
                              me.callBindingUpdate(collectionChanged);
                              return;
                          }
  
                          var postdata = options.data != undefined ? options.data : {};
                          // call the source object's processdata function.
                          if (source.processdata) {
                              source.processdata(postdata);
                          }
                          // call the adapter's process data function.
                          if ($.isFunction(options.processData)) {
                              options.processData(postdata);
                          }
  
                          // call the adapter's format data function.
                          if ($.isFunction(options.formatData)) {
                              var newpostdata = options.formatData(postdata);
                              if (newpostdata != undefined) {
                                  postdata = newpostdata;
                              }
                          }
  
                          var contentType = 'application/x-www-form-urlencoded';
                          if (options.contentType) {
                              contentType = options.contentType;
                          }
  
                          var type = "GET";
                          if (source.type) {
                              type = source.type;
                          }
  
                          if (options.type) {
                              type = options.type;
                          }
  
                          var dataType = datatype;
                          if (datatype == "ics") dataType = "text";
                          if (source.url && source.url.length > 0) {
                              if ($.isFunction(options.loadServerData)) {
                                  me._requestData(postdata, source, options);
                              }
                              else {
                                  this.xhr = $.jqx.data.ajax({
                                      dataType: dataType,
                                      cache: this.cache,
                                      type: type,
                                      url: source.url,
                                      async: async,
                                      timeout: source.timeout,
                                      contentType: contentType,
                                      data: postdata,
                                      success: function (data, status, xhr) {
                                          if ($.isFunction(source.beforeprocessing)) {
                                              var tmpdata = source.beforeprocessing(data, status, xhr);
                                              if (tmpdata != undefined) {
                                                  data = tmpdata;
                                              }
                                          }
                                          if ($.isFunction(options.downloadComplete)) {
                                              var tmpdata = options.downloadComplete(data, status, xhr);
                                              if (tmpdata != undefined) {
                                                  data = tmpdata;
                                              }
                                          }
  
                                          if (data == null) {
                                              me.records = new Array();
                                              me.cachedrecords = new Array();
                                              me.originaldata = new Array();
  
                                              me.callDownloadComplete();
                                              if ($.isFunction(options.loadComplete)) {
                                                  options.loadComplete(new Array());
                                              }
                                              return;
                                          }
  
                                          var records = data;
                                          if (data.records) {
                                              records = data.records;
                                          }
  
                                          if (data.totalrecords != undefined) {
                                              source.totalrecords = data.totalrecords;
                                          }
                                          else if (data.totalRecords != undefined) {
                                              source.totalrecords = data.totalRecords;
                                          }
  
                                          if (source.datatype === "xml") {
                                              me.loadxml(null, records, source);
                                          }
                                          else if (datatype === "text") {
                                              me.loadtext(records, source);
                                          }
                                          else if (datatype === "ics") {
                                              me.loadics(records, source);
                                          }
                                          else {
                                              me.loadjson(null, records, source);
                                          }
  
                                          // add foreign values.
                                          me.addForeignValues(source);
  
                                          if (options.uniqueDataFields) {
                                              var uniquerecords = me.getUniqueRecords(me.records, options.uniqueDataFields);
                                              me.records = uniquerecords;
                                              me.cachedrecords = uniquerecords;
                                          }
  
                                          if (options.beforeLoadComplete) {
                                              var newRecords = options.beforeLoadComplete(me.records, data);
                                              if (newRecords != undefined) {
                                                  me.records = newRecords;
                                                  me.cachedrecords = newRecords;
                                              }
                                          }
  
                                          me.loadedData = data;
                                          me.buildHierarchy.call(me);
  
                                          me.callDownloadComplete();
                                          if ($.isFunction(options.loadComplete)) {
                                              options.loadComplete(data, status, xhr, me.records);
                                          }
                                      },
                                      error: function (xhr, status, error) {
                                          if ($.isFunction(source.loaderror)) { source.loaderror(xhr, status, error); }
                                          if ($.isFunction(options.loadError)) { options.loadError(xhr, status, error); }
                                          xhr = null;
                                          me.callDownloadComplete();
                                      },
                                      beforeSend: function (xhr, settings) {
                                          if ($.isFunction(options.beforeSend)) { options.beforeSend(xhr, settings); }
                                          if ($.isFunction(source.beforesend)) { source.beforesend(xhr, settings); }
                                      }
                                  });
                              }
                          }
                          else {
                              me.buildHierarchy(new Array());
                              me.callDownloadComplete();
                              if ($.isFunction(options.loadComplete)) {
                                  if (!data) {
                                      var data = {};
                                  }
                                  options.loadComplete(data);
                              }
                          }
                      }
                      break;
              }
              this.callBindingUpdate(collectionChanged);
          },
  
          buildHierarchy: function(dataRecords)
          {
              var source = this._source;
              var hierarchy = new Array();
              if (!source.datafields) {
                  return;
              }
  
              if (source.hierarchy && !source.hierarchy.reservedNames) {
                  source.hierarchy.reservedNames = {
                      leaf: "leaf",
                      parent: "parent",
                      expanded: "expanded",
                      checked: "checked",
                      selected: "selected",
                      level: "level",
                      icon: "icon",
                      data: "data"
                  }
              }
              else {
                  if (source.hierarchy) {
                      var names = source.hierarchy.reservedNames;
                      if (!names.leaf) names.leaf = "leaf";
                      if (!names.parent) names.parent = "parent";
                      if (!names.expanded) names.expanded = "expanded";
                      if (!names.checked) names.checked = "checked";
                      if (!names.selected) names.selected = "selected";
                      if (!names.level) names.level = "level";
                      if (!names.data) names.data = "data";
                  }
              }
  
              if (!source.hierarchy) {
                  return;
              }
  
              var that = this;
              var names = source.hierarchy.reservedNames;
              if (source.hierarchy.root) {
                  if (source.dataType == "xml") {
                      var hierarchy = this.getRecordsHierarchy('uid', 'parentuid', 'records', null, dataRecords);
                      this.hierarchy = hierarchy;
                      return hierarchy;
                  }
                  else {
                      this.hierarchy = this.records;
                      var root = source.hierarchy.root;
                      for (var i = 0; i < this.records.length; i++) {
                          var record = this.records[i];
                          if (!record) {
                              continue;
                          }
  
                          var addRecords = function (record) {
                              if (source.hierarchy.record) {
                                  record.records = record[root][source.hierarchy.record];
                              }
                              else {
                                  var splitMap = root.split(that.mapChar);
                                  var records = null;
                                  if (splitMap.length > 1) {
                                      var d = record;
                                      for (var p = 0; p < splitMap.length; p++) {
                                          if (d != undefined) {
                                              d = d[splitMap[p]];
                                          }
                                      }
                                      records = d;
                                  }
                                  else records = record[root];
                                  record.records = records;
                              }
                              if (record.records == null || (record.records && record.records.length == 0)) {
                                  record[names.leaf] = true;
                              }
                          }
                          addRecords(record);
                          record[names.level] = 0;
                          var recordid = this.getid(source.id, record, i);
                          record.uid = recordid;
                          record[names.parent] = null;
                          record[names.data] = record;
                          if (record[names.expanded] === undefined) {
                              record[names.expanded] = false;
                          }
                          var drillThrough = function (parent, records) {
                              if (!records) {
                                  parent.records = new Array();
                                  return;
                              }
  
                              for (var i = 0; i < records.length; i++) {
                                  var record = records[i];
                                  if (!record) {
                                      continue;
                                  }
  
                                  addRecords(record);
                                  record[names.level] = parent[names.level] + 1;
                                  record[names.parent] = parent;
                                  record[names.data] = record;
                                  var recordid = that.getid(source.id, record, i);
                                  if (recordid == i && source.id == null) {
                                      record.uid = parent.uid + "_" + recordid;
                                  }
                                  else {
                                      record.uid = recordid;
                                  }
  
                                  if (record[names.expanded] === undefined) {
                                      record[names.expanded] = false;
                                  }
                                  drillThrough(record, record.records);
                              }
                          }
                          drillThrough(record, record.records);
                      }
                  }             
                  return this.hierarchy;
              }
  
              if (source.hierarchy.keyDataField && source.hierarchy.parentDataField) {
                  var hierarchy = this.getRecordsHierarchy(source.hierarchy.keyDataField.name, source.hierarchy.parentDataField.name, 'records', null, dataRecords);
                  this.hierarchy = hierarchy;
                  return hierarchy;
              }
  
              if (source.hierarchy.groupingDataFields) {
                  var groups = new Array();
                  for (var i = 0; i < source.hierarchy.groupingDataFields.length; i++) {
                      groups.push(source.hierarchy.groupingDataFields[i].name);
                  }
  
                  var hierarchy = this.getGroupedRecords(groups, 'records', 'label', null, 'data', null, 'parent', dataRecords);
                  this.hierarchy = hierarchy;
                  return hierarchy;
              }
          },
  
          addRecord: function (record, position, parentID, virtualMode) {
              var that = this;
              var reservedNames = function()
              {
                  return {
                      leaf: "leaf",
                      parent: "parent",
                      expanded: "expanded",
                      checked: "checked",
                      selected: "selected",
                      level: "level",
                      icon: "icon",
                      data: "data"
                  }
              }
              if (record != undefined) {
                  if (parentID != undefined) {
                      if (this.hierarchy.length > 0) {
                          var traverse = function (records) {
                              if (records) {
                                  for (var i = 0; i < records.length; i++) {
                                      var r = records[i];
                                      if (r.uid == parentID) {
                                          var names = (that._source && that._source.hierarchy) ? that._source.hierarchy.reservedNames : null;  
                                          if (names == null) names = reservedNames();
  
                                          record[names.parent] = r;
                                          record[names.level] = r[names.level] + 1;
  
                                          if (!r.records) {
                                              r.records = new Array();
                                              r[names.leaf] = false;
                                          }
                                          else {
                                              r[names.leaf] = false;
                                          }
  
                                          if (position == 'last') {
                                              r.records.push(record);
                                          }
                                          else if (typeof position === 'number' && isFinite(position)) {
                                              r.records.splice(position, 0, record);
                                          }
                                          else {
                                              r.records.splice(0, 0, record);
                                          }
                                          return true;
                                      }
                                      if (r.records) {
                                          traverse(r.records);
                                      }
                                  }
                              }
                          }
                          traverse(this.hierarchy);
                      }
                  }
                  else {
                      if (this.hierarchy && this.hierarchy.length >= 0 && (this._source.hierarchy || virtualMode)) {
                          var names = (that._source && that._source.hierarchy) ? that._source.hierarchy.reservedNames : null;
                          if (names == null) names = reservedNames();
  
                          record[names.level] = 0;
  
                          if (position == 'last') {
                              this.hierarchy.push(record);
                          }
                          else if (typeof position === 'number' && isFinite(position)) {
                              this.hierarchy.splice(position, 0, record);
                          }
                          else {
                              this.hierarchy.splice(0, 0, record);
                          }
                      }
                      else {
                          if (position == 'last') {
                              this.records.push(record);
                          }
                          else if (typeof position === 'number' && isFinite(position)) {
                              this.records.splice(position, 0, record);
                          }
                          else {
                              this.records.splice(0, 0, record);
                          }
                      }
                      return true;
                  }
              }
              return false;
          },
  
          deleteRecord: function(uid)
          {
              var that = this;
              if (this.hierarchy.length > 0) {
                  var traverse = function (records) {
                      if (records) {
                          for (var i = 0; i < records.length; i++) {
                              var r = records[i];
                              if (r.uid == uid) {
                                  records.splice(i, 1);
                                  if (that.recordids[uid]) {
                                      delete that.recordids[uid];
                                  }
  
                                  var removeChildren = function (children) {
                                      for (var x = 0; x < children.length; x++) {
                                          var uid = children[x].uid;
                                          for (var j = 0; j < that.records.length; j++) {
                                              var r = that.records[j];
                                              if (r.uid == uid) {
                                                  that.records.splice(j, 1);
                                                  break;
                                              }
                                          }
                                          if (children[x].records) {
                                              removeChildren(children[x].records);
                                          }
                                      }
                                  }
                                  if (r.records) {
                                      removeChildren(r.records);                              
                                  }
                                  for (var j = 0; j < that.records.length; j++) {
                                      var r = that.records[j];
                                      if (r.uid == uid) {
                                          that.records.splice(j, 1);
                                          break;
                                      }
                                  }
                                  return true;
                              }
                              if (r.records) {
                                  traverse(r.records);
                              }
                          }
                      }
                  }
                  traverse(this.hierarchy);
              }
              else {
                  for (var i = 0; i < this.records.length; i++) {
                      var r = this.records[i];
                      if (r.uid == uid) {
                          this.records.splice(i, 1);
                          return true;
                      }
                  }
              }
              return false;
          },
  
          addForeignValues: function(source)
          {
              var me = this;
              var datafieldslength = source.datafields ? source.datafields.length : 0;
              for (var j = 0; j < datafieldslength; j++) {
                  var datafield = source.datafields[j];
                  if (datafield != undefined) {
                      if (datafield.values != undefined) {
                          if (datafield.value == undefined) datafield.value = datafield.name;
                          if (datafield.values['value'] == undefined) {
                              datafield.values['value'] = datafield.value;
                          }
  
                          var matchedIDs = new Array();
                          var start, end;
                          if (me.pageable && me.virtualmode) {
                              start = me.pagenum * me.pagesize;
                              end = start + me.pagesize;
                              if (end > me.totalrecords) {
                                  end = me.totalrecords;
                              }
                          }
                          else if (me.virtualmode) {
                              start = source.recordstartindex;
                              end = source.recordendindex;
                              if (end > me.totalrecords) {
                                  end = me.totalrecords;
                              }
                          }
                          else {
                              start = 0;
                              end = me.records.length;
                          }
  
                          for (var i = start; i < end; i++) {
                              var record = me.records[i];
                              var name = datafield.name;
                              var value = record[datafield.value];
  
                              if (matchedIDs[value] != undefined) {
                                  record[name] = matchedIDs[value];
                              }
                              else {
                                  for (var p = 0; p < datafield['values'].source.length; p++) {
                                      var sourcerecord = datafield.values.source[p];
                                      var sourcevalue = sourcerecord[datafield.values['value']];
                                      if (sourcevalue == undefined) {
                                          sourcevalue = sourcerecord.uid;
                                      }
                                      if (sourcevalue == value) {
                                          var label = sourcerecord[datafield.values['name']];
                                          record[name] = label;
                                          matchedIDs[value] = label;
                                          break;
                                      }
                                  }
                              }
                          }
                      }
                      else if (datafield.value != undefined) {
                          for (var i = 0; i < me.records.length; i++) {
                              var record = me.records[i];
                              record[datafield.name] = record[datafield.value];
                          }
                      }
                  }
              }
          },
  
          abort: function () {
              var me = this;
              if (this.xhr && this.xhr.readyState != 4) {
                  this.xhr.abort();
                  me.callDownloadComplete();
              }
          },
  
          _requestData: function (postdata, source, options) {
              var me = this;
              var success = function (requestedData) {
                  if (requestedData.totalrecords) {
                      source.totalrecords = requestedData.totalrecords;
                      me.totalrecords = requestedData.totalrecords;
                  }
                  if (requestedData.records) {
                      me.records = requestedData.records;
                      me.cachedrecords = requestedData.records;
                  }
                  // add foreign values.
                  me.addForeignValues(source);
  
                  if (options.uniqueDataFields) {
                      var uniquerecords = me.getUniqueRecords(me.records, options.uniqueDataFields);
                      me.records = uniquerecords;
                      me.cachedrecords = uniquerecords;
                  }
  
                  if (options.beforeLoadComplete) {
                      // beforeLoadComplete is set in jqxgrid.filter.js and ignores the second argument.
                      // Commented out the 'data' parameter to suppress linting errors
                      var newRecords = options.beforeLoadComplete(me.records /*,  data */);
                      if (newRecords != undefined) {
                          me.records = newRecords;
                          me.cachedrecords = newRecords;
                      }
                  }
                  for (var i = 0; i < me.records.length; i++) {
                      var record = me.records[i];
                      if (undefined == record) {
                          continue;
                      }
  
                      if (undefined == record.uid) {
                          record.uid = me.getid(source.id, record, i);
                      }
                  }
  
                  me.buildHierarchy.call(me);
                  if ($.isFunction(options.loadComplete)) {
                      options.loadComplete(requestedData);
                  }
                  me.callDownloadComplete();
              }
              options.loadServerData(postdata, source, success);
          },
  
          getUniqueRecords: function (records, dataFields) {
              if (records && dataFields) {
                  var length = records.length;
                  var datafieldslength = dataFields.length;
  
                  var uniqueRecords = new Array();
                  var lookupkeys = new Array();
                  // loop through all records.
                  for (var urec = 0; urec < length; urec++) {
                      var datarow = records[urec];
                      var lookupkey = "";
                      if (datarow == undefined)
                          continue;
                      // build lookup key from the datafield values.
                      for (var datafieldindex = 0; datafieldindex < datafieldslength; datafieldindex++) {
                          var datafield = dataFields[datafieldindex];
                          lookupkey += datarow[datafield] + "_";
                      }
                      // add the unique record.
                      if (!lookupkeys[lookupkey]) {
                          uniqueRecords[uniqueRecords.length] = datarow;
                      }
                      // add the lookup key.
                      lookupkeys[lookupkey] = true;
                  }
              }
  
              return uniqueRecords;
          },
  
          getAggregatedData: function (aggregates, calendar, records, level) {
              var dataRecords = records;
              if (!dataRecords) {
                  dataRecords = this.records;
              }
              var data = {};
              var dataValuesByAggregate = new Array();
              var length = dataRecords.length;
              if (length == 0) return;
              if (length == undefined) return;
              for (var i = 0; i < length; i++) {
                  var record = dataRecords[i];
                  for (var j = 0; j < aggregates.length; j++) {
                      var aggregate = aggregates[j];
                      var value = record[aggregate.name];
          //            if (value === null) continue;
                      if (aggregate.aggregates) {
                          data[aggregate.name] = data[aggregate.name] || {};
                          dataValuesByAggregate[aggregate.name] = dataValuesByAggregate[aggregate.name] || 0;
                          dataValuesByAggregate[aggregate.name]++;
                          var _customCalcFunc = function (aggObject) {
                              for (var obj in aggObject) {
                                  var oldValue = data[aggregate.name][obj];
                                  if (oldValue == null) {
                                      data[aggregate.name][obj] = 0;
                                      oldValue = 0;
                                  }
                                  if ($.isFunction(aggObject[obj])) {
                                      oldValue = aggObject[obj](oldValue, value, aggregate.name, record, level);
                                  }
                                  data[aggregate.name][obj] = oldValue;
                              }
                          }
  
                          var canParse = parseFloat(value);
                          if (isNaN(canParse)) canParse = false; else canParse = true;
                          if (canParse)
                              value = parseFloat(value);
  
                          if (typeof value === 'number' && isFinite(value)) {
                              $.each(aggregate.aggregates, function () {
                                  var oldValue = data[aggregate.name][this];
                                  if (oldValue == null) {
                                      oldValue = 0;
                                      if (this == 'min') oldValue = 9999999999999;
                                      if (this == 'max') oldValue = -9999999999999;
                                  }
                                  if (this == 'sum' || this == 'avg' || this == 'stdev'
                                  || this == 'stdevp' || this == 'var' || this == 'varp') {
                                      oldValue += parseFloat(value);
                                  }
                                  else if (this == 'product') {
                                      if (i == 0)
                                          oldValue = parseFloat(value);
                                      else
                                          oldValue *= parseFloat(value);
                                  }
                                  else if (this == 'min') {
                                      oldValue = Math.min(oldValue, parseFloat(value));
                                  }
                                  else if (this == 'max') {
                                      oldValue = Math.max(oldValue, parseFloat(value));
                                  }
                                  else if (this == 'count') {
                                      oldValue++;
                                  }
                                  else if (typeof (this) == 'object') {
                                      _customCalcFunc(this);
                                      return;
                                  }
                                  data[aggregate.name][this] = oldValue;
                              });
                          }
                          else {
                              $.each(aggregate.aggregates, function () {
                                  if (this == 'min' || this == 'max' || this == 'count' || this == 'product' || this == 'sum'
                                   || this == 'avg' || this == 'stdev'
                                  || this == 'stdevp' || this == 'var' || this == 'varp') {
                                      if (value === null) return true;
          
                                      var oldValue = data[aggregate.name][this];
                                      if (oldValue == null) {
                                          oldValue = 0;
                                      }
                                      data[aggregate.name][this] = oldValue;
                                      return true;
                                  }
  
                                  if (typeof (this) == 'object') {
                                      _customCalcFunc(this);
                                  }
                              });
                          }
                      }
                  }
              }
  
              for (var j = 0; j < aggregates.length; j++) {
                  var aggregate = aggregates[j];
                  if (!data[aggregate.name]) {
                      data[aggregate.name] = {};
                      $.each(aggregate.aggregates, function (index) {
                          data[aggregate.name][this] = 0;
                      });
                  }
  
                  if (data[aggregate.name]['avg'] != undefined) {
                      var value = data[aggregate.name]['avg'];
                      var dataValues = dataValuesByAggregate[aggregate.name];
                      if (dataValues === 0 || dataValues == undefined) {
                          data[aggregate.name]['avg'] = 0;
                      }
                      else {
                          data[aggregate.name]['avg'] = value / dataValues;
                      }
                  }
                  else if (data[aggregate.name]['count'] != undefined) {
                      data[aggregate.name]['count'] = length;
                  }
  
                  // stdev, stdevp, var, varp.
                  // stdev - Standard deviation on a sample.
                  // varp - Variance on an entire population.
                  // var - Variance on a sample.
                  if (data[aggregate.name]['stdev'] || data[aggregate.name]['stdevp']
                  || data[aggregate.name]['var'] || data[aggregate.name]['varp']) {
                      $.each(aggregate.aggregates, function (index) {
                          if (this == 'stdev' || this == 'var' || this == 'varp' || this == 'stdevp') {
                              var value = data[aggregate.name][this];
                              var count = length;
                              var average = (value / length);
                              var sumSq = 0.0;
                              for (var i = 0; i < length; i++) {
                                  var record = dataRecords[i];
                                  var recordvalue = record[aggregate.name];
                                  sumSq += (recordvalue - average) * (recordvalue - average);
                              }
  
                              var denominator = (this == 'stdevp' || this == 'varp') ? count : count - 1;
                              if (denominator == 0)
                                  denominator = 1;
  
                              if (this == 'var' || this == 'varp') {
                                  data[aggregate.name][this] = sumSq / denominator;
                              }
                              else if (this == 'stdevp' || this == 'stdev') {
                                  data[aggregate.name][this] = Math.sqrt(sumSq / denominator);
                              }
                          }
                      });
                  }
  
                  if (aggregate.formatStrings) {
                      $.each(aggregate.aggregates, function (index) {
                          var formatString = aggregate.formatStrings[index];
                          if (formatString) {
                              if (this == 'min' || this == 'max' || this == 'count' || this == 'product' || this == 'sum'
                                   || this == 'avg' || this == 'stdev'
                                  || this == 'stdevp' || this == 'var' || this == 'varp') {
                                  var value = data[aggregate.name][this];
                                  data[aggregate.name][this] = $.jqx.dataFormat.formatnumber(value, formatString, calendar);
                              }
                              else if (typeof this == 'object') {
                                  for (var obj in this) {
                                      var value = data[aggregate.name][obj];
                                      data[aggregate.name][obj] = $.jqx.dataFormat.formatnumber(value, formatString, calendar);
                                  }
                              }
                          }
                      });
                  }
              }
              return data;
          },
  
          bindDownloadComplete: function (id, func) {
              this._downloadComplete[this._downloadComplete.length] = { id: id, func: func };
  
          },
  
          unbindDownloadComplete: function (id) {
              for (var i = 0; i < this._downloadComplete.length; i++) {
                  if (this._downloadComplete[i].id == id) {
                      this._downloadComplete[i].func = null;
                      this._downloadComplete.splice(i, 1);
                      break;
                  }
              }
          },
  
          callDownloadComplete: function () {
              for (var complete = 0; complete < this._downloadComplete.length; complete++) {
                  var downloadComplete = this._downloadComplete[complete];
                  if (downloadComplete.func != null) {
                      downloadComplete.func();
                  }
              }
          },
  
          setSource: function (source) {
              this._source = source;
          },
  
          generatekey: function () {
              var S4 = function () {
                  return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
              };
              return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
          },
  
          getGroupedRecords: function (groups, collectionName, groupName, mappingFields, recordName, valueName, parentName, data, startIndex) {
              var visualRows = 0;
              var self = this;
              if (!startIndex) startIndex = 0;
              var groupHashCodes = new Array();
              for (var iGroupColumn = 0; iGroupColumn < groups.length; iGroupColumn++) {
                  groupHashCodes[iGroupColumn] = self.generatekey();
              }
  
              if (!collectionName) {
                  collectionName = 'items';
              }
  
              if (!groupName) {
                  groupName = 'group';
              }
  
              if (!recordName) {
                  recordName = 'record';
              }
  
              if (!parentName) {
                  parentName = 'parentItem';
              }
  
              if (undefined === valueName) {
                  valueName = 'value';
              }
  
              var grouprecords = new Array();
              var grouprecordsindex = 0;
              var hashRowGroups = new Array();
              var groupslength = groups.length;
              var groupsHierarchy = new Array();
              if (!data) {
                  var data = this.records;
              }
  
              var dataLength = data.length;
  
              var itemByRecord = function (record) {
                  var itemObj = record;
                  if (mappingFields) {
                      $.each(mappingFields, function () {
                          if (this.name && this.map) {
                              itemObj[this.map] = itemObj[this.name];
                          }
                      });
                  }
  
                  return itemObj;
              }
  
              for (var obj = 0; obj < dataLength; obj++) {
                  var item = itemByRecord(data[obj]);
                  var id = item[self.uniqueId];
                  var itemKeysHierarchy = new Array();
                  var keys = 0;
                  for (iGroupColumn = 0; iGroupColumn < groupslength; iGroupColumn++) {
                      var group = groups[iGroupColumn];
                      var value = item[group];
  
                      if (null == value)
                          continue;
  
                      itemKeysHierarchy[keys++] = { value: value, hash: groupHashCodes[iGroupColumn] };
                  }
  
                  if (itemKeysHierarchy.length != groupslength)
                      break;
  
                  var parentItem = null;
  
                  var lookupKey = "";
                  var iLevel = -1;
                  for (var q = 0; q < itemKeysHierarchy.length; q++) {
                      iLevel++;
                      var itemKey = itemKeysHierarchy[q].value;
                      var columnHash = itemKeysHierarchy[q].hash;
                      lookupKey = lookupKey + "_" + columnHash + "_" + itemKey;
                      if (hashRowGroups[lookupKey] != undefined && hashRowGroups[lookupKey] != null) {
                          parentItem = hashRowGroups[lookupKey];
                          continue;
                      }
                      if (parentItem == null) {
                          parentItem = { level: 0 };
                          parentItem[parentName] = null;
                          parentItem[groupName] = itemKey;
                          parentItem[recordName] = item;
                          if (item.expanded !== undefined) {
                              parentItem.expanded = item.expanded;
                          }
                          else
                          {
                              parentItem.expanded = false;
                          }
  
                          if (valueName) {
                              parentItem[valueName] = item[valueName];
                          }
                          parentItem[collectionName] = new Array();
                          var uid = grouprecords.length + startIndex;
                          if (!this._source.id || typeof item.uid === "number" || isFinite(item.uid)) {
                              uid = "Row" + uid;
                          }
                          parentItem.uid = uid;
                          grouprecords[grouprecordsindex++] = parentItem;
                      }
                      else {
                          var subItem = { level: parentItem.level + 1 };
                          subItem[parentName] = parentItem;
                          subItem[groupName] = itemKey;
                          subItem[collectionName] = new Array();
                          subItem[recordName] = item;
                          if (item.expanded !== undefined) {
                              subItem.expanded = item.expanded;
                          }
                          else {
                              subItem.expanded = false;
                          }
  
                          if (valueName) {
                              subItem[valueName] = item[valueName];
                          }
                          subItem.uid = parentItem.uid + "_" + parentItem[collectionName].length;
                          parentItem[collectionName][parentItem[collectionName].length] = subItem;
                          parentItem = subItem;
                      }
  
                      hashRowGroups[lookupKey] = parentItem;
                  }
  
                  if (item) {
                      item.leaf = true;
                  }
  
                  if (parentItem != null) {
                      if (this._source.id == null) {
                          if (undefined == item.uid) {
                              item.uid = parentItem.uid + "_" + parentItem[collectionName].length;
                          }
                          else {
                              if (item.uid.toString().indexOf(parentItem.uid) == -1) {
                                  item.uid = parentItem.uid + "_" + item.uid;
                              }
                          }
                      }
                      item[parentName] = parentItem;
                      item.level = parentItem.level + 1;
                      parentItem[collectionName][parentItem[collectionName].length] = item;
                  }
                  else {
                      if (undefined == item.uid) {
                          item.uid = this.generatekey();
                      }
                  }
              }
              return grouprecords;
          },
  
          getRecordsHierarchy: function (fieldName, parentFieldName, collectionName, mappingFields, dataRecords) {
              var recordsHierarchy = new Array();
              var flatData = this.records;
              if (dataRecords) {
                  flatData = dataRecords;
              }
  
              if (this.records.length == 0)
                  return null;
  
              var subItemsName = collectionName != null ? collectionName : "items";
              var items = [];
              var data = flatData;
              var dataLength = data.length;
              var names = (this._source && this._source.hierarchy) ? this._source.hierarchy.reservedNames : null;
  
              var itemByRecord = function (record) {
                  var itemObj = record;
                  if (mappingFields) {
                      $.each(mappingFields, function () {
                          if (this.name && this.map) {
                              itemObj[this.map] = itemObj[this.name];
                          }
                      });
                  }
  
                  return itemObj;
              }
  
              // build hierarchical source.
              for (var i = 0; i < dataLength; i++) {
                  var item = $.extend({}, data[i]);
                  var parentid = item[parentFieldName];
                  var id = item[fieldName];
                  items[id] = { parentid: parentid, item: item };
              }
  
              for (var i = 0; i < dataLength; i++) {
                  var item = $.extend({}, data[i]);
                  var parentid = item[parentFieldName];
                  var id = item[fieldName];
  
                  if (items[parentid] != undefined) {
                      var item = { parentid: parentid, item: items[id].item };
                      var parentItem = items[parentid].item;
                      if (!parentItem[subItemsName]) {
                          parentItem[subItemsName] = [];
                      }
                      var length = parentItem[subItemsName].length;
                      var record = item.item;
  
                      if (!names)
                      {
                          if (record.parent == undefined) {
                              record.parent = parentItem;
                          }
                      }
                      else
                      {
                          if (record[names.parent] == undefined) {
                              record[names.parent] = parentItem;
                          }                   
                      }
  
                      var itemObj = itemByRecord(record);
                      parentItem[subItemsName][length] = itemObj;
                      items[parentid].item = parentItem;
                      items[id] = item;
                  }
                  else {
                      var record = items[id].item;
                      if (!names)
                      {
                          if (record.parent == undefined) {
                              record.parent = null;
                          }
                      }
                      else
                      {
                          if (record[names.parent] == undefined) {
                              record[names.parent] = null;
                          }
                      }
  
                      var itemObj = itemByRecord(record);
                      if (!names)
                      {
                          itemObj.level = 0;
                      }
                      else
                      {
                          itemObj[names.level] = 0;
                      }
  
                      recordsHierarchy[recordsHierarchy.length] = itemObj;
                  }
              }
              if (recordsHierarchy.length != 0) {
                  var updateLevels = function (level, records) {
                      for (var i = 0; i < records.length; i++) {
                          if (!names)
                          {
                              records[i].level = level;
                          }
                          else
                          {
                              records[i][names.level] = level;
                          }
  
                          var subRecords = records[i][subItemsName];
                          if (subRecords) {
                              if (subRecords.length > 0) {
                                  updateLevels(level + 1, subRecords);
                              }
                              else {
                                  if (!names)
                                  {
                                      records[i].leaf = true;
                                  }
                                  else
                                  {
                                      records[i][names.leaf] = true;
                                  }
                              }
                          }
                          else {
                              if (!names)
                              {                 
                                  records[i].leaf = true;
                              }
                              else
                              {
                                  records[i][names.leaf] = true;
                              }
                          }
                      }
                  };
                  updateLevels(0, recordsHierarchy);
              }
              return recordsHierarchy;
          },
  
          bindBindingUpdate: function (id, func) {
              this._bindingUpdate[this._bindingUpdate.length] = { id: id, func: func };
  
          },
  
          unbindBindingUpdate: function (id) {
              for (var i = 0; i < this._bindingUpdate.length; i++) {
                  if (this._bindingUpdate[i].id == id) {
                      this._bindingUpdate[i].func = null;
                      this._bindingUpdate.splice(i, 1);
                      break;
                  }
              }
          },
  
          callBindingUpdate: function (collectionChanged) {
              for (var update = 0; update < this._bindingUpdate.length; update++) {
                  var bindingUpdate = this._bindingUpdate[update];
                  if (bindingUpdate.func != null) {
                      bindingUpdate.func(collectionChanged);
                  }
              }
          },
  
          getid: function (id, record, index) {
              if (id != null && id.name != undefined) {
                  if (id.name) {
                      var result = $(record).attr(id.name);
                      if (result != null && result.toString().length > 0) {
                          return result;
                      }
                      else if (id.map) {
                          try
                          {
                              var result = $(record).attr(id.map);
                              if (result != null && result.toString().length > 0) {
                                  return result;
                              }
                              else if ($(id.map, record).length > 0) {
                                  return $(id.map, record).text();
                              }
                              else if ($(id.name, record).length > 0) {
                                  return $(id.name, record).text();
                              }
                          }
                          catch (error) {
                              return index;
                          }
                      }
                      return;
                  }
              }
  
              if ($(id, record).length > 0) {
                  return $(id, record).text();
              }
  
              if (id) {
                  if (id.toString().length > 0) {
                      var result = $(record).attr(id);
                      if (result != null && result.toString().length > 0) {
                          return $.trim(result).split(" ").join("").replace(/([ #;?%&,.+*~\':"!^$[\]()=>|\/@])/g, '');
                      }
                      else {
                          var splitMap = id.split(this.mapChar);
                          if (splitMap.length > 1) {
                              var d = record;
                              for (var p = 0; p < splitMap.length; p++) {
                                  if (d != undefined) {
                                      d = d[splitMap[p]];
                                  }
                              }
                              if (d != undefined) {
                                  return d;
                              }
                          }
                          else {
                              if (record[id] != undefined) {
                                  return record[id];
                              }
                          }
                      }
                  }
              }
  
              return index;
          },
  
          loadjson: function (jsondata, data, source) {
              if (typeof (jsondata) == 'string') {
                  jsondata = $.parseJSON(jsondata);
              }
  
              if (source.root == undefined) source.root = '';
              if (source.record == undefined) source.record = '';
  
              var jsondata = jsondata || data;
              if (!jsondata) {
                  jsondata = [];
              }
  
              var me = this;
              if (source.root != '') {
                  var splitMap = source.root.split(me.mapChar);
                  if (splitMap.length > 1) {
                      var d = jsondata;
                      for (var p = 0; p < splitMap.length; p++) {
                          if (d != undefined) {
                              d = d[splitMap[p]];
                          }
                      }
                      jsondata = d;
                  }
                  else {
                      if (jsondata[source.root] !== undefined) {
                          jsondata = jsondata[source.root];
                      }
                      else if (jsondata[0] && jsondata[0][source.root] !== undefined) {
                          jsondata = jsondata[0][source.root];
                      }
                      else {
                          $.each(jsondata, function (i) {
                              var root = this;
                              if (this == source.root) {
                                  jsondata = this;
                                  return false;
                              }
                              else if (this[source.root] != undefined) {
                                  jsondata = this[source.root];
                              }
                          });
                      }
  
                      if (!jsondata) {
                          var splitMap = source.root.split(me.mapChar);
                          if (splitMap.length > 0) {
                              var d = jsondata;
                              for (var p = 0; p < splitMap.length; p++) {
                                  if (d != undefined) {
                                      d = d[splitMap[p]];
                                  }
                              }
                              jsondata = d;
                          }
                      }
                  }
              }
              else {
                  if (!jsondata.length) {
                      for (var obj in jsondata) {
                          if ($.isArray(jsondata[obj])) {
                              jsondata = jsondata[obj];
                              break;
                          }
                      }
                  }
              }
  
              if (jsondata != null && jsondata.length == undefined) {
                  jsondata = $.makeArray(jsondata);
              }
  
              if (jsondata == null || jsondata == undefined || jsondata == "undefined" || jsondata.length == undefined) {
                  throw new Error('jqxDataAdapter: JSON Parse error! Invalid JSON. Please, check your JSON or your jqxDataAdapter initialization!');
                  return;
              }
  
              if (jsondata.length == 0) {
                  this.totalrecords = 0;
                  return;
              }
  
              var length = jsondata.length;
              this.totalrecords = this.virtualmode ? (source.totalrecords || length) : length;
              this.records = new Array();
              this.originaldata = new Array();
  
              var records = this.records;
              var recordsstartindex = !this.pageable ? source.recordstartindex : this.pagesize * this.pagenum;
  
              this.recordids = new Array();
  
              if (source.loadallrecords) {
                  recordsstartindex = 0;
                  length = this.totalrecords;
              }
  
              var dataoffset = 0;
              if (this.virtualmode) {
                  recordsstartindex = !this.pageable ? source.recordstartindex : this.pagesize * this.pagenum;
                  dataoffset = recordsstartindex;
                  recordsstartindex = 0;
                  length = this.totalrecords;
              }
  
              var datafieldslength = source.datafields ? source.datafields.length : 0;
              // auto-generate data columns
              if (datafieldslength == 0) {
                  var firstrecord = jsondata[0];
                  var datafields = new Array();
                  for (var obj in firstrecord) {
                      var field = obj;
                      datafields[datafields.length] = { name: field };
                  }
                  source.datafields = datafields;
                  source.generatedfields = source.datafields;
                  datafieldslength = datafields.length;
              }
  
              var index = recordsstartindex;
              for (var i = recordsstartindex; i < length; i++) {
                  var record = jsondata[i];
  
                  if (record == undefined)
                      break;
  
                  if (source.record && source.record != '') {
                      record = record[source.record];
                      if (record == undefined)
                          continue;
                  }
  
                  var recordid = this.getid(source.id, record, i);
                  if (typeof (recordid) === "object") {
                      recordid = i;
                  }
  
                  if (!this.recordids[recordid]) {
                      this.recordids[recordid] = record;
                      var datarow = {};
  
                      for (var j = 0; j < datafieldslength; j++) {
                          var datafield = source.datafields[j];
                          var value = '';
                          if (undefined == datafield || datafield == null) {
                              continue;
                          }
  
                          if (datafield.map) {
                              if ($.isFunction(datafield.map)) {
                                  value = datafield.map(record);
                              }
                              else {
                                  var splitMap = datafield.map.split(me.mapChar);
                                  if (splitMap.length > 0) {
                                      var datarecord = record;
                                      for (var p = 0; p < splitMap.length; p++) {
                                          if (datarecord != undefined) {
                                              datarecord = datarecord[splitMap[p]];
                                          }
                                      }
                                      value = datarecord;
                                  }
                                  else {
                                      value = record[datafield.map];
                                  }
                              }
  
                              if (value != undefined && value != null) {
                                  value = this.getvaluebytype(value, datafield);
                              }
                              else if (value == undefined && value != null) {
                                  value = '';
                              }
                          }
  
                          // searches by both selectors when necessary.
                          if (value == '' && !datafield.map) {
                              value = record[datafield.name];
                              if (value == undefined && value != null) {
                                  value = '';
                              }
                              // the datafield.value allows you to load values like: "Nombre":{"#text":"FASE 1"}, where the datafield is Nombre, the value is object. 
                              // If the datafield.value is "#text", the value that will be loaded will be "FASE 1".
                              if (datafield.value != undefined) {
                                  if (value != undefined) {
                                      var tmpvalue = value[datafield.value];
                                      if (tmpvalue != undefined) {
                                          value = tmpvalue;
                                      }
                                  }
                              }
                          }
  
                          value = this.getvaluebytype(value, datafield);
                          if (datafield.displayname != undefined) {
                              datarow[datafield.displayname] = value;
                          }
                          else {
                              datarow[datafield.name] = value;
                          }
  
                          if (datafield.type === "array") {
                              var updateValues = function (records) {
                                  if (!records) return;
                                  for (var t = 0; t < records.length; t++) {
                                      var record = records[t];
                                      if (!record) {
                                          continue;
                                      }
  
                                      for (var c = 0; c < datafieldslength; c++) {
                                          var datafield = source.datafields[c];
                                          var value = '';
                                          if (undefined == datafield || datafield == null) {
                                              continue;
                                          }
  
                                          if (datafield.map) {
                                              if ($.isFunction(datafield.map)) {
                                                  value = datafield.map(record);
                                              }
                                              else {
                                                  var splitMap = datafield.map.split(me.mapChar);
                                                  if (splitMap.length > 0) {
                                                      var datarecord = record;
                                                      for (var p = 0; p < splitMap.length; p++) {
                                                          if (datarecord != undefined) {
                                                              datarecord = datarecord[splitMap[p]];
                                                          }
                                                      }
                                                      value = datarecord;
                                                  }
                                                  else {
                                                      value = record[datafield.map];
                                                  }
                                              }
  
                                              if (value != undefined && value != null) {
                                                  value = this.getvaluebytype(value, datafield);
                                              }
                                              else if (value == undefined && value != null) {
                                                  value = '';
                                              }
                                          }
  
                                          // searches by both selectors when necessary.
                                          if (value == '' && !datafield.map) {
                                              value = record[datafield.name];
                                              if (value == undefined && value != null) {
                                                  value = '';
                                              }
                                              // the datafield.value allows you to load values like: "Nombre":{"#text":"FASE 1"}, where the datafield is Nombre, the value is object. 
                                              // If the datafield.value is "#text", the value that will be loaded will be "FASE 1".
                                              if (datafield.value != undefined) {
                                                  if (value != undefined) {
                                                      var tmpvalue = value[datafield.value];
                                                      if (tmpvalue != undefined) {
                                                          value = tmpvalue;
                                                      }
                                                  }
                                              }
                                          }
  
                                          value = this.getvaluebytype(value, datafield);
                                          if (datafield.displayname != undefined) {
                                              record[datafield.displayname] = value;
                                          }
                                          else {
                                              record[datafield.name] = value;
                                          }
                                          if (datafield.type === "array") {
                                              updateValues.call(this, value);
                                          }
                                      }
                                  }
                              }
                              updateValues.call(this, value);
                          }
                      }
  
                      if (source.recordendindex <= 0 || recordsstartindex < source.recordendindex) {
                          //      records[dataoffset + index] = $.extend({}, datarow);
                          records[dataoffset + index] = new Object(datarow);
                          records[dataoffset + index].uid = recordid;
  
                          this.originaldata[dataoffset + index] = new Object(records[i]);
  
                     //     this.originaldata[dataoffset + index] = $.extend({}, records[i]);
                          index++;
                      }
                  }
              }
              this.records = records;
              this.cachedrecords = this.records;
          },
  
          loadxml: function (xmldata, data, source) {
              if (typeof (xmldata) == 'string') {
                  xmldata = data = $($.parseXML(xmldata));
                  xmldata = null;
              }
  
              if (source.root == undefined) source.root = '';
              if (source.record == undefined) source.record = '';
  
  
              var xmldata;
  
              if ($.jqx.browser.msie && data) {
                  if (data.xml != undefined) {
                      xmldata = $(source.root + " " + source.record, $.parseXML(data.xml));
                  }
                  else {
                      xmldata = xmldata || $(source.root + " " + source.record, data);
                  }
              }
              else xmldata = xmldata || $(source.root + " " + source.record, data);
  
              if (!xmldata) {
                  xmldata = [];
              }
  
              var length = xmldata.length;
              if (xmldata.length == 0) {
                  return;
              }
  
              this.totalrecords = this.virtualmode ? (source.totalrecords || length) : length;
              this.records = new Array();
              this.originaldata = new Array();
  
              var records = this.records;
              var recordsstartindex = !this.pageable ? source.recordstartindex : this.pagesize * this.pagenum;
  
              this.recordids = new Array();
  
              if (source.loadallrecords) {
                  recordsstartindex = 0;
                  length = this.totalrecords;
              }
  
              var dataoffset = 0;
              if (this.virtualmode) {
                  recordsstartindex = !this.pageable ? source.recordstartindex : this.pagesize * this.pagenum;
                  dataoffset = recordsstartindex;
                  recordsstartindex = 0;
                  length = this.totalrecords;
              }
  
              var datafieldslength = source.datafields ? source.datafields.length : 0;
              // auto-generate data columns
              if (datafieldslength == 0) {
                  var firstrecord = xmldata[0];
                  var datafields = new Array();
                  for (var obj in firstrecord) {
                      var field = obj;
                      datafields[datafields.length] = { name: field };
                  }
                  source.datafields = datafields;
                  source.generatedfields = source.datafields;
  
                  datafieldslength = datafields.length;
              }
  
              var p = recordsstartindex;
              var hasArray = false;
              for (var i = recordsstartindex; i < length; i++) {
                  var record = xmldata[i];
                  if (record == undefined)
                      break;
         
                  var recordid = this.getid(source.id, record, i);
                  if (!this.recordids[recordid]) {
                      this.recordids[recordid] = record;
                      var datarow = {};
  
                      var multiLevel = false;
                      if (source.hierarchy && source.hierarchy.root) {           
                          multiLevel = true;
                      }
  
                      for (var j = 0; j < datafieldslength; j++) {
                          var datafield = source.datafields[j];
                          var value = '';
                          if (undefined == datafield || datafield == null) {
                              continue;
                          }
  
                          if (datafield.map) {
                              if ($.isFunction(datafield.map)) {
                                  value = datafield.map(record);
                              }
                              else {
                                  var attributeStartIndex = datafield.map.indexOf('[');
                                  if (attributeStartIndex < 0) {
                                      value = $(datafield.map, record);
                                      if (value.length == 1) value = value.text();
                                      else {
                                          hasArray = true;
                                          var subArray = new Array();
                                          for (var f = 0; f < value.length; f++) {
                                              subArray.push($(value[f]).text());
                                          }
                                          value = subArray;
                                          if (multiLevel && subArray.length > 0) {
                                              value = subArray[0];
                                          }
                                      }
                                  }
                                  else {
                                      var submap = datafield.map.substring(0, attributeStartIndex - 1);
                                      var attributeEndIndex = datafield.map.indexOf(']');
                                      var attribute = datafield.map.substring(attributeStartIndex + 1, attributeEndIndex);
                                      value = $(submap, record).attr(attribute);
                                      if (value == undefined) {
                                          value = $(record).attr(attribute);
                                      }
  
                                      if (value == undefined) value = '';
                                  }
                                  if (value == '') {
                                      value = $(record).attr(datafield.map);
                                      if (value == undefined) value = '';
                                  }
                              }
                          }
                          // searches by both selectors when necessary.
                          if (value == '') {
                              value = $(datafield.name, record);
                              if (value.length == 1) value = value.text();
                              else {
                                  var subArray = new Array();
                                  for (var f = 0; f < value.length; f++) {
                                      subArray.push($(value[f]).text());
                                  }
                                  value = subArray;
                                  if (multiLevel && subArray.length > 0) {
                                      value = subArray[0];
                                  }
                              }
  
                              if (value == '') {
                                  value = $(record).attr(datafield.name);
                                  if (value == undefined) value = '';
                              }
                              if (value == '') {
                                  if (record.nodeName && record.nodeName == datafield.name && record.firstChild) {
                                      value = $(record.firstChild).text();
                                  }
                              }
                          }
  
                          var originalvalue = value;
                          value = this.getvaluebytype(value, datafield);
                          if (datafield.displayname != undefined) {
                              datarow[datafield.displayname] = value;
                          }
                          else {
                              datarow[datafield.name] = value;
                          }
                      }
                      if (source.recordendindex <= 0 || recordsstartindex < source.recordendindex) {
                          records[dataoffset + p] = $.extend({}, datarow);
                          records[dataoffset + p].uid = recordid;
  
                          this.originaldata[dataoffset + p] = $.extend({}, records[i]);
                          p++;
                      }
                  }
              }
  
              if (source.hierarchy && source.hierarchy.root) {
                  for (var i = recordsstartindex; i < length; i++) {
                      var record = xmldata[i];
                      var dataRecord = records[i];
  
                      if ($(record).parent().length > 0) {
                          var recordid = this.getid(source.id, $(record).parents(source.hierarchy.record + ":first" ));
                          dataRecord.parentuid = recordid;
                      }
                      else {
                          dataRecord.parentuid = null;
                      }
                  }
              }
  
              this.records = records;
              this.cachedrecords = this.records;
          },
  
          loadics: function (data, source) {
              if (data == null) {
                  return;
              }
  
              var rowDelimiter = source.rowDelimiter || this.rowDelimiter || '\n';
              var rows = data.split(rowDelimiter);
              var length = rows.length;
              var rowsWithNewRowDelimiter = data.split('\r');
              if (length == 1 && rowsWithNewRowDelimiter.length > 1) {
                  rows = rowsWithNewRowDelimiter;
                  length = rows.length;
              }
              this.records = new Array();
              this.originaldata = new Array();
  
              var records = this.records;
              this.recordids = new Array();
  
              var dataoffset = 0;
              
              var stringToDate = function (until) {
                  var re = /^(\d{4})(\d{2})(\d{2})(T(\d{2})(\d{2})(\d{2})Z)?$/;
                  var bits = re.exec(until);
                  if (!bits) {
                      throw new Error('Invalid UNTIL value: ' + until)
                  }
                  return new Date(
                      Date.UTC(bits[1],
                      bits[2] - 1,
                      bits[3],
                      bits[5] || 0,
                      bits[6] || 0,
                      bits[7] || 0
                  ));
              }
  
              for (var i = 0; i < length; i++) {
                  var record = rows[i];
                  if (record == "BEGIN:VEVENT") {
                      var appointment = {};
                      continue;
                  }
  
                  if (record.indexOf("SUMMARY") >= 0) {
                      appointment.SUMMARY = record.substring(record.indexOf("SUMMARY") + 8);
                      continue;
                  }
                  if (record.indexOf("LOCATION") >= 0) {
                      appointment.LOCATION = record.substring(record.indexOf("LOCATION") + 9);
                      continue;
                  }
                  if (record.indexOf("DESCRIPTION") >= 0) {
                      appointment.DESCRIPTION = record.substring(record.indexOf("DESCRIPTION") + 12);
                      continue;
                  }
                  if (record.indexOf("RRULE") >= 0) {
                      appointment.RRULE = record.substring(record.indexOf("RRULE") + 6);
                      continue;
                  }
                  if (record.indexOf("EXDATE") >= 0) {
                      var exDate = record.substring(record.indexOf("EXDATE") + 7);
                      appointment.EXDATE = exDate;
                      continue;
                  }
                  if (record.indexOf("DTEND") >= 0) {
                      appointment.DTEND = stringToDate(record.substring(record.indexOf("DTEND") + 6));
                      continue;
                  }
                  if (record.indexOf("DTSTART") >= 0) {
                      appointment.DTSTART = stringToDate(record.substring(record.indexOf("DTSTART") + 8));
                      continue;
                  }
                  if (record.indexOf("UID") >= 0) {
                      appointment.uid = appointment.UID = record.substring(record.indexOf("UID") + 4);
                      continue;
                  }
                  if (record.indexOf("STATUS") >= 0) {
                      appointment.STATUS = record.substring(record.indexOf("STATUS") + 7);
                      continue;
                  }
                  if (record == "END:VEVENT") {
                      records.push(appointment);
                      continue;
                  }
              }
              this.records = records;
              this.cachedrecords = this.records;
          },
  
          loadtext: function (data, source) {
              if (data == null) {
                  return;
              }
  
              var rowDelimiter = source.rowDelimiter || this.rowDelimiter || '\n';
              var rows = data.split(rowDelimiter);
              var length = rows.length;
              var rowsWithNewRowDelimiter = data.split('\r');
              if (length == 1 && rowsWithNewRowDelimiter.length > 1) {
                  rows = rowsWithNewRowDelimiter;
                  length = rows.length;
              }
              this.totalrecords = this.virtualmode ? (source.totalrecords || length) : length;
              this.records = new Array();
              this.originaldata = new Array();
  
              var records = this.records;
              var recordsstartindex = !this.pageable ? source.recordstartindex : this.pagesize * this.pagenum;
  
              this.recordids = new Array();
  
              if (source.loadallrecords) {
                  recordsstartindex = 0;
                  length = this.totalrecords;
              }
  
              var dataoffset = 0;
              if (this.virtualmode) {
                  recordsstartindex = !this.pageable ? source.recordstartindex : this.pagesize * this.pagenum;
                  dataoffset = recordsstartindex;
                  recordsstartindex = 0;
                  length = this.totalrecords;
              }
  
              var datafieldslength = source.datafields.length;
              var columnDelimiter = source.columnDelimiter || this.columnDelimiter;
              if (!columnDelimiter)
                  columnDelimiter = (source.datatype === 'tab' || source.datatype === 'tsv') ? '\t' : ',';
  
              for (var i = recordsstartindex; i < length; i++) {
                  var record = rows[i];
                  var recordid = null;
                  if (!this.recordids[recordid]) {
                      if (source.id == null) {
                          recordid = i;
                          this.recordids[recordid] = record;
                      }
  
                      var datarow = {};
                      var columns = rows[i].split(columnDelimiter);
  
                      for (var j = 0; j < datafieldslength; j++) {
                          if (j >= columns.length)
                              continue;
                          var datafield = source.datafields[j];
  
                          var value = columns[j];
                          if (datafield.map && $.isFunction(datafield.map)) {
                              value = datafield.map(record);
                          }
  
                          if (datafield.type) {
                              value = this.getvaluebytype(value, datafield);
                          }
  
                          var key = datafield.map || datafield.name || j.toString();
                          datarow[key] = value;
                          if (source.id != null) {
                              if (source.id === datafield.name) {
                                  recordid = value;
                                  this.recordids[recordid] = record;
                              }
                          }
                      }
                      if (recordid == null) {
                          recordid = i;
                      }
  
                      records[dataoffset + i] = $.extend({}, datarow);
                      records[dataoffset + i].uid = recordid;
  
                      this.originaldata[dataoffset + i] = $.extend({}, records[i]);
                  }
              }
              this.records = records;
              this.cachedrecords = this.records;
          },
  
          getvaluebytype: function (value, datafield) {
              var originalvalue = value;
              if (value == null) return value;
              if ($.isArray(value) && datafield.type != "array") {
                  for (var t = 0; t < value.length; t++) {
                      value[t] = this.getvaluebytype(value[t], datafield);
                  }
                  return value;
              }
  
              if (datafield.type == 'date') {
                  if (value == "NaN") {
                      value = "";
                  }
                  else {
                      if (value && value instanceof Date) {
                          return value;
                      }
  
                      var tmpvalue = new Date(value);
  
                      if (typeof value == 'string') {
                          if (datafield.format) {
                              var newtmpvalue = $.jqx.dataFormat.parsedate(value, datafield.format);
                              if (newtmpvalue != null) {
                                  tmpvalue = newtmpvalue;
                              }
                          }
                      }
  
                      if (tmpvalue.toString() == 'NaN' || tmpvalue.toString() == "Invalid Date") {
                          if ($.jqx.dataFormat) {
                              value = $.jqx.dataFormat.tryparsedate(value);
                          }
                          else value = tmpvalue;
                      }
                      else {
                          value = tmpvalue;
                      }
  
                      if (value == null) {
                          value = originalvalue;
                      }
                  }
              }
              else if (datafield.type == 'float' || datafield.type == 'number' || datafield.type == 'decimal') {
                  if (value == "NaN") value = "";
                  else {
                      var value = parseFloat(value);
                      if (isNaN(value)) {
                          value = originalvalue;
                      }
                  }
              }
              else if (datafield.type == 'int' || datafield.type == 'integer') {
                  var value = parseInt(value);
                  if (isNaN(value)) {
                      value = originalvalue;
                  }
              }
              else if (datafield.type == 'bool' || datafield.type == 'boolean') {
                  if (value != null) {
                      if (value.toLowerCase != undefined) {
                          if (value.toLowerCase() == 'false') {
                              value = false;
                          }
                          else if (value.toLowerCase() == 'true') {
                              value = true;
                          }
                      }
                  }
  
                  if (value == 1) {
                      value = true;
                  }
                  else if (value == 0 && value !== "") {
                      value = false;
                  }
                  else value = '';
              }
  
              return value;
          }
      }
  
      $.jqx.dataFormat = {};
  
      $.extend($.jqx.dataFormat, {
          regexTrim: /^\s+|\s+$/g,
          regexInfinity: /^[+-]?infinity$/i,
          regexHex: /^0x[a-f0-9]+$/i,
          regexParseFloat: /^[+-]?\d*\.?\d*(e[+-]?\d+)?$/,
          toString: Object.prototype.toString,
  
          isBoolean: function (value) {
              return typeof value === 'boolean';
          },
  
          isObject: function (value) {
              return (value && (typeof value === 'object' || $.isFunction(value))) || false;
          },
  
          isDate: function (value) {
              return value instanceof Date;
          },
  
          arrayIndexOf: function (array, item) {
              if (array.indexOf) {
                  return array.indexOf(item);
              }
              for (var i = 0, length = array.length; i < length; i++) {
                  if (array[i] === item) {
                      return i;
                  }
              }
              return -1;
          },
  
          isString: function (value) {
              return typeof value === 'string';
          },
  
          isNumber: function (value) {
              return typeof value === 'number' && isFinite(value);
          },
  
          isNull: function (value) {
              return value === null;
          },
  
          isUndefined: function (value) {
              return typeof value === 'undefined';
          },
  
          isValue: function (value) {
              return (this.isObject(value) || this.isString(value) || this.isNumber(value) || this.isBoolean(value));
          },
  
          isEmpty: function (value) {
              if (!this.isString(value) && this.isValue(value)) {
                  return false;
              } else if (!this.isValue(value)) {
                  return true;
              }
              value = $.trim(value).replace(/\&nbsp\;/ig, '').replace(/\&#160\;/ig, '');
              return value === "";
          },
  
          startsWith: function (value, pattern) {
              return value.indexOf(pattern) === 0;
          },
  
          endsWith: function (value, pattern) {
              return value.substr(value.length - pattern.length) === pattern;
          },
  
          trim: function (value) {
              return (value + "").replace(this.regexTrim, "");
          },
  
          isArray: function (obj) {
              return this.toString.call(obj) === "[object Array]";
          },
  
          defaultcalendar: function () {
              var calendar = {
                  // separator of parts of a date (e.g. '/' in 11/05/1955)
                  '/': "/",
                  // separator of parts of a time (e.g. ':' in 05:44 PM)
                  ':': ":",
                  // the first day of the week (0 = Sunday, 1 = Monday, etc)
                  firstDay: 0,
                  days: {
                      // full day names
                      names: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
                      // abbreviated day names
                      namesAbbr: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
                      // shortest day names
                      namesShort: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]
                  },
                  months: {
                      // full month names (13 months for lunar calendards -- 13th month should be "" if not lunar)
                      names: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", ""],
                      // abbreviated month names
                      namesAbbr: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ""]
                  },
                  // AM and PM designators in one of these forms:
                  // The usual view, and the upper and lower case versions
                  //      [standard,lowercase,uppercase]
                  // The culture does not use AM or PM (likely all standard date formats use 24 hour time)
                  //      null
                  AM: ["AM", "am", "AM"],
                  PM: ["PM", "pm", "PM"],
                  eras: [
                  // eras in reverse chronological order.
                  // name: the name of the era in this culture (e.g. A.D., C.E.)
                  // start: when the era starts in ticks (gregorian, gmt), null if it is the earliest supported era.
                  // offset: offset in years from gregorian calendar
                      {"name": "A.D.", "start": null, "offset": 0 }
                  ],
                  twoDigitYearMax: 2029,
                  patterns: {
                      // short date pattern
                      d: "M/d/yyyy",
                      // long date pattern
                      D: "dddd, MMMM dd, yyyy",
                      // short time pattern
                      t: "h:mm tt",
                      // long time pattern
                      T: "h:mm:ss tt",
                      // long date, short time pattern
                      f: "dddd, MMMM dd, yyyy h:mm tt",
                      // long date, long time pattern
                      F: "dddd, MMMM dd, yyyy h:mm:ss tt",
                      // month/day pattern
                      M: "MMMM dd",
                      // month/year pattern
                      Y: "yyyy MMMM",
                      // S is a sortable format that does not vary by culture
                      S: "yyyy\u0027-\u0027MM\u0027-\u0027dd\u0027T\u0027HH\u0027:\u0027mm\u0027:\u0027ss",
                      // formatting of dates in MySQL DataBases
                      ISO: "yyyy-MM-dd hh:mm:ss",
                      ISO2: "yyyy-MM-dd HH:mm:ss",
                      d1: "dd.MM.yyyy",
                      d2: "dd-MM-yyyy",
                      d3: "MM-dd-yyyy",
                      zone1: "yyyy-MM-ddTHH:mm:ss-HH:mm",
                      zone2: "yyyy-MM-ddTHH:mm:ss+HH:mm",
                      custom: "yyyy-MM-ddTHH:mm:ss.fff",
                      custom2: "yyyy-MM-dd HH:mm:ss.fff"
                  },
                  percentsymbol: "%",
                  currencysymbol: "$",
                  currencysymbolposition: "before",
                  decimalseparator: '.',
                  thousandsseparator: ','
              }
              return calendar;
          },
  
          expandFormat: function (calendar, format) {
              // expands unspecified or single character date formats into the full pattern.
              format = format || "F";
              var pattern,
                  patterns = calendar.patterns,
                  len = format.length;
              if (len === 1) {
                  pattern = patterns[format];
                  if (!pattern) {
                      throw "Invalid date format string '" + format + "'.";
                  }
                  format = pattern;
              }
              else if (len === 2 && format.charAt(0) === "%") {
                  // %X escape format -- intended as a custom format string that is only one character, not a built-in format.
                  format = format.charAt(1);
              }
              return format;
          },
  
          getEra: function (date, eras) {
              if (!eras) return 0;
              if (typeof date === 'string') {
                  return 0;
              }
  
              var start, ticks = date.getTime();
              for (var i = 0, l = eras.length; i < l; i++) {
                  start = eras[i].start;
                  if (start === null || ticks >= start) {
                      return i;
                  }
              }
              return 0;
          },
  
          toUpper: function (value) {
              // 'he-IL' has non-breaking space in weekday names.
              return value.split("\u00A0").join(' ').toUpperCase();
          },
  
          toUpperArray: function (arr) {
              var results = [];
              for (var i = 0, l = arr.length; i < l; i++) {
                  results[i] = this.toUpper(arr[i]);
              }
              return results;
          },
  
          getEraYear: function (date, cal, era, sortable) {
              var year = date.getFullYear();
              if (!sortable && cal.eras) {
                  // convert normal gregorian year to era-shifted gregorian
                  // year by subtracting the era offset
                  year -= cal.eras[era].offset;
              }
              return year;
          },
  
          toUpper: function(value)
          {
              if (value) {
                  return value.toUpperCase();
              }
              return "";
          },
  
          getDayIndex: function (cal, value, abbr) {
              var ret,
                  days = cal.days,
                  upperDays = cal._upperDays;
              if (!upperDays) {
                  cal._upperDays = upperDays = [
                      this.toUpperArray(days.names),
                      this.toUpperArray(days.namesAbbr),
                      this.toUpperArray(days.namesShort)
                  ];
              }
              value = value.toUpperCase();
              if (abbr) {
                  ret = this.arrayIndexOf(upperDays[1], value);
                  if (ret === -1) {
                      ret = this.arrayIndexOf(upperDays[2], value);
                  }
              }
              else {
                  ret = this.arrayIndexOf(upperDays[0], value);
              }
              return ret;
          },
  
          getMonthIndex: function (cal, value, abbr) {
              var months = cal.months,
                  monthsGen = cal.monthsGenitive || cal.months,
                  upperMonths = cal._upperMonths,
                  upperMonthsGen = cal._upperMonthsGen;
              if (!upperMonths) {
                  cal._upperMonths = upperMonths = [
                      this.toUpperArray(months.names),
                      this.toUpperArray(months.namesAbbr)
                  ];
                  cal._upperMonthsGen = upperMonthsGen = [
                      this.toUpperArray(monthsGen.names),
                      this.toUpperArray(monthsGen.namesAbbr)
                  ];
              }
              value = this.toUpper(value);
              var i = this.arrayIndexOf(abbr ? upperMonths[1] : upperMonths[0], value);
              if (i < 0) {
                  i = this.arrayIndexOf(abbr ? upperMonthsGen[1] : upperMonthsGen[0], value);
              }
              return i;
          },
  
          appendPreOrPostMatch: function (preMatch, strings) {
              // appends pre- and post- token match strings while removing escaped characters.
              // Returns a single quote count which is used to determine if the token occurs
              // in a string literal.
              var quoteCount = 0,
                  escaped = false;
              for (var i = 0, il = preMatch.length; i < il; i++) {
                  var c = preMatch.charAt(i);
                  switch (c) {
                      case '\'':
                          if (escaped) {
                              strings.push("'");
                          }
                          else {
                              quoteCount++;
                          }
                          escaped = false;
                          break;
                      case '\\':
                          if (escaped) {
                              strings.push("\\");
                          }
                          escaped = !escaped;
                          break;
                      default:
                          strings.push(c);
                          escaped = false;
                          break;
                  }
              }
              return quoteCount;
          },
  
          getTokenRegExp: function () {
              // regular expression for matching date and time tokens in format strings.
              return /\/|dddd|ddd|dd|d|MMMM|MMM|MM|M|yyyy|yy|y|hh|h|HH|H|mm|m|ss|s|tt|t|fff|ff|f|zzz|zz|z|gg|g/g;
          },
  
          formatlink: function (value, format) {
              var target = '';
              if (format && format.target) { target = 'target=' + format.target; }
              if (target != '') {
                  return "<a " + target + " href=\"" + value + "\">" + value + "</a>";
              }
              return "<a href=\"" + value + "\">" + value + "</a>";
          },
  
          formatemail: function (value) {
              return "<a href=\"mailto:" + value + "\">" + value + "</a>";
          },
  
          formatNumber: function (value, format, calendar)
          {
              return this.formatnumber(value, format, calendar);
          },
  
          formatnumber: function (value, format, calendar) {
              if (calendar == undefined || calendar == null || calendar == "") {
                  calendar = this.defaultcalendar();
              }
  
              if (format === "" || format === null) {
                  return value;
              }
  
              if (!this.isNumber(value)) {
                  value *= 1;
              }
              var precision;
              if (format.length > 1) precision = parseInt(format.slice(1), 10);
  
              var options = {}
              var current = format.charAt(0).toUpperCase();
  
              options.thousandsSeparator = calendar.thousandsseparator;
              options.decimalSeparator = calendar.decimalseparator;
              switch (current) {
                  case "D":
                  case "d":
                  case "F":
                  case "f":
                      options.decimalPlaces = precision;
                      break;
                  case "N":
                  case "n":
                      options.decimalPlaces = 0;
                      break;
                  case "C":
                  case "c":
                      options.decimalPlaces = precision;
                      if (calendar.currencysymbolposition == "before") {
                          options.prefix = calendar.currencysymbol;
                      }
                      else {
                          options.suffix = calendar.currencysymbol;
                      }
                      break;
                  case "P":
                  case "p":
                      options.suffix = calendar.percentsymbol;
                      options.decimalPlaces = precision;
                      break;
                  default:
                      throw "Bad number format specifier: " + current;
              }
  
              if (this.isNumber(value)) {
                  var negative = (value < 0);
                  var output = value + "";
                  var decimalseparator = (options.decimalSeparator) ? options.decimalSeparator : ".";
                  var decimalindex;
                  if (this.isNumber(options.decimalPlaces)) {
                      // Round to the correct decimal place
                      var decimalplaces = options.decimalPlaces;
                      var decimal = Math.pow(10, decimalplaces);
                      output = (value * decimal).toFixed(0) / decimal + "";
                      decimalindex = output.lastIndexOf(".");
                      if (decimalplaces > 0) {
                          // Add the decimal separator
                          if (decimalindex < 0) {
                              output += decimalseparator;
                              decimalindex = output.length - 1;
                          }
                              // Replace the "."
                          else if (decimalseparator !== ".") {
                              output = output.replace(".", decimalseparator);
                          }
                          // Add missing zeros
                          while ((output.length - 1 - decimalindex) < decimalplaces) {
                              output += "0";
                          }
                      }
                  }
                  else {
                      var output = value + "";
                      decimalindex = output.lastIndexOf(".");
                      if (decimalindex > 0 && decimalplaces == undefined) {
                            // Replace the "."
                           if (decimalseparator !== ".") {
                              output = output.replace(".", decimalseparator);
                          }
                      }
                  }
  
                  if (options.thousandsSeparator) {
                      var groupseparator = options.thousandsSeparator;
                      decimalindex = output.lastIndexOf(decimalseparator);
                      decimalindex = (decimalindex > -1) ? decimalindex : output.length;
                      var newoutput = output.substring(decimalindex);
                      var nCount = -1;
                      for (var i = decimalindex; i > 0; i--) {
                          nCount++;
                          if ((nCount % 3 === 0) && (i !== decimalindex) && (!negative || (i > 1))) {
                              newoutput = groupseparator + newoutput;
                          }
                          newoutput = output.charAt(i - 1) + newoutput;
                      }
                      output = newoutput;
                  }
                  // Prepend prefix
                  output = (options.prefix) ? options.prefix + output : output;
                  // Append suffix
                  output = (options.suffix) ? output + options.suffix : output;
                  return output;
  
              } else {
                  return value;
              }
          },
  
          tryparsedate: function (value, calendar) {
              if (calendar == undefined || calendar == null) {
                  calendar = this.defaultcalendar();
              }
              var me = this;
              if (value == "")
                  return null;
  
              if (value != null && !value.substring) {
                  value = value.toString();
              }
  
              if (value != null && value.substring(0, 6) == "/Date(") {
                  var jsonDateRE = /^\/Date\((-?\d+)(\+|-)?(\d+)?\)\/$/;
  
                  var date = new Date(+value.replace(/\/Date\((\d+)\)\//, '$1'));
                  if (date == "Invalid Date") {
                      var m = value.match(/^\/Date\((\d+)([-+]\d\d)(\d\d)\)\/$/);
                      var date = null;
                      if (m)
                          date = new Date(1 * m[1] + 3600000 * m[2] + 60000 * m[3]);
                  }
                  if (date == null || date == "Invalid Date" || isNaN(date)) {
                      var arr = jsonDateRE.exec(value);
                      if (arr) {
                          // 0 - complete results; 1 - ticks; 2 - sign; 3 - minutes
                          var result = new Date(parseInt(arr[1]));
                          if (arr[2]) {
                              var mins = parseInt(arr[3]);
                              if (arr[2] === "-") {
                                  mins = -mins;
                              }
                              var current = result.getUTCMinutes();
                              result.setUTCMinutes(current - mins);
                          }
                          if (!isNaN(result.valueOf())) {
                              return result;
                          }
                      }
                  }
  
                  return date;
              }
  
              var patterns = calendar.patterns;
              for (var prop in patterns) {
                  date = me.parsedate(value, patterns[prop], calendar);
                  if (date) {
                      if (prop == "ISO") {
                          var tmpDate = me.parsedate(value, patterns["ISO2"], calendar);
                          if (tmpDate) return tmpDate;
                      }
                      return date;
                  }
              }
  
              if (value != null) {
                  var tmpDate = null;
                  var dateParts = [':', '/', '-'];
                  var canParse = true;
                  for (var part = 0; part < dateParts.length; part++) {
                      if (value.indexOf(dateParts[part]) != -1) {
                          canParse = false;
                      }
                  }
  
                  if (canParse) {
                      var number = new Number(value);
                      if (!isNaN(number)) {
                          return new Date(number);
                      }
                  }
              }
  
              if ($.type(value) === "string") {
                  var that = me;
                  value = that.trim(value);
                  var splitParts = [':', '/', '-', ' ', ','];
                  var replaceAll = function (find, replace, str) {
                      return str.replace(new RegExp(find, 'g'), replace);
                  }
                  value = replaceAll(', ', ',', value);
                  var timePart = "";
                  var datePart = value;
                  if (value.indexOf(":") >= 0) {
                      timePart = value.substring(value.indexOf(":") - 2);
                      timePart = that.trim(timePart);
                      datePart = value.substring(0, value.indexOf(":") - 2);
                  }
                  else if (value.toUpperCase().indexOf("AM") >= 0) {
                      timePart = value.substring(value.toUpperCase().indexOf("AM") - 2);
                      timePart = that.trim(timePart);
                      datePart = value.substring(0, value.toUpperCase().indexOf("AM") - 2);
                  }
                  else if (value.toUpperCase().indexOf("PM") >= 0) {
                      timePart = value.substring(value.toUpperCase().indexOf("PM") - 2);
                      timePart = that.trim(timePart);
                      datePart = value.substring(0, value.toUpperCase().indexOf("PM") - 2);
                  }
                  var parseDate = new Date();
                  var parsed = false;
                  if (datePart) {
                      for (var i = 0; i < splitParts.length; i++) {
                          if (datePart.indexOf(splitParts[i]) >= 0) {
                              dateParts = datePart.split(splitParts[i]);
                              break;
                          }
                      }
  
                      var days = new Array();
                      var months = new Array();
                      var years = new Array();
                      var dayPart = null;
                      var monthPart = null;
                      for (var i = 0; i < dateParts.length; i++) {
                          var part = dateParts[i];
                          var isDay = that.parsedate(part, "d", calendar) || that.parsedate(part, "dd", calendar) || that.parsedate(part, "ddd", calendar) || that.parsedate(part, "dddd", calendar);
                          if (isDay) {
                              if (part.length <= 2) {
                                  dayPart = i;
                                  days.push(isDay.getDate());
                                  break
                              }
                          }
                      }
                      for (var i = 0; i < dateParts.length; i++) {
                          var part = dateParts[i];
                          var isMonth = that.parsedate(part, "M", calendar) || that.parsedate(part, "MM", calendar) || that.parsedate(part, "MMM", calendar) || that.parsedate(part, "MMMM", calendar);
                          if (isMonth) {
                              if (dayPart != undefined && dayPart == i)
                                  continue;
  
                              months.push(isMonth.getMonth());
  
                              if (part.length > 2) {
                                  monthPart = i;
                                  break;
                              }
                          }
                      }
                      for (var i = 0; i < dateParts.length; i++) {
                          var part = dateParts[i];
                          var isYear = that.parsedate(part, "yyyy", calendar);
                          if (isYear) {
                              if (dayPart != undefined && dayPart == i)
                                  continue;
  
                              if (monthPart != undefined && monthPart == i)
                                  continue;
  
                              years.push(isYear.getFullYear());
                          }
                      }
                      var dates = new Array();
                      for (var d = 0; d < days.length; d++) {
                          for (var m = 0; m < months.length; m++) {
                              for (var y = 0; y < years.length; y++) {
                                  var result = new Date(years[y], months[m], days[d]);
                                  if (years[y] < 1970)
                                      result.setFullYear(years[y]);
                                  if (result.getTime() != NaN) {
                                      dates.push(result);
                                  }
                              }
                          }
                      }
                      if (dates.length > 0) {
                          parseDate = dates[0];
                          parsed = true;
                      }
                  }
                  if (timePart) {
                      var timeParts = timePart.indexOf(":") >= 0 ? timePart.split(':') : timePart;
                      var parsedTime = that.parsedate(timePart, "h:mm tt", calendar) || that.parsedate(timePart, "h:mm:ss tt", calendar) || that.parsedate(timePart, "HH:mm:ss.fff", calendar) || that.parsedate(timePart, "HH:mm:ss.ff", calendar) || that.parsedate(timePart, "HH:mm:ss.tttt", calendar) || that.parsedate(timePart, "HH:mm:ss", calendar) || that.parsedate(timePart, "HH:mm", calendar) || that.parsedate(timePart, "HH", calendar);
  
                      var hour = 0, minute = 0, second = 0, milisecond = 0;
                      if (parsedTime && parsedTime.getTime() != NaN) {
                          hour = parsedTime.getHours();
                          minute = parsedTime.getMinutes();
                          second = parsedTime.getSeconds();
                          milisecond = parsedTime.getMilliseconds();
                      }
                      else {
                          if (timeParts.length == 1) {
                              hour = parseInt(timeParts[0]);
                          }
                          if (timeParts.length == 2) {
                              hour = parseInt(timeParts[0]);
                              minute = parseInt(timeParts[1]);
                          }
                          if (timeParts.length == 3) {
                              hour = parseInt(timeParts[0]);
                              minute = parseInt(timeParts[1]);
                              if (timeParts[2].indexOf(".") >= 0) {
                                  second = parseInt(timeParts[2].toString().split(".")[0]);
                                  milisecond = parseInt(timeParts[2].toString().split(".")[1]);
                              }
                              else {
                                  second = parseInt(timeParts[2]);
                              }
                          }
                          if (timeParts.length == 4) {
                              hour = parseInt(timeParts[0]);
                              minute = parseInt(timeParts[1]);
                              second = parseInt(timeParts[2]);
                              milisecond = parseInt(timeParts[3]);
                          }
                      }
                      if (parseDate && !isNaN(hour) && !isNaN(minute) && !isNaN(second) && !isNaN(milisecond)) {
                          parseDate.setHours(hour, minute, second, milisecond);
                          parsed = true;
                      }
                  }
                  if (parsed) {
                      return parseDate;
                  }
              }
  
              return null;
          },
  
          getparseregexp: function (cal, format) {
              // converts a format string into a regular expression with groups that
              // can be used to extract date fields from a date string.
              // check for a cached parse regex.
              var re = cal._parseRegExp;
              if (!re) {
                  cal._parseRegExp = re = {};
              }
              else {
                  var reFormat = re[format];
                  if (reFormat) {
                      return reFormat;
                  }
              }
  
              // expand single digit formats, then escape regular expression characters.
              var expFormat = this.expandFormat(cal, format).replace(/([\^\$\.\*\+\?\|\[\]\(\)\{\}])/g, "\\\\$1"),
                  regexp = ["^"],
                  groups = [],
                  index = 0,
                  quoteCount = 0,
                  tokenRegExp = this.getTokenRegExp(),
                  match;
  
              // iterate through each date token found.
              while ((match = tokenRegExp.exec(expFormat)) !== null) {
                  var preMatch = expFormat.slice(index, match.index);
                  index = tokenRegExp.lastIndex;
  
                  // don't replace any matches that occur inside a string literal.
                  quoteCount += this.appendPreOrPostMatch(preMatch, regexp);
                  if (quoteCount % 2) {
                      regexp.push(match[0]);
                      continue;
                  }
  
                  // add a regex group for the token.
                  var m = match[0],
                      len = m.length,
                      add;
                  switch (m) {
                      case 'dddd': case 'ddd':
                      case 'MMMM': case 'MMM':
                      case 'gg': case 'g':
                          add = "(\\D+)";
                          break;
                      case 'tt': case 't':
                          add = "(\\D*)";
                          break;
                      case 'yyyy':
                      case 'fff':
                      case 'ff':
                      case 'f':
                          add = "(\\d{" + len + "})";
                          break;
                      case 'dd': case 'd':
                      case 'MM': case 'M':
                      case 'yy': case 'y':
                      case 'HH': case 'H':
                      case 'hh': case 'h':
                      case 'mm': case 'm':
                      case 'ss': case 's':
                          add = "(\\d\\d?)";
                          break;
                      case 'zzz':
                          add = "([+-]?\\d\\d?:\\d{2})";
                          break;
                      case 'zz': case 'z':
                          add = "([+-]?\\d\\d?)";
                          break;
                      case '/':
                          add = "(\\" + cal["/"] + ")";
                          break;
                      default:
                          throw "Invalid date format pattern '" + m + "'.";
                          break;
                  }
                  if (add) {
                      regexp.push(add);
                  }
                  groups.push(match[0]);
              }
              this.appendPreOrPostMatch(expFormat.slice(index), regexp);
              regexp.push("$");
  
              // allow whitespace to differ when matching formats.
              var regexpStr = regexp.join('').replace(/\s+/g, "\\s+"),
                  parseRegExp = { 'regExp': regexpStr, 'groups': groups };
  
              // cache the regex for this format.
              return re[format] = parseRegExp;
          },
  
          outOfRange: function (value, low, high) {
              return value < low || value > high;
          },
  
          expandYear: function (cal, year) {
              // expands 2-digit year into 4 digits.
              var now = new Date(),
          era = this.getEra(now);
              if (year < 100) {
                  var twoDigitYearMax = cal.twoDigitYearMax;
                  twoDigitYearMax = typeof twoDigitYearMax === 'string' ? new Date().getFullYear() % 100 + parseInt(twoDigitYearMax, 10) : twoDigitYearMax;
                  var curr = this.getEraYear(now, cal, era);
                  year += curr - (curr % 100);
                  if (year > twoDigitYearMax) {
                      year -= 100;
                  }
              }
              return year;
          },
  
          parsedate: function (value, format, calendar) {
              if (calendar == undefined || calendar == null) {
                  calendar = this.defaultcalendar();
              }
              // try to parse the date string by matching against the format string
              // while using the specified culture for date field names.
              value = this.trim(value);
              var cal = calendar,
              // convert date formats into regular expressions with groupings.
              // use the regexp to determine the input format and extract the date fields.
                  parseInfo = this.getparseregexp(cal, format),
                  match = new RegExp(parseInfo.regExp).exec(value);
              if (match === null) {
                  return null;
              }
              // found a date format that matches the input.
              var groups = parseInfo.groups,
                  era = null, year = null, month = null, date = null, weekDay = null,
                  hour = 0, hourOffset, min = 0, sec = 0, msec = 0, tzMinOffset = null,
                  pmHour = false;
              // iterate the format groups to extract and set the date fields.
              for (var j = 0, jl = groups.length; j < jl; j++) {
                  var matchGroup = match[j + 1];
                  if (matchGroup) {
                      var current = groups[j],
                          clength = current.length,
                          matchInt = parseInt(matchGroup, 10);
                      switch (current) {
                          case 'dd': case 'd':
                              // Day of month.
                              date = matchInt;
                              // check that date is generally in valid range, also checking overflow below.
                              if (this.outOfRange(date, 1, 31)) return null;
                              break;
                          case 'MMM':
                          case 'MMMM':
                              month = this.getMonthIndex(cal, matchGroup, clength === 3);
                              if (this.outOfRange(month, 0, 11)) return null;
                              break;
                          case 'M': case 'MM':
                              // Month.
                              month = matchInt - 1;
                              if (this.outOfRange(month, 0, 11)) return null;
                              break;
                          case 'y': case 'yy':
                          case 'yyyy':
                              year = clength < 4 ? this.expandYear(cal, matchInt) : matchInt;
                              if (this.outOfRange(year, 0, 9999)) return null;
                              break;
                          case 'h': case 'hh':
                              // Hours (12-hour clock).
                              hour = matchInt;
                              if (hour === 12) hour = 0;
                              if (this.outOfRange(hour, 0, 11)) return null;
                              break;
                          case 'H': case 'HH':
                              // Hours (24-hour clock).
                              hour = matchInt;
                              if (this.outOfRange(hour, 0, 23)) return null;
                              break;
                          case 'm': case 'mm':
                              // Minutes.
                              min = matchInt;
                              if (this.outOfRange(min, 0, 59)) return null;
                              break;
                          case 's': case 'ss':
                              // Seconds.
                              sec = matchInt;
                              if (this.outOfRange(sec, 0, 59)) return null;
                              break;
                          case 'tt': case 't':
                              // AM/PM designator.
                              // see if it is standard, upper, or lower case PM. If not, ensure it is at least one of
                              // the AM tokens. If not, fail the parse for this format.
                              pmHour = cal.PM && (matchGroup === cal.PM[0] || matchGroup === cal.PM[1] || matchGroup === cal.PM[2]);
                              if (!pmHour && (!cal.AM || (matchGroup !== cal.AM[0] && matchGroup !== cal.AM[1] && matchGroup !== cal.AM[2]))) return null;
                              break;
                          case 'f':
                              // Deciseconds.
                          case 'ff':
                              // Centiseconds.
                          case 'fff':
                              // Milliseconds.
                              msec = matchInt * Math.pow(10, 3 - clength);
                              if (this.outOfRange(msec, 0, 999)) return null;
                              break;
                          case 'ddd':
                              // Day of week.
                          case 'dddd':
                              // Day of week.
                              weekDay = this.getDayIndex(cal, matchGroup, clength === 3);
                              if (this.outOfRange(weekDay, 0, 6)) return null;
                              break;
                          case 'zzz':
                              // Time zone offset in +/- hours:min.
                              var offsets = matchGroup.split(/:/);
                              if (offsets.length !== 2) return null;
                              hourOffset = parseInt(offsets[0], 10);
                              if (this.outOfRange(hourOffset, -12, 13)) return null;
                              var minOffset = parseInt(offsets[1], 10);
                              if (this.outOfRange(minOffset, 0, 59)) return null;
                              tzMinOffset = (hourOffset * 60) + (this.startsWith(matchGroup, '-') ? -minOffset : minOffset);
                              break;
                          case 'z': case 'zz':
                              // Time zone offset in +/- hours.
                              hourOffset = matchInt;
                              if (this.outOfRange(hourOffset, -12, 13)) return null;
                              tzMinOffset = hourOffset * 60;
                              break;
                          case 'g': case 'gg':
                              var eraName = matchGroup;
                              if (!eraName || !cal.eras) return null;
                              eraName = this.trim(eraName.toLowerCase());
                              for (var i = 0, l = cal.eras.length; i < l; i++) {
                                  if (eraName === cal.eras[i].name.toLowerCase()) {
                                      era = i;
                                      break;
                                  }
                              }
                              // could not find an era with that name
                              if (era === null) return null;
                              break;
                      }
                  }
              }
              var result = new Date(), defaultYear, convert = cal.convert;
              defaultYear = result.getFullYear();
              if (year === null) {
                  year = defaultYear;
              }
              else if (cal.eras) {
                  // year must be shifted to normal gregorian year
                  // but not if year was not specified, its already normal gregorian
                  // per the main if clause above.
                  year += cal.eras[(era || 0)].offset;
              }
              // set default day and month to 1 and January, so if unspecified, these are the defaults
              // instead of the current day/month.
              if (month === null) {
                  month = 0;
              }
              if (date === null) {
                  date = 1;
              }
              // now have year, month, and date, but in the culture's calendar.
              // convert to gregorian if necessary
              if (convert) {
                  result = convert.toGregorian(year, month, date);
                  // conversion failed, must be an invalid match
                  if (result === null) return null;
              }
              else {
                  // have to set year, month and date together to avoid overflow based on current date.
                  result.setFullYear(year, month, date);
                  // check to see if date overflowed for specified month (only checked 1-31 above).
                  if (result.getDate() !== date) return null;
                  // invalid day of week.
                  if (weekDay !== null && result.getDay() !== weekDay) {
                      return null;
                  }
              }
              // if pm designator token was found make sure the hours fit the 24-hour clock.
              if (pmHour && hour < 12) {
                  hour += 12;
              }
              result.setHours(hour, min, sec, msec);
              if (tzMinOffset !== null) {
                  // adjust timezone to utc before applying local offset.
                  var adjustedMin = result.getMinutes() - (tzMinOffset + result.getTimezoneOffset());
                  // Safari limits hours and minutes to the range of -127 to 127.  We need to use setHours
                  // to ensure both these fields will not exceed this range.  adjustedMin will range
                  // somewhere between -1440 and 1500, so we only need to split this into hours.
                  result.setHours(result.getHours() + parseInt(adjustedMin / 60, 10), adjustedMin % 60);
              }
              return result;
          },
  
          cleardatescache: function () {
              this.datescache = new Array();
          },
  
          formatDate: function (value, format, calendar)
          {
              return this.formatdate(value, format, calendar);
          },
  
          formatdate: function (value, format, calendar) {
              if (calendar == undefined || calendar == null) {
                  calendar = this.defaultcalendar();
              }
  
              if (typeof value === 'string') {
                  return value;
              }
  
              var lookupkey = value.toString() + "_" + format;
              if (this.datescache && this.datescache[lookupkey]) {
                  if (format.indexOf('f') == -1) {
                      return this.datescache[lookupkey];
                  }
              }
  
              if (!format || !format.length || format === 'i') {
                  var ret;
                  ret = this.formatDate(value, calendar.patterns.F, calendar);
                  return ret;
              }
  
              var eras = calendar.eras,
              sortable = format === "s";
              format = this.expandFormat(calendar, format);
  
              // Start with an empty string
              ret = [];
              var hour,
              zeros = ['0', '00', '000'],
              foundDay,
              checkedDay,
              dayPartRegExp = /([^d]|^)(d|dd)([^d]|$)/g,
              quoteCount = 0,
              tokenRegExp = this.getTokenRegExp(),
              converted;
  
              function padZeros(num, c) {
                  var r, s = num + '';
                  if (c > 1 && s.length < c) {
                      r = (zeros[c - 2] + s);
                      return r.substr(r.length - c, c);
                  }
                  else {
                      r = s;
                  }
                  return r;
              }
  
              function hasDay() {
                  if (foundDay || checkedDay) {
                      return foundDay;
                  }
                  foundDay = dayPartRegExp.test(format);
                  checkedDay = true;
                  return foundDay;
              }
  
              function getPart(date, part) {
                  if (converted) {
                      return converted[part];
                  }
                  if (date.getMonth != undefined) {
                      switch (part) {
                          case 0: return date.getFullYear();
                          case 1: return date.getMonth();
                          case 2: return date.getDate();
                      }
                  }
              }
  
              for (; ; ) {
                  // Save the current index
                  var index = tokenRegExp.lastIndex,
                  // Look for the next pattern
                  ar = tokenRegExp.exec(format);
  
                  // Append the text before the pattern (or the end of the string if not found)
                  var preMatch = format.slice(index, ar ? ar.index : format.length);
                  quoteCount += this.appendPreOrPostMatch(preMatch, ret);
  
                  if (!ar) {
                      break;
                  }
  
                  // do not replace any matches that occur inside a string literal.
                  if (quoteCount % 2) {
                      ret.push(ar[0]);
                      continue;
                  }
  
                  var current = ar[0],
                  clength = current.length;
  
                  switch (current) {
                      case "ddd":
                          //Day of the week, as a three-letter abbreviation
                      case "dddd":
                          // Day of the week, using the full name
                          var names = (clength === 3) ? calendar.days.namesAbbr : calendar.days.names;
                          ret.push(names[value.getDay()]);
                          break;
                      case "d":
                          // Day of month, without leading zero for single-digit days
                      case "dd":
                          // Day of month, with leading zero for single-digit days
                          foundDay = true;
                          ret.push(padZeros(getPart(value, 2), clength));
                          break;
                      case "MMM":
                          // Month, as a three-letter abbreviation
                      case "MMMM":
                          // Month, using the full name
                          var part = getPart(value, 1);
                          ret.push(calendar.months[clength === 3 ? "namesAbbr" : "names"][part]);
                          break;
                      case "M":
                          // Month, as digits, with no leading zero for single-digit months
                      case "MM":
                          // Month, as digits, with leading zero for single-digit months
                          ret.push(padZeros(getPart(value, 1) + 1, clength));
                          break;
                      case "y":
                          // Year, as two digits, but with no leading zero for years less than 10
                      case "yy":
                          // Year, as two digits, with leading zero for years less than 10
                      case "yyyy":
                          // Year represented by four full digits
                          part = this.getEraYear(value, calendar, this.getEra(value, eras), sortable);
                          if (clength < 4) {
                              part = part % 100;
                          }
                          ret.push(padZeros(part, clength));
                          break;
                      case "h":
                          // Hours with no leading zero for single-digit hours, using 12-hour clock
                      case "hh":
                          // Hours with leading zero for single-digit hours, using 12-hour clock
                          hour = value.getHours() % 12;
                          if (hour === 0) hour = 12;
                          ret.push(padZeros(hour, clength));
                          break;
                      case "H":
                          // Hours with no leading zero for single-digit hours, using 24-hour clock
                      case "HH":
                          // Hours with leading zero for single-digit hours, using 24-hour clock
                          ret.push(padZeros(value.getHours(), clength));
                          break;
                      case "m":
                          // Minutes with no leading zero  for single-digit minutes
                      case "mm":
                          // Minutes with leading zero  for single-digit minutes
                          ret.push(padZeros(value.getMinutes(), clength));
                          break;
                      case "s":
                          // Seconds with no leading zero for single-digit seconds
                      case "ss":
                          // Seconds with leading zero for single-digit seconds
                          ret.push(padZeros(value.getSeconds(), clength));
                          break;
                      case "t":
                          // One character am/pm indicator ("a" or "p")
                      case "tt":
                          // Multicharacter am/pm indicator
                          part = value.getHours() < 12 ? (calendar.AM ? calendar.AM[0] : " ") : (calendar.PM ? calendar.PM[0] : " ");
                          ret.push(clength === 1 ? part.charAt(0) : part);
                          break;
                      case "f":
                          // Deciseconds
                      case "ff":
                          // Centiseconds
                      case "fff":
                          // Milliseconds
                          ret.push(padZeros(value.getMilliseconds(), 3).substr(0, clength));
                          break;
                      case "z":
                          // Time zone offset, no leading zero
                      case "zz":
                          // Time zone offset with leading zero
                          hour = value.getTimezoneOffset() / 60;
                          ret.push((hour <= 0 ? '+' : '-') + padZeros(Math.floor(Math.abs(hour)), clength));
                          break;
                      case "zzz":
                          // Time zone offset with leading zero
                          hour = value.getTimezoneOffset() / 60;
                          ret.push((hour <= 0 ? '+' : '-') + padZeros(Math.floor(Math.abs(hour)), 2) +
                          // Hard coded ":" separator, rather than using calendar.TimeSeparator
                          // Repeated here for consistency, plus ":" was already assumed in date parsing.
                      ":" + padZeros(Math.abs(value.getTimezoneOffset() % 60), 2));
                          break;
                      case "g":
                      case "gg":
                          if (calendar.eras) {
                              ret.push(calendar.eras[this.getEra(value, eras)].name);
                          }
                          break;
                      case "/":
                          ret.push(calendar["/"]);
                          break;
                      default:
                          throw "Invalid date format pattern '" + current + "'.";
                          break;
                  }
              }
  
              var result = ret.join('');
  
              if (!this.datescache) {
                  this.datescache = new Array();
              }
  
              this.datescache[lookupkey] = result;
              return result;
          }
      });
  
      // AJAX
      $.jqx.data = {};
      var
          ajaxLocParts,
          ajaxLocation,
  
          rhash = /#.*$/,
          rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg,
          rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,
          rnoContent = /^(?:GET|HEAD)$/,
          rprotocol = /^\/\//,
          rquery = /\?/,
          rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
          rts = /([?&])_=[^&]*/,
          rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,
          core_rspace = /\s+/,
          _load = $.fn.load,
          prefilters = {},
          transports = {},
          allTypes = ["*/"] + ["*"];
  
      try {
          ajaxLocation = location.href;
      } catch (e) {
          ajaxLocation = document.createElement("a");
          ajaxLocation.href = "";
          ajaxLocation = ajaxLocation.href;
      }
  
      ajaxLocParts = rurl.exec(ajaxLocation.toLowerCase()) || [];
  
      function addToPrefiltersOrTransports(structure) {
  
          return function (dataTypeExpression, func) {
  
              if (typeof dataTypeExpression !== "string") {
                  func = dataTypeExpression;
                  dataTypeExpression = "*";
              }
  
              var dataType, list, placeBefore,
                  dataTypes = dataTypeExpression.toLowerCase().split(core_rspace),
                  i = 0,
                  length = dataTypes.length;
  
              if ($.isFunction(func)) {
                  for (; i < length; i++) {
                      dataType = dataTypes[i];
                      placeBefore = /^\+/.test(dataType);
                      if (placeBefore) {
                          dataType = dataType.substr(1) || "*";
                      }
                      list = structure[dataType] = structure[dataType] || [];
                      list[placeBefore ? "unshift" : "push"](func);
                  }
              }
          };
      }
  
      function inspectPrefiltersOrTransports(structure, options, originalOptions, jqXHR,
              dataType /* internal */, inspected /* internal */) {
  
          dataType = dataType || options.dataTypes[0];
          inspected = inspected || {};
  
          inspected[dataType] = true;
  
          var selection,
              list = structure[dataType],
              i = 0,
              length = list ? list.length : 0,
              executeOnly = (structure === prefilters);
  
          for (; i < length && (executeOnly || !selection) ; i++) {
              selection = list[i](options, originalOptions, jqXHR);
              if (typeof selection === "string") {
                  if (!executeOnly || inspected[selection]) {
                      selection = undefined;
                  } else {
                      options.dataTypes.unshift(selection);
                      selection = inspectPrefiltersOrTransports(
                              structure, options, originalOptions, jqXHR, selection, inspected);
                  }
              }
          }
          if ((executeOnly || !selection) && !inspected["*"]) {
              selection = inspectPrefiltersOrTransports(
                      structure, options, originalOptions, jqXHR, "*", inspected);
          }
          return selection;
      }
  
      function ajaxExtend(target, src) {
          var key, deep,
              flatOptions = $.jqx.data.ajaxSettings.flatOptions || {};
          for (key in src) {
              if (src[key] !== undefined) {
                  (flatOptions[key] ? target : (deep || (deep = {})))[key] = src[key];
              }
          }
          if (deep) {
              $.extend(true, target, deep);
          }
      }
  
      $.extend($.jqx.data, {
          ajaxSetup: function (target, settings) {
              if (settings) {
                  ajaxExtend(target, $.jqx.data.ajaxSettings);
              } else {
                  settings = target;
                  target = $.jqx.data.ajaxSettings;
              }
              ajaxExtend(target, settings);
              return target;
          },
  
          ajaxSettings: {
              url: ajaxLocation,
              isLocal: rlocalProtocol.test(ajaxLocParts[1]),
              global: true,
              type: "GET",
              contentType: "application/x-www-form-urlencoded; charset=UTF-8",
              processData: true,
              async: true,
            
              accepts: {
                  xml: "application/xml, text/xml",
                  html: "text/html",
                  text: "text/plain",
                  json: "application/json, text/javascript",
                  "*": allTypes
              },
  
              contents: {
                  xml: /xml/,
                  html: /html/,
                  json: /json/
              },
  
              responseFields: {
                  xml: "responseXML",
                  text: "responseText"
              },
  
              converters: {
                  "* text": window.String,
                  "text html": true,
                  "text json": $.parseJSON,
                  "text xml": $.parseXML
              },
  
              flatOptions: {
                  context: true,
                  url: true
              }
          },
  
          ajaxPrefilter: addToPrefiltersOrTransports(prefilters),
          ajaxTransport: addToPrefiltersOrTransports(transports),
  
          ajax: function (url, options) {
  
              if (typeof url === "object") {
                  options = url;
                  url = undefined;
              }
  
              options = options || {};
  
              var ifModifiedKey,
                  responseHeadersString,
                  responseHeaders,
                  transport,
                  timeoutTimer,
                  parts,
                  fireGlobals,
                  i,
                  s = $.jqx.data.ajaxSetup({}, options),
                  callbackContext = s.context || s,
                  globalEventContext = callbackContext !== s &&
                      (callbackContext.nodeType || callbackContext instanceof $) ?
                              $(callbackContext) : $.event,
                  deferred = $.Deferred(),
                  completeDeferred = $.Callbacks("once memory"),
                  statusCode = s.statusCode || {},
                  requestHeaders = {},
                  requestHeadersNames = {},
                  state = 0,
                  strAbort = "canceled",
                  jqXHR = {
                      readyState: 0,
                      setRequestHeader: function (name, value) {
                          if (!state) {
                              var lname = name.toLowerCase();
                              name = requestHeadersNames[lname] = requestHeadersNames[lname] || name;
                              requestHeaders[name] = value;
                          }
                          return this;
                      },
                      getAllResponseHeaders: function () {
                          return state === 2 ? responseHeadersString : null;
                      },
                      getResponseHeader: function (key) {
                          var match;
                          if (state === 2) {
                              if (!responseHeaders) {
                                  responseHeaders = {};
                                  while ((match = rheaders.exec(responseHeadersString))) {
                                      responseHeaders[match[1].toLowerCase()] = match[2];
                                  }
                              }
                              match = responseHeaders[key.toLowerCase()];
                          }
                          return match === undefined ? null : match;
                      },
  
                      overrideMimeType: function (type) {
                          if (!state) {
                              s.mimeType = type;
                          }
                          return this;
                      },
  
                      abort: function (statusText) {
                          statusText = statusText || strAbort;
                          if (transport) {
                              transport.abort(statusText);
                          }
                          done(0, statusText);
                          return this;
                      }
                  };
  
              function done(status, nativeStatusText, responses, headers) {
                  var isSuccess, success, error, response, modified,
                      statusText = nativeStatusText;
  
                  if (state === 2) {
                      return;
                  }
  
                  state = 2;
                  if (timeoutTimer) {
                      clearTimeout(timeoutTimer);
                  }
  
                  transport = undefined;
                  responseHeadersString = headers || "";
                  jqXHR.readyState = status > 0 ? 4 : 0;
  
                  if (responses) {
                      response = ajaxHandleResponses(s, jqXHR, responses);
                  }
  
                  if (status >= 200 && status < 300 || status === 304) {
  
                      if (s.ifModified) {
  
                          modified = jqXHR.getResponseHeader("Last-Modified");
                          if (modified) {
                              $.lastModified[ifModifiedKey] = modified;
                          }
                          modified = jqXHR.getResponseHeader("Etag");
                          if (modified) {
                              $.etag[ifModifiedKey] = modified;
                          }
                      }
  
                      if (status === 304) {
                          statusText = "notmodified";
                          isSuccess = true;
                      } else {
  
                          isSuccess = ajaxConvert(s, response);
                          statusText = isSuccess.state;
                          success = isSuccess.data;
                          error = isSuccess.error;
                          isSuccess = !error;
                      }
                  } else {
                      error = statusText;
                      if (!statusText || status) {
                          statusText = "error";
                          if (status < 0) {
                              status = 0;
                          }
                      }
                  }
  
                  jqXHR.status = status;
                  jqXHR.statusText = (nativeStatusText || statusText) + "";
  
                  if (isSuccess) {
                      deferred.resolveWith(callbackContext, [success, statusText, jqXHR]);
                  } else {
                      deferred.rejectWith(callbackContext, [jqXHR, statusText, error]);
                  }
  
                  jqXHR.statusCode(statusCode);
                  statusCode = undefined;
  
                  if (fireGlobals) {
                      globalEventContext.trigger("ajax" + (isSuccess ? "Success" : "Error"),
                              [jqXHR, s, isSuccess ? success : error]);
                  }
  
                  completeDeferred.fireWith(callbackContext, [jqXHR, statusText]);
  
                  if (fireGlobals) {
                      globalEventContext.trigger("ajaxComplete", [jqXHR, s]);
                      if (!(--$.active)) {
                          $.event.trigger("ajaxStop");
                      }
                  }
              }
  
              deferred.promise(jqXHR);
              jqXHR.success = jqXHR.done;
              jqXHR.error = jqXHR.fail;
              jqXHR.complete = completeDeferred.add;
  
              jqXHR.statusCode = function (map) {
                  if (map) {
                      var tmp;
                      if (state < 2) {
                          for (tmp in map) {
                              statusCode[tmp] = [statusCode[tmp], map[tmp]];
                          }
                      } else {
                          tmp = map[jqXHR.status];
                          jqXHR.always(tmp);
                      }
                  }
                  return this;
              };
  
              s.url = ((url || s.url) + "").replace(rhash, "").replace(rprotocol, ajaxLocParts[1] + "//");
              s.dataTypes = $.trim(s.dataType || "*").toLowerCase().split(core_rspace);
  
              if (s.crossDomain == null) {
                  parts = rurl.exec(s.url.toLowerCase());
                  s.crossDomain = !!(parts &&
                      (parts[1] !== ajaxLocParts[1] || parts[2] !== ajaxLocParts[2] ||
                          (parts[3] || (parts[1] === "http:" ? 80 : 443)) !=
                              (ajaxLocParts[3] || (ajaxLocParts[1] === "http:" ? 80 : 443)))
                  );
              }
  
              if (s.data && s.processData && typeof s.data !== "string") {
                  s.data = $.param(s.data, s.traditional);
              }
  
              inspectPrefiltersOrTransports(prefilters, s, options, jqXHR);
  
              if (state === 2) {
                  return jqXHR;
              }
  
              fireGlobals = s.global;
              s.type = s.type.toUpperCase();
              s.hasContent = !rnoContent.test(s.type);
  
              if (fireGlobals && $.active++ === 0) {
                  $.event.trigger("ajaxStart");
              }
  
              if (!s.hasContent) {
                  if (s.data) {
                      s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
                      delete s.data;
                  }
  
                  ifModifiedKey = s.url;
  
                  if (s.cache === false) {
  
                      var ts = (new Date()).getTime(),
                          ret = s.url.replace(rts, "$1_=" + ts);
  
                      s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "");
                  }
              }
  
              if (s.data && s.hasContent && s.contentType !== false || options.contentType) {
                  jqXHR.setRequestHeader("Content-Type", s.contentType);
              }
  
              if (s.ifModified) {
                  ifModifiedKey = ifModifiedKey || s.url;
                  if ($.lastModified[ifModifiedKey]) {
                      jqXHR.setRequestHeader("If-Modified-Since", $.lastModified[ifModifiedKey]);
                  }
                  if ($.etag[ifModifiedKey]) {
                      jqXHR.setRequestHeader("If-None-Match", $.etag[ifModifiedKey]);
                  }
              }
  
              jqXHR.setRequestHeader(
                  "Accept",
                  s.dataTypes[0] && s.accepts[s.dataTypes[0]] ?
                      s.accepts[s.dataTypes[0]] + (s.dataTypes[0] !== "*" ? ", " + allTypes + "; q=0.01" : "") :
                      s.accepts["*"]
              );
  
              for (i in s.headers) {
                  jqXHR.setRequestHeader(i, s.headers[i]);
              }
  
              if (s.beforeSend && (s.beforeSend.call(callbackContext, jqXHR, s) === false || state === 2)) {
                  return jqXHR.abort();
  
              }
  
              strAbort = "abort";
  
              for (i in { success: 1, error: 1, complete: 1 }) {
                  jqXHR[i](s[i]);
              }
  
              transport = inspectPrefiltersOrTransports(transports, s, options, jqXHR);
  
              if (!transport) {
                  done(-1, "No Transport");
              } else {
                  jqXHR.readyState = 1;
                  if (fireGlobals) {
                      globalEventContext.trigger("ajaxSend", [jqXHR, s]);
                  }
                  if (s.async && s.timeout > 0) {
                      timeoutTimer = setTimeout(function () {
                          jqXHR.abort("timeout");
                      }, s.timeout);
                  }
  
                  try {
                      state = 1;
                      transport.send(requestHeaders, done);
                  } catch (e) {
                      if (state < 2) {
                          done(-1, e);
                      } else {
                          throw e;
                      }
                  }
              }
  
              return jqXHR;
          },
  
          active: 0,
  
          lastModified: {},
          etag: {}
  
      });
  
      function ajaxHandleResponses(s, jqXHR, responses) {
  
          var ct, type, finalDataType, firstDataType,
              contents = s.contents,
              dataTypes = s.dataTypes,
              responseFields = s.responseFields;
  
          for (type in responseFields) {
              if (type in responses) {
                  jqXHR[responseFields[type]] = responses[type];
              }
          }
  
          while (dataTypes[0] === "*") {
              dataTypes.shift();
              if (ct === undefined) {
                  ct = s.mimeType || jqXHR.getResponseHeader("content-type");
              }
          }
  
          if (ct) {
              for (type in contents) {
                  if (contents[type] && contents[type].test(ct)) {
                      dataTypes.unshift(type);
                      break;
                  }
              }
          }
  
          if (dataTypes[0] in responses) {
              finalDataType = dataTypes[0];
          } else {
              for (type in responses) {
                  if (!dataTypes[0] || s.converters[type + " " + dataTypes[0]]) {
                      finalDataType = type;
                      break;
                  }
                  if (!firstDataType) {
                      firstDataType = type;
                  }
              }
              finalDataType = finalDataType || firstDataType;
          }
  
          if (finalDataType) {
              if (finalDataType !== dataTypes[0]) {
                  dataTypes.unshift(finalDataType);
              }
              return responses[finalDataType];
          }
      }
  
      function ajaxConvert(s, response) {
          var conv, conv2, current, tmp,
              dataTypes = s.dataTypes.slice(),
              prev = dataTypes[0],
              converters = {},
              i = 0;
  
          if (s.dataFilter) {
              response = s.dataFilter(response, s.dataType);
          }
  
          if (dataTypes[1]) {
              for (conv in s.converters) {
                  converters[conv.toLowerCase()] = s.converters[conv];
              }
          }
  
          for (; (current = dataTypes[++i]) ;) {
              if (current !== "*") {
                  if (prev !== "*" && prev !== current) {
                      conv = converters[prev + " " + current] || converters["* " + current];
  
                      if (!conv) {
                          for (conv2 in converters) {
                              tmp = conv2.split(" ");
                              if (tmp[1] === current) {
                                  conv = converters[prev + " " + tmp[0]] ||
                                      converters["* " + tmp[0]];
                                  if (conv) {
                                      if (conv === true) {
                                          conv = converters[conv2];
  
                                      } else if (converters[conv2] !== true) {
                                          current = tmp[0];
                                          dataTypes.splice(i--, 0, current);
                                      }
  
                                      break;
                                  }
                              }
                          }
                      }
  
                      if (conv !== true) {
                          if (conv && s["throws"]) {
                              response = conv(response);
                          } else {
                              try {
                                  response = conv(response);
                              } catch (e) {
                                  return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
                              }
                          }
                      }
                  }
  
                  prev = current;
              }
          }
  
          return { state: "success", data: response };
      }
      var oldCallbacks = [],
          rquestion = /\?/,
          rjsonp = /(=)\?(?=&|$)|\?\?/,
          nonce = (new Date()).getTime();
  
      $.jqx.data.ajaxSetup({
          jsonp: "callback",
          jsonpCallback: function () {
              var callback = oldCallbacks.pop() || ($.expando + "_" + (nonce++));
              this[callback] = true;
              return callback;
          }
      });
  
      $.jqx.data.ajaxPrefilter("json jsonp", function (s, originalSettings, jqXHR) {
  
          var callbackName, overwritten, responseContainer,
              data = s.data,
              url = s.url,
              hasCallback = s.jsonp !== false,
              replaceInUrl = hasCallback && rjsonp.test(url),
              replaceInData = hasCallback && !replaceInUrl && typeof data === "string" &&
                  !(s.contentType || "").indexOf("application/x-www-form-urlencoded") &&
                  rjsonp.test(data);
  
          if (s.dataTypes[0] === "jsonp" || replaceInUrl || replaceInData) {
  
              callbackName = s.jsonpCallback = $.isFunction(s.jsonpCallback) ?
                  s.jsonpCallback() :
                  s.jsonpCallback;
              overwritten = window[callbackName];
  
              if (replaceInUrl) {
                  s.url = url.replace(rjsonp, "$1" + callbackName);
              } else if (replaceInData) {
                  s.data = data.replace(rjsonp, "$1" + callbackName);
              } else if (hasCallback) {
                  s.url += (rquestion.test(url) ? "&" : "?") + s.jsonp + "=" + callbackName;
              }
  
              s.converters["script json"] = function () {
                  if (!responseContainer) {
                      $.error(callbackName + " was not called");
                  }
                  return responseContainer[0];
              };
  
              s.dataTypes[0] = "json";
  
              window[callbackName] = function () {
                  responseContainer = arguments;
              };
  
              jqXHR.always(function () {
                  window[callbackName] = overwritten;
                  if (s[callbackName]) {
                      s.jsonpCallback = originalSettings.jsonpCallback;
  
                      oldCallbacks.push(callbackName);
                  }
  
                  if (responseContainer && $.isFunction(overwritten)) {
                      overwritten(responseContainer[0]);
                  }
  
                  responseContainer = overwritten = undefined;
              });
  
              return "script";
          }
      });
  
      $.jqx.data.ajaxSetup({
          accepts: {
              script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
          },
          contents: {
              script: /javascript|ecmascript/
          },
          converters: {
              "text script": function (text) {
                  $.globalEval(text);
                  return text;
              }
          }
      });
  
      $.jqx.data.ajaxPrefilter("script", function (s) {
          if (s.cache === undefined) {
              s.cache = false;
          }
          if (s.crossDomain) {
              s.type = "GET";
              s.global = false;
          }
      });
  
      $.jqx.data.ajaxTransport("script", function (s) {
          if (s.crossDomain) {
              var script,
                  head = document.head || document.getElementsByTagName("head")[0] || document.documentElement;
  
              return {
  
                  send: function (_, callback) {
  
                      script = document.createElement("script");
  
                      script.async = "async";
  
                      if (s.scriptCharset) {
                          script.charset = s.scriptCharset;
                      }
  
                      script.src = s.url;
  
                      script.onload = script.onreadystatechange = function (_, isAbort) {
  
                          if (isAbort || !script.readyState || /loaded|complete/.test(script.readyState)) {
  
                              script.onload = script.onreadystatechange = null;
  
                              if (head && script.parentNode) {
                                  head.removeChild(script);
                              }
  
                              script = undefined;
  
                              if (!isAbort) {
                                  callback(200, "success");
                              }
                          }
                      };
                      head.insertBefore(script, head.firstChild);
                  },
  
                  abort: function () {
                      if (script) {
                          script.onload(0, 1);
                      }
                  }
              };
          }
      });
      var xhrCallbacks,
          xhrOnUnloadAbort = window.ActiveXObject ? function () {
              for (var key in xhrCallbacks) {
                  xhrCallbacks[key](0, 1);
              }
          } : false,
          xhrId = 0;
  
      function createStandardXHR() {
          try {
              return new window.XMLHttpRequest();
          } catch (e) { }
      }
  
      function createActiveXHR() {
          try {
              return new window.ActiveXObject("Microsoft.XMLHTTP");
          } catch (e) { }
      }
  
      $.jqx.data.ajaxSettings.xhr = window.ActiveXObject ?
          function () {
              return !this.isLocal && createStandardXHR() || createActiveXHR();
          } :
          createStandardXHR;
  
      (function (xhr) {
          $.extend($.support, {
              ajax: !!xhr,
              cors: !!xhr && ("withCredentials" in xhr)
          });
      })($.jqx.data.ajaxSettings.xhr());
  
      if (!$.support) $.support = {ajax:true};
      if ($.support.ajax) {
  
          $.jqx.data.ajaxTransport(function (s) {
              if (!s.crossDomain || $.support.cors) {
  
                  var callback;
  
                  return {
                      send: function (headers, complete) {
  
                          var handle, i,
                              xhr = s.xhr();
  
                          if (s.username) {
                              xhr.open(s.type, s.url, s.async, s.username, s.password);
                          } else {
                              xhr.open(s.type, s.url, s.async);
                          }
  
                          if (s.xhrFields) {
                              for (i in s.xhrFields) {
                                  xhr[i] = s.xhrFields[i];
                              }
                          }
  
                          if (s.mimeType && xhr.overrideMimeType) {
                              xhr.overrideMimeType(s.mimeType);
                          }
  
  
                          if (!s.crossDomain && !headers["X-Requested-With"]) {
                              headers["X-Requested-With"] = "XMLHttpRequest";
                          }
  
                          try {
                              for (i in headers) {
                                  xhr.setRequestHeader(i, headers[i]);
                              }
                          } catch (_) { }
  
                          xhr.send((s.hasContent && s.data) || null);
  
                          callback = function (_, isAbort) {
  
                              var status,
                                  statusText,
                                  responseHeaders,
                                  responses,
                                  xml;
                              try {
  
                                  if (callback && (isAbort || xhr.readyState === 4)) {
                                      callback = undefined;
                                      if (handle) {
                                          xhr.onreadystatechange = function () { };
                                          if (xhrOnUnloadAbort) {
                                              delete xhrCallbacks[handle];
                                          }
                                      }
  
                                      if (isAbort) {
                                          if (xhr.readyState !== 4) {
                                              xhr.abort();
                                          }
                                      } else {
                                          status = xhr.status;
                                          responseHeaders = xhr.getAllResponseHeaders();
                                          responses = {};
                                          xml = xhr.responseXML;
  
                                          if (xml && xml.documentElement /* #4958 */) {
                                              responses.xml = xml;
                                          }
  
                                          try {
                                              responses.text = xhr.responseText;
                                          } catch (e) {
                                          }
  
                                          try {
                                              statusText = xhr.statusText;
                                          } catch (e) {
                                              statusText = "";
                                          }
  
                                          if (!status && s.isLocal && !s.crossDomain) {
                                              status = responses.text ? 200 : 404;
                                          } else if (status === 1223) {
                                              status = 204;
                                          }
                                      }
                                  }
                              } catch (firefoxAccessException) {
                                  if (!isAbort) {
                                      complete(-1, firefoxAccessException);
                                  }
                              }
  
                              if (responses) {
                                  complete(status, statusText, responses, responseHeaders);
                              }
                          };
  
                          if (!s.async) {
                              callback();
                          } else if (xhr.readyState === 4) {
                              setTimeout(callback, 0);
                          } else {
                              handle = ++xhrId;
                              if (xhrOnUnloadAbort) {
                                  if (!xhrCallbacks) {
                                      xhrCallbacks = {};
                                      $(window).unload(xhrOnUnloadAbort);
                                  }
                                  xhrCallbacks[handle] = callback;
                              }
                              xhr.onreadystatechange = callback;
                          }
                      },
  
                      abort: function () {
                          if (callback) {
                              callback(0, 1);
                          }
                      }
                  };
              }
          });
      }
      $.jqx.filter = function () {
          this.operator = 'and';
          var and_operator = 0;
          var or_operator = 1;
          var stringcomparisonoperators = ['EMPTY', 'NOT_EMPTY', 'CONTAINS', 'CONTAINS_CASE_SENSITIVE',
          'DOES_NOT_CONTAIN', 'DOES_NOT_CONTAIN_CASE_SENSITIVE', 'STARTS_WITH', 'STARTS_WITH_CASE_SENSITIVE',
          'ENDS_WITH', 'ENDS_WITH_CASE_SENSITIVE', 'EQUAL', 'EQUAL_CASE_SENSITIVE', 'NULL', 'NOT_NULL'];
          var numericcomparisonoperators = ['EQUAL', 'NOT_EQUAL', 'LESS_THAN', 'LESS_THAN_OR_EQUAL', 'GREATER_THAN', 'GREATER_THAN_OR_EQUAL', 'NULL', 'NOT_NULL'];
          var datecomparisonoperators = ['EQUAL', 'NOT_EQUAL', 'LESS_THAN', 'LESS_THAN_OR_EQUAL', 'GREATER_THAN', 'GREATER_THAN_OR_EQUAL', 'NULL', 'NOT_NULL'];
          var booleancomparisonoperators = ['EQUAL', 'NOT_EQUAL'];
  
          var filters = new Array();
          var comparisonoperators = new Array();
  
          this.evaluate = function (value) {
              var result = true;
              for (var i = 0; i < filters.length; i++) {
                  var currentResult = filters[i].evaluate(value);
                  if (i == 0) {
                      result = currentResult;
                  }
                  else {
                      if (comparisonoperators[i] == or_operator || comparisonoperators[i] == "or")
                          result = result || currentResult;
                      else
                          result = result && currentResult;
                  }
              }
  
              return result;
          }
  
          this.getfilterscount = function () {
              return filters.length;
          }
  
          this.setoperatorsbyfiltertype = function (type, array) {
              switch (type) {
                  case "numericfilter":
                      numericcomparisonoperators = array;
                      break;
                  case "stringfilter":
                      stringcomparisonoperators = array;
                      break;
                  case "datefilter":
                      datecomparisonoperators = array;
                      break;
                  case "booleanfilter":
                      booleancomparisonoperators = array;
                      break;
              }
          }
  
          this.getoperatorsbyfiltertype = function (type) {
              var array = new Array();
              switch (type) {
                  case "numericfilter":
                      array = numericcomparisonoperators.slice(0);
                      break;
                  case "stringfilter":
                      array = stringcomparisonoperators.slice(0);
                      break;
                  case "datefilter":
                      array = datecomparisonoperators.slice(0);
                      break;
                  case "booleanfilter":
                      array = booleancomparisonoperators.slice(0);
                      break;
              }
              return array;
          }
  
          var generatefilterkey = function () {
              var S4 = function () {
                  return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
              };
              return (S4() + "-" + S4() + "-" + S4());
          }
  
          this.createfilter = function (filtertype, filtervalue, filtercomparisonoperator, customfilter, formatstring, localization) {
              if (filtertype == null || filtertype == undefined)
                  return null;
  
              switch (filtertype) {
                  case 'numericfilter':
                      return new numericfilter(filtervalue, filtercomparisonoperator.toUpperCase());
                  case 'stringfilter':
                      return new stringfilter(filtervalue, filtercomparisonoperator.toUpperCase());
                  case 'datefilter':
                      return new datefilter(filtervalue, filtercomparisonoperator.toUpperCase(), formatstring, localization);
                  case 'booleanfilter':
                      return new booleanfilter(filtervalue, filtercomparisonoperator.toUpperCase());
                  case 'custom':
                      return new filter(filtervalue, filtercomparisonoperator.toUpperCase(), customfilter);
              }
  
              throw new Error("jqxGrid: There is no such filter type. The available filter types are: 'numericfilter', 'stringfilter', 'datefilter' and 'booleanfilter'");
              return null;
          }
  
          this.getfilters = function () {
              var filtersarray = new Array();
              for (var i = 0; i < filters.length; i++) {
                  var filter = { value: filters[i].filtervalue, condition: filters[i].comparisonoperator, operator: comparisonoperators[i], type: filters[i].type };
                  if (filters[i].data) {
                      filter.id = filters[i].data;
                  }
                  filtersarray[i] = filter;
              }
              return filtersarray;
          }
  
          this.addfilter = function (comparisonoperator, filter) {
              filters[filters.length] = filter;
              filter.key = generatefilterkey();
              comparisonoperators[comparisonoperators.length] = comparisonoperator;
          }
  
          this.removefilter = function (filter) {
              for (var i = 0; i < filters.length; i++) {
                  if (filters[i].key == filter.key) {
                      filters.splice(i, 1);
                      comparisonoperators.splice(i, 1);
                      break;
                  }
              }
          }
  
          this.getoperatorat = function (index) {
              if (index == undefined || index == null)
                  return null;
  
              if (index < 0 || index > filters.length)
                  return null;
  
              return comparisonoperators[index];
          }
  
          this.setoperatorat = function (index, comparisonoperator) {
              if (index == undefined || index == null)
                  return null;
  
              if (index < 0 || index > filters.length)
                  return null;
  
              comparisonoperators[comparisonoperator] = comparisonoperator;
          }
  
          this.getfilterat = function (index) {
              if (index == undefined || index == null)
                  return null;
  
              if (index < 0 || index > filters.length)
                  return null;
  
              return filters[index];
          }
  
          this.setfilterat = function (index, filter) {
              if (index == undefined || index == null)
                  return null;
  
              if (index < 0 || index > filters.length)
                  return null;
  
              filter.key = generatefilterkey();
              filters[index] = filter;
          }
  
          this.clear = function () {
              filters = new Array();
              comparisonoperators = new Array();
          }
  
          var stringfilter = function (filtervalue, comparisonoperator) {
              this.filtervalue = filtervalue;
              this.comparisonoperator = comparisonoperator;
              this.type = 'stringfilter';
              this.evaluate = function (value) {
                  var filtervalue = this.filtervalue;
                  var comparisonoperator = this.comparisonoperator;
                  if (value == null || value == undefined || value == "") {
                      if (comparisonoperator == 'NULL')
                          return true;
  
                      if (comparisonoperator == "EQUAL" && value == filtervalue) {
                          return true;
                      }
  
                      if (comparisonoperator == "NOT_EQUAL" && value != filtervalue) {
                          return true;
                      }
  
                      if (comparisonoperator != 'EMPTY')
                          return false;
                      else if (value == "")
                          return true;
                  }
  
                  var val = "";
                  try {
                      val = value.toString();
                  }
                  catch (error) {
                      return true;
                  }
  
                  var compare = function (val, filtervalue) {
                      switch (comparisonoperator) {
                          case 'EQUAL':
                              return $.jqx.string.equalsIgnoreCase(val, filtervalue);
                          case 'EQUAL_CASE_SENSITIVE':
                              return $.jqx.string.equals(val, filtervalue);
                          case 'NOT_EQUAL':
                              return !$.jqx.string.equalsIgnoreCase(val, filtervalue);
                          case 'NOT_EQUAL_CASE_SENSITIVE':
                              return !$.jqx.string.equals(val, filtervalue);
                          case 'CONTAINS':
                              return $.jqx.string.containsIgnoreCase(val, filtervalue);
                          case 'CONTAINS_CASE_SENSITIVE':
                              return $.jqx.string.contains(val, filtervalue);
                          case 'DOES_NOT_CONTAIN':
                              return !$.jqx.string.containsIgnoreCase(val, filtervalue);
                          case 'DOES_NOT_CONTAIN_CASE_SENSITIVE':
                              return !$.jqx.string.contains(val, filtervalue);
                          case 'EMPTY':
                              return val == '';
                          case 'NOT_EMPTY':
                              return val != '';
                          case 'NOT_NULL':
                              return val != null;
                          case 'STARTS_WITH':
                              return $.jqx.string.startsWithIgnoreCase(val, filtervalue);
                          case 'ENDS_WITH':
                              return $.jqx.string.endsWithIgnoreCase(val, filtervalue);
                          case 'ENDS_WITH_CASE_SENSITIVE':
                              return $.jqx.string.endsWith(val, filtervalue);
                          case 'STARTS_WITH_CASE_SENSITIVE':
                              return $.jqx.string.startsWith(val, filtervalue);
                          default:
                              return false;
                      }
                  }
  
                  var filterValues = new Array();
                  if (filtervalue && filtervalue.indexOf)
                      if(filtervalue.indexOf("|") >= 0 || filtervalue.indexOf(" AND ") >= 0 || filtervalue.indexOf(" OR ") >= 0 || filtervalue.indexOf(" and ") >= 0 || filtervalue.indexOf(" or ") >= 0) {
                      var result = compare(val, filtervalue);
                      if (result) {
                          return result;
                      }
  
                      var andFilters = filtervalue.indexOf(" AND ") >= 0 ? filtervalue.split(" AND ") : new Array();
                      var orFilters = filtervalue.indexOf(" OR ") >= 0 ? filtervalue.split(" OR ") : new Array();
                      var andLowerCaseFilters = filtervalue.indexOf(" and ") >= 0 ? filtervalue.split(" and ") : new Array();
                      var orLowerCaseFilters = filtervalue.indexOf(" or ") >= 0 ? filtervalue.split(" or ") : new Array();
                      var delimiterFilters = filtervalue.indexOf("|") >= 0 ? filtervalue.split("|") : new Array();
                      if (delimiterFilters.length > 0) {
                          for (var i = 0; i < delimiterFilters.length; i++) {
                              delimiterFilters[i] = $.trim(delimiterFilters[i]);
                          }
                      }
                      var commaFilters = filtervalue.indexOf(" ") >= 0 ? filtervalue.split(" ") : new Array();
                      if (commaFilters.length > 0) {
                          for (var i = 0; i < commaFilters.length; i++) {
                              commaFilters[i] = $.trim(commaFilters[i]);
                          }
                      }
  
                      andFilters = andFilters.concat(commaFilters);
                      andFilters = andFilters.concat(andLowerCaseFilters);
                      orFilters = orFilters.concat(delimiterFilters);
                      orFilters = orFilters.concat(orLowerCaseFilters);
  
                      if (andFilters.length > 0) {
                          for (var i = 0; i < andFilters.length; i++) {
                              if (!andFilters[i].indexOf(" OR ") >= 0) {
                                  filterValues.push(andFilters[i]);
                              }
                          }
                      }
                      if (orFilters.length > 0) {
                          for (var i = 0; i < orFilters.length; i++) {
                              if (!orFilters[i].indexOf(" AND ") >= 0) {
                                  filterValues.push(orFilters[i]);
                              }
                          }
                      }
  
                      var filterresult = undefined;
                      for (var j = 0; j < filterValues.length; j++) {
                          var value = filterValues[j];
                          var result = compare(val, value);
                          var filteroperator = j < andFilters.length ? "and" : "or";
                          if (filterresult == undefined) {
                              filterresult = result;
                          }
                          else {
                              if (filteroperator == 'or') {
                                  filterresult = filterresult || result;
                              }
                              else {
                                  filterresult = filterresult && result;
                              }
                          }
                      }
                      return filterresult;
                  }
           
                  return compare(val, filtervalue);
              }
          }
  
          var booleanfilter = function (filtervalue, comparisonoperator) {
              this.filtervalue = filtervalue;
              this.comparisonoperator = comparisonoperator;
              this.type = 'booleanfilter';
              this.evaluate = function (value) {
                  var filtervalue = this.filtervalue;
                  var comparisonoperator = this.comparisonoperator;
                  if (value == null || value == undefined) {
                      if (comparisonoperator == 'NULL')
                          return true;
  
                      return false;
                  }
  
                  var val = value;
  
                  switch (comparisonoperator) {
                      case 'EQUAL':
                          return val == filtervalue || val.toString() == filtervalue.toString();
                      case 'NOT_EQUAL':
                          return val != filtervalue && val.toString() != filtervalue.toString();
                      default:
                          return false;
                  }
              }
          }
  
          var numericfilter = function (filtervalue, comparisonoperator) {
              this.filtervalue = filtervalue;
              this.comparisonoperator = comparisonoperator;
              this.type = 'numericfilter';
              this.evaluate = function (value) {
                  var filtervalue = this.filtervalue;
                  var comparisonoperator = this.comparisonoperator;
                  if (value === null || value === undefined || value === "") {
                      if (comparisonoperator == 'NOT_NULL')
                          return false;
  
                      if (comparisonoperator == 'NULL')
                          return true;
                      else {
                          switch (comparisonoperator) {
                              case 'EQUAL':
                                  return value == filtervalue;
                              case 'NOT_EQUAL':
                                  return value != filtervalue;
                          }
                          return false;
                      }
                  }
                  else {
                      if (comparisonoperator == 'NULL')
                          return false;
  
                      if (comparisonoperator == 'NOT_NULL')
                          return true;
                  }
  
                  var val = value;
  
                  try {
                      val = parseFloat(val);
                  }
                  catch (error) {
                      if (value.toString() != "")
                          return false;
                  }
  
                  var compare = function (val, filtervalue) {
                      switch (comparisonoperator) {
                          case 'EQUAL':
                              return val == filtervalue;
                          case 'NOT_EQUAL':
                              return val != filtervalue;
                          case 'GREATER_THAN':
                              return val > filtervalue;
                          case 'GREATER_THAN_OR_EQUAL':
                              return val >= filtervalue;
                          case 'LESS_THAN':
                              return val < filtervalue;
                          case 'LESS_THAN_OR_EQUAL':
                              return val <= filtervalue;
                          case 'STARTS_WITH':
                              return $.jqx.string.startsWithIgnoreCase(val.toString(), filtervalue.toString());
                          case 'ENDS_WITH':
                              return $.jqx.string.endsWithIgnoreCase(val.toString(), filtervalue.toString());
                          case 'ENDS_WITH_CASE_SENSITIVE':
                              return $.jqx.string.endsWith(val.toString(), filtervalue.toString());
                          case 'STARTS_WITH_CASE_SENSITIVE':
                              return $.jqx.string.startsWith(val.toString(), filtervalue.toString());
                          case 'CONTAINS':
                              return $.jqx.string.containsIgnoreCase(val.toString(), filtervalue.toString());
                          case 'CONTAINS_CASE_SENSITIVE':
                              return $.jqx.string.contains(val.toString(), filtervalue.toString());
                          case 'DOES_NOT_CONTAIN':
                              return !$.jqx.string.containsIgnoreCase(val.toString(), filtervalue.toString());
                          case 'DOES_NOT_CONTAIN_CASE_SENSITIVE':
                              return !$.jqx.string.contains(val.toString(), filtervalue.toString());
                          default:
                              return true;
                      }
                  }
  
                  var filterValues = new Array();
  
                  if (filtervalue && filtervalue.indexOf)
                      if(filtervalue.indexOf("|") >= 0  || filtervalue.indexOf(" AND ") >= 0 || filtervalue.indexOf(" OR ") >= 0 || filtervalue.indexOf(" and ") >= 0 || filtervalue.indexOf(" or ") >= 0) {
                      var result = compare(val, filtervalue);
                      if (result) {
                          return result;
                      }
                      filtervalue = filtervalue.toString();
                      var andFilters = filtervalue.indexOf(" AND ") >= 0 ? filtervalue.split(" AND ") : new Array();
                      var orFilters = filtervalue.indexOf(" OR ") >= 0 ? filtervalue.split(" OR ") : new Array();
                      var andLowerCaseFilters = filtervalue.indexOf(" and ") >= 0 ? filtervalue.split(" and ") : new Array();
                      var orLowerCaseFilters = filtervalue.indexOf(" or ") >= 0 ? filtervalue.split(" or ") : new Array();
                      andFilters = andFilters.concat(andLowerCaseFilters);
                      orFilters = orFilters.concat(orLowerCaseFilters);
                      var delimiterFilters = filtervalue.indexOf("|") >= 0 ? filtervalue.split("|") : new Array();
                      if (delimiterFilters.length > 0) {
                          for (var i = 0; i < delimiterFilters.length; i++) {
                              delimiterFilters[i] = $.trim(delimiterFilters[i]);
                          }
                      }
                      orFilters = orFilters.concat(delimiterFilters);
  
                      if (andFilters.length > 0) {
                          for (var i = 0; i < andFilters.length; i++) {
                              if (!andFilters[i].indexOf(" OR ") >= 0) {
                                  filterValues.push(andFilters[i]);
                              }
                          }
                      }
                      if (orFilters.length > 0) {
                          for (var i = 0; i < orFilters.length; i++) {
                              if (!orFilters[i].indexOf(" AND ") >= 0) {
                                  filterValues.push(orFilters[i]);
                              }
                          }
                      }
  
                      var filterresult = undefined;
                      for (var j = 0; j < filterValues.length; j++) {
                          var value = filterValues[j];
  
                          if (value && value.indexOf && value.indexOf("..") >= 0) {
                              var values = value.toString().split("..");
                              if (values.length == 2) {
                                  result = val >= values[0] && val <= values[1];
                              }
                          }
                          else {
                              var result = compare(val, value);
                          }
                          var filteroperator = j < andFilters.length ? "and" : "or";
                          if (filterresult == undefined) {
                              filterresult = result;
                          }
                          else {
                              if (filteroperator == 'or') {
                                  filterresult = filterresult || result;
                              }
                              else {
                                  filterresult = filterresult && result;
                              }
                          }
                      }
                      return filterresult;
                  }
                  if (filtervalue && filtervalue.indexOf && filtervalue.indexOf("..") >= 0) {
                      filterValues = filtervalue.toString().split("..");
                      if (filterValues.length == 2) {
                          return val >= filterValues[0] && val <= filterValues[1];
                      }
                  }
                  return compare(val, filtervalue);             
              }
          }
  
          var datefilter = function (filtervalue, comparisonoperator, formatstring, localization) {
              this.filtervalue = filtervalue;
              this.type = 'datefilter';
              var that = this;
              if (formatstring != undefined && localization != undefined) {
                  var parsedDate = $.jqx.dataFormat.parsedate(filtervalue, formatstring, localization);
                  if (parsedDate != null) {
                      this.filterdate = parsedDate;
                  }
                  else {
                      var result = $.jqx.dataFormat.tryparsedate(filtervalue, localization);
                      if (result != null) this.filterdate = result;
                  }
  
              }
              else {
                  var tmpvalue = new Date(filtervalue);
                  if (tmpvalue.toString() == 'NaN' || tmpvalue.toString() == "Invalid Date") {
                      this.filterdate = $.jqx.dataFormat.tryparsedate(filtervalue);
                  }
                  else {
                      this.filterdate = tmpvalue;
                  }
              }
              if (!this.filterdate) {
                  var tmpvalue = new Date(filtervalue);
                  if (tmpvalue.toString() == 'NaN' || tmpvalue.toString() == "Invalid Date") {
                      this.filterdate = $.jqx.dataFormat.tryparsedate(filtervalue);
                  }
                  else {
                      this.filterdate = tmpvalue;
                  }
              }
  
              this.comparisonoperator = comparisonoperator;
              this.evaluate = function (value) {
                  var filtervalue = this.filtervalue;
                  var comparisonoperator = this.comparisonoperator;
                  if (value == null || value == undefined || value == "") {
                      if (comparisonoperator == 'NOT_NULL')
                          return false;
  
                      if (comparisonoperator == 'NULL')
                          return true;
                      else {
                          switch (comparisonoperator) {
                              case 'EQUAL':
                                  return value == filtervalue;
                              case 'NOT_EQUAL':
                                  return value != filtervalue;
                          }
                          return false;
                      }
                  }
                  else {
                      if (comparisonoperator == 'NULL')
                          return false;
  
                      if (comparisonoperator == 'NOT_NULL')
                          return true;
                  }
  
                  var val = new Date();
                  val.setFullYear(1900, 0, 1);
                  val.setHours(12, 0, 0, 0);
                  try {
                      var tmpvalue = new Date(value);
  
                      if (tmpvalue.toString() == 'NaN' || tmpvalue.toString() == "Invalid Date") {
                          value = $.jqx.dataFormat.tryparsedate(value);
                      }
                      else {
                          value = tmpvalue;
                      }
  
                      val = value;
  
                      var compareTimePart = false;
                      if (formatstring != undefined && localization != undefined) {
                          if (formatstring.indexOf('t') >= 0 || formatstring.indexOf('T') >= 0 || formatstring.indexOf(':') >= 0 || formatstring.indexOf('f') >= 0) {
                              compareTimePart = true;
                              if (filtervalue && filtervalue.toString().indexOf(':') == -1) {
                                  var result = $.jqx.dataFormat.tryparsedate(filtervalue.toString() + ":00", localization);
                                  if (result != null) that.filterdate = result;
                              }
                          }
                      }
                      if (!compareTimePart) {
                          val.setHours(0);
                          val.setMinutes(0);
                          val.setSeconds(0);
                      }
                  }
                  catch (error) {
                      if (value.toString() != "")
                          return false;
                  }
  
                  if (that.filterdate != null) {
                      filtervalue = that.filterdate;
                  }
                  else {
                      if (filtervalue && filtervalue.indexOf) {
                          if (filtervalue.indexOf(':') != -1 || !isNaN(parseInt(filtervalue))) {
                              var tmpFilter = new Date(val);
                              tmpFilter.setHours(12, 0, 0, 0);
                              var timeStrings = filtervalue.split(':');
                              for (var i = 0; i < timeStrings.length; i++) {
                                  if (i == 0) {
                                      tmpFilter.setHours(timeStrings[i]);
                                  }
                                  if (i == 1) {
                                      tmpFilter.setMinutes(timeStrings[i]);
                                  }
                                  if (i == 2) {
                                      tmpFilter.setSeconds(timeStrings[i]);
                                  }
                              }
                              filtervalue = tmpFilter;
                          }
                      }
                  }
                  if (compareTimePart) {
                      if (filtervalue && filtervalue.setFullYear) {
                          if (val && val.getFullYear) {
                              if (formatstring.indexOf('d') == -1 && formatstring.indexOf('M') == -1 && formatstring.indexOf('y') == -1) {
                                  filtervalue.setFullYear(val.getFullYear(), val.getMonth(), val.getDate());
                              }
                          }
                      }
                  }
  
  
                  var compare = function (val, filtervalue) {
                      if (val == null) val = "";
                      switch (comparisonoperator) {
                          case 'EQUAL':
                              return val.toString() == filtervalue.toString();
                          case 'NOT_EQUAL':
                              return val.toString() != filtervalue.toString();
                          case 'GREATER_THAN':
                              return val > filtervalue;
                          case 'GREATER_THAN_OR_EQUAL':
                              return val >= filtervalue;
                          case 'LESS_THAN':
                              return val < filtervalue;
                          case 'LESS_THAN_OR_EQUAL':
                              return val <= filtervalue;
                          case 'STARTS_WITH':
                              return $.jqx.string.startsWithIgnoreCase(val.toString(), filtervalue.toString());
                          case 'ENDS_WITH':
                              return $.jqx.string.endsWithIgnoreCase(val.toString(), filtervalue.toString());
                          case 'ENDS_WITH_CASE_SENSITIVE':
                              return $.jqx.string.endsWith(val.toString(), filtervalue.toString());
                          case 'STARTS_WITH_CASE_SENSITIVE':
                              return $.jqx.string.startsWith(val.toString(), filtervalue.toString());
                          case 'CONTAINS':
                              return $.jqx.string.containsIgnoreCase(val.toString(), filtervalue.toString());
                          case 'CONTAINS_CASE_SENSITIVE':
                              return $.jqx.string.contains(val.toString(), filtervalue.toString());
                          case 'DOES_NOT_CONTAIN':
                              return !$.jqx.string.containsIgnoreCase(val.toString(), filtervalue.toString());
                          case 'DOES_NOT_CONTAIN_CASE_SENSITIVE':
                              return !$.jqx.string.contains(val.toString(), filtervalue.toString());
                          default:
                              return true;
                      }
                  }
                  var filterValues = new Array();
                  if (filtervalue && filtervalue.indexOf)
                      if (filtervalue.indexOf("|") >= 0 || filtervalue.indexOf(" AND ") >= 0 || filtervalue.indexOf(" OR ") >= 0 || filtervalue.indexOf(" and ") >= 0 || filtervalue.indexOf(" or ") >= 0) {
                      var result = compare(val, filtervalue);
                      if (result) {
                          return result;
                      }
                      var andFilters = filtervalue.indexOf(" AND ") >= 0 ? filtervalue.split(" AND ") : new Array();
                      var orFilters = filtervalue.indexOf(" OR ") >= 0 ? filtervalue.split(" OR ") : new Array();
                      var andLowerCaseFilters = filtervalue.indexOf(" and ") >= 0 ? filtervalue.split(" and ") : new Array();
                      var orLowerCaseFilters = filtervalue.indexOf(" or ") >= 0 ? filtervalue.split(" or ") : new Array();
                      andFilters = andFilters.concat(andLowerCaseFilters);
                      orFilters = orFilters.concat(orLowerCaseFilters);
                      var delimiterFilters = filtervalue.indexOf("|") >= 0 ? filtervalue.split("|") : new Array();
                      if (delimiterFilters.length > 0) {
                          for (var i = 0; i < delimiterFilters.length; i++) {
                              delimiterFilters[i] = $.trim(delimiterFilters[i]);
                          }
                      }
                      orFilters = orFilters.concat(delimiterFilters);
  
                      if (andFilters.length > 0) {
                          for (var i = 0; i < andFilters.length; i++) {
                              if (!andFilters[i].indexOf(" OR ") >= 0) {
                                  filterValues.push(andFilters[i]);
                              }
                          }
                      }
                      if (orFilters.length > 0) {
                          for (var i = 0; i < orFilters.length; i++) {
                              if (!orFilters[i].indexOf(" AND ") >= 0) {
                                  filterValues.push(orFilters[i]);
                              }
                          }
                      }
  
                      var filterresult = undefined;
                      for (var j = 0; j < filterValues.length; j++) {
                          var value = filterValues[j];
                          if (value && value.indexOf && value.indexOf("..") >= 0) {
                              var values = value.toString().split("..");
                              if (values.length == 2) {
                                  result = val >= values[0] && val <= values[1];
                              }
                          }
                          else {
                              var result = compare(val, value);
                          }
                          var filteroperator = j < andFilters.length ? "and" : "or";
                          if (filterresult == undefined) {
                              filterresult = result;
                          }
                          else {
                              if (filteroperator == 'or') {
                                  filterresult = filterresult || result;
                              }
                              else {
                                  filterresult = filterresult && result;
                              }
                          }
                      }
                      return filterresult;
                  }
                  if (filtervalue && filtervalue.indexOf && filtervalue.indexOf("..") >= 0) {
                      filterValues = filtervalue.toString().split("..");
                      if (filterValues.length == 2) {
                          return val >= filterValues[0] && val <= filterValues[1];
                      }
                  }
                  return compare(val, filtervalue);
              }
          }
  
          var filter = function (filtervalue, comparisonoperator, customfilter) {
              this.filtervalue = filtervalue;
              this.comparisonoperator = comparisonoperator;
              this.evaluate = function (value, comparisonoperator) {
                  return customfilter(this.filtervalue, value, this.comparisonoperator);
              }
          }
      }
  })(jqxBaseFramework);
  